@h-rig/runtime 0.0.6-alpha.34 → 0.0.6-alpha.36
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 +518 -459
- package/dist/bin/rig-agent.js +430 -361
- package/dist/src/control-plane/agent-wrapper.js +523 -464
- package/dist/src/control-plane/harness-main.js +544 -463
- package/dist/src/control-plane/hooks/completion-verification.js +369 -288
- package/dist/src/control-plane/hooks/inject-context.js +158 -99
- package/dist/src/control-plane/hooks/submodule-branch.js +538 -479
- package/dist/src/control-plane/hooks/task-runtime-start.js +538 -479
- package/dist/src/control-plane/materialize-task-config.js +68 -8
- package/dist/src/control-plane/native/git-ops.js +10 -0
- package/dist/src/control-plane/native/harness-cli.js +529 -448
- package/dist/src/control-plane/native/task-ops.js +408 -327
- package/dist/src/control-plane/native/validator.js +159 -100
- package/dist/src/control-plane/native/verifier.js +243 -171
- package/dist/src/control-plane/pi-sessiond/bin.js +0 -7
- package/dist/src/control-plane/pi-sessiond/server.js +0 -7
- package/dist/src/control-plane/pi-sessiond/session-service.js +0 -3
- package/dist/src/control-plane/pi-settings-materializer.js +52 -0
- package/dist/src/control-plane/plugin-host-context.js +59 -0
- package/dist/src/control-plane/runtime/index.js +469 -410
- package/dist/src/control-plane/runtime/isolation/index.js +493 -434
- package/dist/src/control-plane/runtime/isolation.js +493 -434
- package/dist/src/control-plane/runtime/queue.js +411 -352
- package/dist/src/control-plane/tasks/source-lifecycle.js +87 -28
- package/dist/src/index.js +16 -8
- package/dist/src/local-server.js +17 -8
- package/package.json +8 -8
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// packages/runtime/src/control-plane/harness-main.ts
|
|
5
|
-
import { resolve as
|
|
5
|
+
import { resolve as resolve34 } from "path";
|
|
6
6
|
|
|
7
7
|
// packages/runtime/src/control-plane/native/harness-cli.ts
|
|
8
|
-
import { existsSync as
|
|
9
|
-
import { resolve as
|
|
8
|
+
import { existsSync as existsSync31 } from "fs";
|
|
9
|
+
import { resolve as resolve31 } from "path";
|
|
10
10
|
|
|
11
11
|
// packages/runtime/src/control-plane/native/git-ops.ts
|
|
12
|
-
import { existsSync as
|
|
13
|
-
import { dirname as
|
|
12
|
+
import { existsSync as existsSync24, lstatSync, mkdirSync as mkdirSync12, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "fs";
|
|
13
|
+
import { dirname as dirname12, isAbsolute as isAbsolute2, resolve as resolve26 } from "path";
|
|
14
14
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
15
15
|
|
|
16
16
|
// packages/runtime/src/control-plane/runtime/baked-secrets.ts
|
|
@@ -279,8 +279,8 @@ function isAgentRuntimeContextPath(path) {
|
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
// packages/runtime/src/control-plane/native/task-ops.ts
|
|
282
|
-
import { appendFileSync, existsSync as
|
|
283
|
-
import { resolve as
|
|
282
|
+
import { appendFileSync, existsSync as existsSync23, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
|
|
283
|
+
import { resolve as resolve25 } from "path";
|
|
284
284
|
|
|
285
285
|
// packages/runtime/src/build-time-config.ts
|
|
286
286
|
function normalizeBuildConfig(value) {
|
|
@@ -829,6 +829,8 @@ function buildBrowserGuidanceLines(browser) {
|
|
|
829
829
|
}
|
|
830
830
|
|
|
831
831
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
832
|
+
import { existsSync as existsSync8 } from "fs";
|
|
833
|
+
import { resolve as resolvePath } from "path";
|
|
832
834
|
import { createPluginHost } from "@rig/core";
|
|
833
835
|
import { loadConfig } from "@rig/core/load-config";
|
|
834
836
|
|
|
@@ -1176,6 +1178,55 @@ async function materializeSkills(projectRoot, entries) {
|
|
|
1176
1178
|
return written;
|
|
1177
1179
|
}
|
|
1178
1180
|
|
|
1181
|
+
// packages/runtime/src/control-plane/pi-settings-materializer.ts
|
|
1182
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
1183
|
+
import { dirname as dirname6, resolve as resolve9 } from "path";
|
|
1184
|
+
var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
|
|
1185
|
+
var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
|
|
1186
|
+
function readJson(path, fallback) {
|
|
1187
|
+
if (!existsSync7(path))
|
|
1188
|
+
return fallback;
|
|
1189
|
+
try {
|
|
1190
|
+
return JSON.parse(readFileSync6(path, "utf-8"));
|
|
1191
|
+
} catch {
|
|
1192
|
+
return fallback;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
function packageKey(entry) {
|
|
1196
|
+
if (typeof entry === "string")
|
|
1197
|
+
return entry;
|
|
1198
|
+
if (entry && typeof entry === "object" && typeof entry.source === "string") {
|
|
1199
|
+
return entry.source;
|
|
1200
|
+
}
|
|
1201
|
+
return JSON.stringify(entry);
|
|
1202
|
+
}
|
|
1203
|
+
function materializePiPackages(projectRoot, declaredPackages) {
|
|
1204
|
+
const settingsPath = resolve9(projectRoot, SETTINGS_RELATIVE_PATH);
|
|
1205
|
+
const managedRecordPath = resolve9(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
|
|
1206
|
+
const settings = readJson(settingsPath, {});
|
|
1207
|
+
const previouslyManaged = new Set(readJson(managedRecordPath, []));
|
|
1208
|
+
const existing = Array.isArray(settings.packages) ? settings.packages : [];
|
|
1209
|
+
const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
|
|
1210
|
+
const operatorKeys = new Set(operatorEntries.map(packageKey));
|
|
1211
|
+
const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
|
|
1212
|
+
const nextPackages = [...operatorEntries, ...managedToAdd];
|
|
1213
|
+
if (nextPackages.length > 0 || existsSync7(settingsPath)) {
|
|
1214
|
+
const nextSettings = { ...settings };
|
|
1215
|
+
if (nextPackages.length > 0) {
|
|
1216
|
+
nextSettings.packages = nextPackages;
|
|
1217
|
+
} else {
|
|
1218
|
+
delete nextSettings.packages;
|
|
1219
|
+
}
|
|
1220
|
+
mkdirSync5(dirname6(settingsPath), { recursive: true });
|
|
1221
|
+
writeFileSync5(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
|
|
1222
|
+
`, "utf-8");
|
|
1223
|
+
}
|
|
1224
|
+
mkdirSync5(dirname6(managedRecordPath), { recursive: true });
|
|
1225
|
+
writeFileSync5(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
|
|
1226
|
+
`, "utf-8");
|
|
1227
|
+
return { settingsPath, packages: managedToAdd };
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1179
1230
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
1180
1231
|
async function buildPluginHostContext(projectRoot) {
|
|
1181
1232
|
let config;
|
|
@@ -1223,6 +1274,14 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
1223
1274
|
} catch (err) {
|
|
1224
1275
|
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
1225
1276
|
}
|
|
1277
|
+
try {
|
|
1278
|
+
const piPackages = config.runtime?.pi?.packages ?? [];
|
|
1279
|
+
if (piPackages.length > 0 || existsSync8(resolvePath(projectRoot, ".rig/state/pi-managed-packages.json"))) {
|
|
1280
|
+
materializePiPackages(projectRoot, piPackages);
|
|
1281
|
+
}
|
|
1282
|
+
} catch (err) {
|
|
1283
|
+
console.warn(`[plugin-host] Pi package materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
1284
|
+
}
|
|
1226
1285
|
return {
|
|
1227
1286
|
config,
|
|
1228
1287
|
pluginHost,
|
|
@@ -1236,12 +1295,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
1236
1295
|
|
|
1237
1296
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
1238
1297
|
import { spawnSync } from "child_process";
|
|
1239
|
-
import { existsSync as
|
|
1240
|
-
import { basename as basename3, join as join2, resolve as
|
|
1298
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync6 } from "fs";
|
|
1299
|
+
import { basename as basename3, join as join2, resolve as resolve11 } from "path";
|
|
1241
1300
|
|
|
1242
1301
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
1243
|
-
import { existsSync as
|
|
1244
|
-
import { resolve as
|
|
1302
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
1303
|
+
import { resolve as resolve10 } from "path";
|
|
1245
1304
|
|
|
1246
1305
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
1247
1306
|
async function findTaskById(reader, id) {
|
|
@@ -1264,7 +1323,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
1264
1323
|
}
|
|
1265
1324
|
}
|
|
1266
1325
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
1267
|
-
const configPath = options.configPath ??
|
|
1326
|
+
const configPath = options.configPath ?? resolve10(projectRoot, ".rig", "task-config.json");
|
|
1268
1327
|
const reader = {
|
|
1269
1328
|
async listTasks() {
|
|
1270
1329
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -1275,8 +1334,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
1275
1334
|
};
|
|
1276
1335
|
return reader;
|
|
1277
1336
|
}
|
|
1278
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
1279
|
-
if (!
|
|
1337
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve10(projectRoot, ".rig", "task-config.json")) {
|
|
1338
|
+
if (!existsSync9(configPath)) {
|
|
1280
1339
|
return [];
|
|
1281
1340
|
}
|
|
1282
1341
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -1284,7 +1343,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve9(projectRoot, "
|
|
|
1284
1343
|
}
|
|
1285
1344
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
1286
1345
|
try {
|
|
1287
|
-
const parsed = JSON.parse(
|
|
1346
|
+
const parsed = JSON.parse(readFileSync7(configPath, "utf8"));
|
|
1288
1347
|
if (isPlainRecord(parsed)) {
|
|
1289
1348
|
return parsed;
|
|
1290
1349
|
}
|
|
@@ -1368,7 +1427,7 @@ function isPlainRecord(candidate) {
|
|
|
1368
1427
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
1369
1428
|
var FILE_TASK_PATTERN = /\.(task\.)?json$/;
|
|
1370
1429
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
1371
|
-
const configPath = options.configPath ??
|
|
1430
|
+
const configPath = options.configPath ?? resolve11(projectRoot, ".rig", "task-config.json");
|
|
1372
1431
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
1373
1432
|
const spawnFn = options.spawn ?? spawnSync;
|
|
1374
1433
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -1451,10 +1510,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
1451
1510
|
return metadata;
|
|
1452
1511
|
}
|
|
1453
1512
|
function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
1454
|
-
const jsonPath =
|
|
1455
|
-
if (
|
|
1513
|
+
const jsonPath = resolve11(projectRoot, "rig.config.json");
|
|
1514
|
+
if (existsSync10(jsonPath)) {
|
|
1456
1515
|
try {
|
|
1457
|
-
const parsed = JSON.parse(
|
|
1516
|
+
const parsed = JSON.parse(readFileSync8(jsonPath, "utf8"));
|
|
1458
1517
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
1459
1518
|
const source = parsed.taskSource;
|
|
1460
1519
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -1463,12 +1522,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
|
1463
1522
|
return null;
|
|
1464
1523
|
}
|
|
1465
1524
|
}
|
|
1466
|
-
const tsPath =
|
|
1467
|
-
if (!
|
|
1525
|
+
const tsPath = resolve11(projectRoot, "rig.config.ts");
|
|
1526
|
+
if (!existsSync10(tsPath)) {
|
|
1468
1527
|
return null;
|
|
1469
1528
|
}
|
|
1470
1529
|
try {
|
|
1471
|
-
const source =
|
|
1530
|
+
const source = readFileSync8(tsPath, "utf8");
|
|
1472
1531
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
1473
1532
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
1474
1533
|
if (kind !== "files") {
|
|
@@ -1488,10 +1547,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
1488
1547
|
return isPlainRecord2(entry) ? entry : null;
|
|
1489
1548
|
}
|
|
1490
1549
|
function readRawTaskConfig(configPath) {
|
|
1491
|
-
if (!
|
|
1550
|
+
if (!existsSync10(configPath)) {
|
|
1492
1551
|
return null;
|
|
1493
1552
|
}
|
|
1494
|
-
const parsed = JSON.parse(
|
|
1553
|
+
const parsed = JSON.parse(readFileSync8(configPath, "utf8"));
|
|
1495
1554
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
1496
1555
|
}
|
|
1497
1556
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -1499,8 +1558,8 @@ function stripLegacyTaskConfigMetadata2(raw) {
|
|
|
1499
1558
|
return tasks;
|
|
1500
1559
|
}
|
|
1501
1560
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
1502
|
-
const directory =
|
|
1503
|
-
if (!
|
|
1561
|
+
const directory = resolve11(projectRoot, sourcePath);
|
|
1562
|
+
if (!existsSync10(directory)) {
|
|
1504
1563
|
return [];
|
|
1505
1564
|
}
|
|
1506
1565
|
const tasks = [];
|
|
@@ -1515,11 +1574,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
1515
1574
|
return tasks;
|
|
1516
1575
|
}
|
|
1517
1576
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
1518
|
-
const file = findFileBackedTaskFile(
|
|
1577
|
+
const file = findFileBackedTaskFile(resolve11(projectRoot, sourcePath), taskId);
|
|
1519
1578
|
if (!file) {
|
|
1520
1579
|
return null;
|
|
1521
1580
|
}
|
|
1522
|
-
const raw = JSON.parse(
|
|
1581
|
+
const raw = JSON.parse(readFileSync8(file, "utf8"));
|
|
1523
1582
|
if (!isPlainRecord2(raw)) {
|
|
1524
1583
|
return null;
|
|
1525
1584
|
}
|
|
@@ -1532,7 +1591,7 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
1532
1591
|
};
|
|
1533
1592
|
}
|
|
1534
1593
|
function findFileBackedTaskFile(directory, taskId) {
|
|
1535
|
-
if (!
|
|
1594
|
+
if (!existsSync10(directory)) {
|
|
1536
1595
|
return null;
|
|
1537
1596
|
}
|
|
1538
1597
|
for (const name of readdirSync2(directory)) {
|
|
@@ -1542,7 +1601,7 @@ function findFileBackedTaskFile(directory, taskId) {
|
|
|
1542
1601
|
try {
|
|
1543
1602
|
if (!statSync(file).isFile())
|
|
1544
1603
|
continue;
|
|
1545
|
-
const raw = JSON.parse(
|
|
1604
|
+
const raw = JSON.parse(readFileSync8(file, "utf8"));
|
|
1546
1605
|
const inferredId = basename3(file).replace(FILE_TASK_PATTERN, "");
|
|
1547
1606
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
1548
1607
|
if (id === taskId) {
|
|
@@ -1702,8 +1761,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
|
|
|
1702
1761
|
}
|
|
1703
1762
|
|
|
1704
1763
|
// packages/runtime/src/control-plane/native/task-state.ts
|
|
1705
|
-
import { existsSync as
|
|
1706
|
-
import { basename as basename6, resolve as
|
|
1764
|
+
import { existsSync as existsSync17, readFileSync as readFileSync11, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync7 } from "fs";
|
|
1765
|
+
import { basename as basename6, resolve as resolve18 } from "path";
|
|
1707
1766
|
|
|
1708
1767
|
// packages/runtime/src/control-plane/state-sync/types.ts
|
|
1709
1768
|
var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
|
|
@@ -1811,51 +1870,51 @@ function readTaskStateMetadataEnvelope(raw) {
|
|
|
1811
1870
|
};
|
|
1812
1871
|
}
|
|
1813
1872
|
// packages/runtime/src/control-plane/state-sync/read.ts
|
|
1814
|
-
import { existsSync as
|
|
1815
|
-
import { resolve as
|
|
1873
|
+
import { existsSync as existsSync16, readFileSync as readFileSync10 } from "fs";
|
|
1874
|
+
import { resolve as resolve17 } from "path";
|
|
1816
1875
|
|
|
1817
1876
|
// packages/runtime/src/control-plane/native/utils.ts
|
|
1818
|
-
import { existsSync as
|
|
1819
|
-
import { resolve as
|
|
1877
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
|
|
1878
|
+
import { resolve as resolve14 } from "path";
|
|
1820
1879
|
|
|
1821
1880
|
// packages/runtime/src/layout.ts
|
|
1822
|
-
import { existsSync as
|
|
1823
|
-
import { basename as basename4, dirname as
|
|
1881
|
+
import { existsSync as existsSync11 } from "fs";
|
|
1882
|
+
import { basename as basename4, dirname as dirname7, resolve as resolve12 } from "path";
|
|
1824
1883
|
var RIG_DEFINITION_DIRNAME = "rig";
|
|
1825
1884
|
var RIG_STATE_DIRNAME = ".rig";
|
|
1826
1885
|
var RIG_ARTIFACTS_DIRNAME = "artifacts";
|
|
1827
1886
|
function resolveMonorepoRoot(projectRoot) {
|
|
1828
|
-
const normalizedProjectRoot =
|
|
1887
|
+
const normalizedProjectRoot = resolve12(projectRoot);
|
|
1829
1888
|
const explicit = process.env.MONOREPO_ROOT?.trim();
|
|
1830
1889
|
if (explicit) {
|
|
1831
|
-
const explicitRoot =
|
|
1832
|
-
const explicitParent =
|
|
1890
|
+
const explicitRoot = resolve12(explicit);
|
|
1891
|
+
const explicitParent = dirname7(explicitRoot);
|
|
1833
1892
|
if (basename4(explicitParent) === ".worktrees") {
|
|
1834
|
-
const owner =
|
|
1835
|
-
const ownerHasGit =
|
|
1836
|
-
const ownerHasTaskConfig =
|
|
1837
|
-
const ownerHasRigConfig =
|
|
1893
|
+
const owner = dirname7(explicitParent);
|
|
1894
|
+
const ownerHasGit = existsSync11(resolve12(owner, ".git"));
|
|
1895
|
+
const ownerHasTaskConfig = existsSync11(resolve12(owner, ".rig", "task-config.json"));
|
|
1896
|
+
const ownerHasRigConfig = existsSync11(resolve12(owner, "rig.config.ts"));
|
|
1838
1897
|
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
1839
1898
|
return owner;
|
|
1840
1899
|
}
|
|
1841
1900
|
throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
|
|
1842
1901
|
}
|
|
1843
|
-
if (!
|
|
1902
|
+
if (!existsSync11(resolve12(explicitRoot, ".git"))) {
|
|
1844
1903
|
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
|
|
1845
1904
|
}
|
|
1846
|
-
const hasTaskConfig =
|
|
1847
|
-
const hasRigConfig =
|
|
1905
|
+
const hasTaskConfig = existsSync11(resolve12(explicitRoot, ".rig", "task-config.json"));
|
|
1906
|
+
const hasRigConfig = existsSync11(resolve12(explicitRoot, "rig.config.ts"));
|
|
1848
1907
|
if (!hasTaskConfig && !hasRigConfig) {
|
|
1849
1908
|
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
|
|
1850
1909
|
}
|
|
1851
1910
|
return explicitRoot;
|
|
1852
1911
|
}
|
|
1853
|
-
const projectParent =
|
|
1912
|
+
const projectParent = dirname7(normalizedProjectRoot);
|
|
1854
1913
|
if (basename4(projectParent) === ".worktrees") {
|
|
1855
|
-
const worktreeOwner =
|
|
1856
|
-
const ownerHasGit =
|
|
1857
|
-
const ownerHasTaskConfig =
|
|
1858
|
-
const ownerHasRigConfig =
|
|
1914
|
+
const worktreeOwner = dirname7(projectParent);
|
|
1915
|
+
const ownerHasGit = existsSync11(resolve12(worktreeOwner, ".git"));
|
|
1916
|
+
const ownerHasTaskConfig = existsSync11(resolve12(worktreeOwner, ".rig", "task-config.json"));
|
|
1917
|
+
const ownerHasRigConfig = existsSync11(resolve12(worktreeOwner, "rig.config.ts"));
|
|
1859
1918
|
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
1860
1919
|
return worktreeOwner;
|
|
1861
1920
|
}
|
|
@@ -1863,28 +1922,28 @@ function resolveMonorepoRoot(projectRoot) {
|
|
|
1863
1922
|
return normalizedProjectRoot;
|
|
1864
1923
|
}
|
|
1865
1924
|
function resolveRuntimeWorkspaceLayout(workspaceDir) {
|
|
1866
|
-
const root =
|
|
1867
|
-
const rigRoot =
|
|
1868
|
-
const logsDir =
|
|
1869
|
-
const stateDir =
|
|
1870
|
-
const runtimeDir =
|
|
1871
|
-
const binDir =
|
|
1925
|
+
const root = resolve12(workspaceDir);
|
|
1926
|
+
const rigRoot = resolve12(root, ".rig");
|
|
1927
|
+
const logsDir = resolve12(rigRoot, "logs");
|
|
1928
|
+
const stateDir = resolve12(rigRoot, "state");
|
|
1929
|
+
const runtimeDir = resolve12(rigRoot, "runtime");
|
|
1930
|
+
const binDir = resolve12(rigRoot, "bin");
|
|
1872
1931
|
return {
|
|
1873
1932
|
workspaceDir: root,
|
|
1874
1933
|
rigRoot,
|
|
1875
1934
|
stateDir,
|
|
1876
1935
|
logsDir,
|
|
1877
|
-
artifactsRoot:
|
|
1936
|
+
artifactsRoot: resolve12(root, RIG_ARTIFACTS_DIRNAME),
|
|
1878
1937
|
runtimeDir,
|
|
1879
|
-
homeDir:
|
|
1880
|
-
tmpDir:
|
|
1881
|
-
cacheDir:
|
|
1882
|
-
sessionDir:
|
|
1938
|
+
homeDir: resolve12(rigRoot, "home"),
|
|
1939
|
+
tmpDir: resolve12(rigRoot, "tmp"),
|
|
1940
|
+
cacheDir: resolve12(rigRoot, "cache"),
|
|
1941
|
+
sessionDir: resolve12(rigRoot, "session"),
|
|
1883
1942
|
binDir,
|
|
1884
|
-
distDir:
|
|
1885
|
-
pluginBinDir:
|
|
1886
|
-
contextPath:
|
|
1887
|
-
controlPlaneEventsFile:
|
|
1943
|
+
distDir: resolve12(rigRoot, "dist"),
|
|
1944
|
+
pluginBinDir: resolve12(binDir, "plugins"),
|
|
1945
|
+
contextPath: resolve12(rigRoot, "runtime-context.json"),
|
|
1946
|
+
controlPlaneEventsFile: resolve12(logsDir, "control-plane.events.jsonl")
|
|
1888
1947
|
};
|
|
1889
1948
|
}
|
|
1890
1949
|
function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
|
|
@@ -1892,14 +1951,14 @@ function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
|
|
|
1892
1951
|
if (!explicit) {
|
|
1893
1952
|
throw new Error("No active runtime workspace. Set RIG_TASK_WORKSPACE or provision a task runtime first.");
|
|
1894
1953
|
}
|
|
1895
|
-
return
|
|
1954
|
+
return resolve12(explicit);
|
|
1896
1955
|
}
|
|
1897
1956
|
function resolveRigLayout(projectRoot) {
|
|
1898
1957
|
const monorepoRoot = resolveMonorepoRoot(projectRoot);
|
|
1899
|
-
const definitionRoot =
|
|
1958
|
+
const definitionRoot = resolve12(projectRoot, RIG_DEFINITION_DIRNAME);
|
|
1900
1959
|
const runtimeWorkspaceRoot = resolveActiveRuntimeWorkspaceRoot(monorepoRoot);
|
|
1901
1960
|
const runtimeLayout = resolveRuntimeWorkspaceLayout(runtimeWorkspaceRoot);
|
|
1902
|
-
const policyDir =
|
|
1961
|
+
const policyDir = resolve12(definitionRoot, "policy");
|
|
1903
1962
|
return {
|
|
1904
1963
|
projectRoot,
|
|
1905
1964
|
monorepoRoot,
|
|
@@ -1907,48 +1966,48 @@ function resolveRigLayout(projectRoot) {
|
|
|
1907
1966
|
runtimeWorkspaceRoot,
|
|
1908
1967
|
stateRoot: runtimeLayout.rigRoot,
|
|
1909
1968
|
artifactsRoot: runtimeLayout.artifactsRoot,
|
|
1910
|
-
configPath:
|
|
1911
|
-
taskConfigPath:
|
|
1969
|
+
configPath: resolve12(definitionRoot, "config.sh"),
|
|
1970
|
+
taskConfigPath: resolve12(runtimeWorkspaceRoot, ".rig", "task-config.json"),
|
|
1912
1971
|
policyDir,
|
|
1913
|
-
policyFile:
|
|
1914
|
-
pluginsDir:
|
|
1915
|
-
hooksDir:
|
|
1916
|
-
toolsDir:
|
|
1917
|
-
templatesDir:
|
|
1918
|
-
validationDir:
|
|
1972
|
+
policyFile: resolve12(policyDir, "policy.json"),
|
|
1973
|
+
pluginsDir: resolve12(definitionRoot, "plugins"),
|
|
1974
|
+
hooksDir: resolve12(definitionRoot, "hooks"),
|
|
1975
|
+
toolsDir: resolve12(definitionRoot, "tools"),
|
|
1976
|
+
templatesDir: resolve12(definitionRoot, "templates"),
|
|
1977
|
+
validationDir: resolve12(definitionRoot, "validation"),
|
|
1919
1978
|
stateDir: runtimeLayout.stateDir,
|
|
1920
1979
|
logsDir: runtimeLayout.logsDir,
|
|
1921
|
-
notificationsDir:
|
|
1980
|
+
notificationsDir: resolve12(definitionRoot, "notifications"),
|
|
1922
1981
|
runtimeDir: runtimeLayout.runtimeDir,
|
|
1923
1982
|
distDir: runtimeLayout.distDir,
|
|
1924
1983
|
binDir: runtimeLayout.binDir,
|
|
1925
1984
|
pluginBinDir: runtimeLayout.pluginBinDir,
|
|
1926
|
-
keybindingsPath:
|
|
1985
|
+
keybindingsPath: resolve12(definitionRoot, "keybindings.json"),
|
|
1927
1986
|
controlPlaneEventsFile: runtimeLayout.controlPlaneEventsFile
|
|
1928
1987
|
};
|
|
1929
1988
|
}
|
|
1930
1989
|
|
|
1931
1990
|
// packages/runtime/src/control-plane/native/runtime-native.ts
|
|
1932
1991
|
import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
|
|
1933
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
1992
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync6, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync2 } from "fs";
|
|
1934
1993
|
import { tmpdir as tmpdir4 } from "os";
|
|
1935
|
-
import { dirname as
|
|
1936
|
-
var sharedNativeRuntimeOutputDir =
|
|
1937
|
-
var sharedNativeRuntimeOutputPath =
|
|
1994
|
+
import { dirname as dirname8, resolve as resolve13 } from "path";
|
|
1995
|
+
var sharedNativeRuntimeOutputDir = resolve13(tmpdir4(), "rig-native");
|
|
1996
|
+
var sharedNativeRuntimeOutputPath = resolve13(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
|
|
1938
1997
|
var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
|
|
1939
1998
|
var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
|
|
1940
1999
|
async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOutputPath, options = {}) {
|
|
1941
2000
|
if (await buildNativeRuntimeLibrary(outputPath, options)) {
|
|
1942
2001
|
return outputPath;
|
|
1943
2002
|
}
|
|
1944
|
-
return !options.force &&
|
|
2003
|
+
return !options.force && existsSync12(outputPath) ? outputPath : null;
|
|
1945
2004
|
}
|
|
1946
2005
|
async function loadNativeRuntimeLibrary() {
|
|
1947
2006
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
1948
2007
|
return null;
|
|
1949
2008
|
}
|
|
1950
2009
|
for (const candidate of nativeRuntimeLibraryCandidates()) {
|
|
1951
|
-
if (!candidate || !
|
|
2010
|
+
if (!candidate || !existsSync12(candidate)) {
|
|
1952
2011
|
continue;
|
|
1953
2012
|
}
|
|
1954
2013
|
const loaded = tryDlopenNativeRuntimeLibrary(candidate);
|
|
@@ -1964,12 +2023,12 @@ async function loadNativeRuntimeLibrary() {
|
|
|
1964
2023
|
}
|
|
1965
2024
|
function nativePackageLibraryCandidates(fromDir, names) {
|
|
1966
2025
|
const candidates = [];
|
|
1967
|
-
let cursor =
|
|
2026
|
+
let cursor = resolve13(fromDir);
|
|
1968
2027
|
for (let index = 0;index < 8; index += 1) {
|
|
1969
2028
|
for (const name of names) {
|
|
1970
|
-
candidates.push(
|
|
2029
|
+
candidates.push(resolve13(cursor, "native", `${process.platform}-${process.arch}`, name), resolve13(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve13(cursor, "native", name), resolve13(cursor, "native", "lib", name));
|
|
1971
2030
|
}
|
|
1972
|
-
const parent =
|
|
2031
|
+
const parent = dirname8(cursor);
|
|
1973
2032
|
if (parent === cursor)
|
|
1974
2033
|
break;
|
|
1975
2034
|
cursor = parent;
|
|
@@ -1978,27 +2037,27 @@ function nativePackageLibraryCandidates(fromDir, names) {
|
|
|
1978
2037
|
}
|
|
1979
2038
|
function nativeRuntimeLibraryCandidates() {
|
|
1980
2039
|
const explicit = process.env.RIG_NATIVE_RUNTIME_LIB?.trim() || "";
|
|
1981
|
-
const execDir = process.execPath?.trim() ?
|
|
2040
|
+
const execDir = process.execPath?.trim() ? dirname8(process.execPath.trim()) : "";
|
|
1982
2041
|
const platformSpecific = `runtime-native-${process.platform}-${process.arch}.${suffix}`;
|
|
1983
2042
|
return [...new Set([
|
|
1984
2043
|
explicit,
|
|
1985
2044
|
...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
|
|
1986
|
-
execDir ?
|
|
1987
|
-
execDir ?
|
|
1988
|
-
execDir ?
|
|
1989
|
-
execDir ?
|
|
1990
|
-
execDir ?
|
|
1991
|
-
execDir ?
|
|
2045
|
+
execDir ? resolve13(execDir, colocatedNativeRuntimeFileName) : "",
|
|
2046
|
+
execDir ? resolve13(execDir, platformSpecific) : "",
|
|
2047
|
+
execDir ? resolve13(execDir, "..", colocatedNativeRuntimeFileName) : "",
|
|
2048
|
+
execDir ? resolve13(execDir, "..", platformSpecific) : "",
|
|
2049
|
+
execDir ? resolve13(execDir, "lib", colocatedNativeRuntimeFileName) : "",
|
|
2050
|
+
execDir ? resolve13(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
|
|
1992
2051
|
sharedNativeRuntimeOutputPath
|
|
1993
2052
|
].filter(Boolean))];
|
|
1994
2053
|
}
|
|
1995
2054
|
function resolveNativeRuntimeSourcePath() {
|
|
1996
2055
|
const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
|
|
1997
|
-
if (explicit &&
|
|
2056
|
+
if (explicit && existsSync12(explicit)) {
|
|
1998
2057
|
return explicit;
|
|
1999
2058
|
}
|
|
2000
|
-
const bundled =
|
|
2001
|
-
return
|
|
2059
|
+
const bundled = resolve13(import.meta.dir, "../../../native/snapshot.zig");
|
|
2060
|
+
return existsSync12(bundled) ? bundled : null;
|
|
2002
2061
|
}
|
|
2003
2062
|
async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
2004
2063
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
@@ -2011,8 +2070,8 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
|
2011
2070
|
}
|
|
2012
2071
|
const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
2013
2072
|
try {
|
|
2014
|
-
|
|
2015
|
-
const needsBuild = options.force === true || !
|
|
2073
|
+
mkdirSync6(dirname8(outputPath), { recursive: true });
|
|
2074
|
+
const needsBuild = options.force === true || !existsSync12(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
|
|
2016
2075
|
if (!needsBuild) {
|
|
2017
2076
|
return true;
|
|
2018
2077
|
}
|
|
@@ -2030,7 +2089,7 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
|
2030
2089
|
stderr: "pipe"
|
|
2031
2090
|
});
|
|
2032
2091
|
const exitCode = await build.exited;
|
|
2033
|
-
if (exitCode !== 0 || !
|
|
2092
|
+
if (exitCode !== 0 || !existsSync12(tempOutputPath)) {
|
|
2034
2093
|
rmSync3(tempOutputPath, { force: true });
|
|
2035
2094
|
return false;
|
|
2036
2095
|
}
|
|
@@ -2160,11 +2219,11 @@ async function runCaptureAsync(command, cwd, env, timeoutMs) {
|
|
|
2160
2219
|
return { exitCode, stdout, stderr };
|
|
2161
2220
|
}
|
|
2162
2221
|
function readJsonFile(path, fallback) {
|
|
2163
|
-
if (!
|
|
2222
|
+
if (!existsSync13(path)) {
|
|
2164
2223
|
return fallback;
|
|
2165
2224
|
}
|
|
2166
2225
|
try {
|
|
2167
|
-
return JSON.parse(
|
|
2226
|
+
return JSON.parse(readFileSync9(path, "utf-8"));
|
|
2168
2227
|
} catch {
|
|
2169
2228
|
return fallback;
|
|
2170
2229
|
}
|
|
@@ -2178,31 +2237,31 @@ function unique(values) {
|
|
|
2178
2237
|
function resolveHarnessPaths(projectRoot) {
|
|
2179
2238
|
const hasRuntimeWorkspace = Boolean(process.env.RIG_TASK_WORKSPACE?.trim());
|
|
2180
2239
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2181
|
-
const harnessRoot =
|
|
2182
|
-
const stateRoot =
|
|
2240
|
+
const harnessRoot = resolve14(projectRoot, "rig");
|
|
2241
|
+
const stateRoot = resolve14(projectRoot, ".rig");
|
|
2183
2242
|
const layout = hasRuntimeWorkspace ? resolveRigLayout(projectRoot) : null;
|
|
2184
|
-
const stateDir = layout?.stateDir ??
|
|
2185
|
-
const logsDir = layout?.logsDir ??
|
|
2186
|
-
const artifactsDir = layout?.artifactsRoot ??
|
|
2187
|
-
const taskConfigPath = layout?.taskConfigPath ??
|
|
2188
|
-
const binDir = layout?.binDir ??
|
|
2243
|
+
const stateDir = layout?.stateDir ?? resolve14(stateRoot, "state");
|
|
2244
|
+
const logsDir = layout?.logsDir ?? resolve14(stateRoot, "logs");
|
|
2245
|
+
const artifactsDir = layout?.artifactsRoot ?? resolve14(monorepoRoot, "artifacts");
|
|
2246
|
+
const taskConfigPath = layout?.taskConfigPath ?? resolve14(monorepoRoot, ".rig", "task-config.json");
|
|
2247
|
+
const binDir = layout?.binDir ?? resolve14(stateRoot, "bin");
|
|
2189
2248
|
return {
|
|
2190
2249
|
harnessRoot,
|
|
2191
2250
|
stateDir: process.env.RIG_STATE_DIR || stateDir,
|
|
2192
2251
|
artifactsDir,
|
|
2193
2252
|
logsDir: process.env.RIG_LOGS_DIR || logsDir,
|
|
2194
2253
|
binDir,
|
|
2195
|
-
hooksDir:
|
|
2196
|
-
validationDir:
|
|
2254
|
+
hooksDir: resolve14(harnessRoot, "hooks"),
|
|
2255
|
+
validationDir: resolve14(harnessRoot, "validation"),
|
|
2197
2256
|
taskConfigPath,
|
|
2198
|
-
sessionPath: process.env.RIG_SESSION_FILE ||
|
|
2257
|
+
sessionPath: process.env.RIG_SESSION_FILE || resolve14(stateRoot, "session", "session.json"),
|
|
2199
2258
|
monorepoRoot,
|
|
2200
|
-
tsApiTestsDir: process.env.TS_API_TESTS_DIR ||
|
|
2201
|
-
taskRepoCommitsPath:
|
|
2202
|
-
baseRepoPinsPath:
|
|
2203
|
-
failedApproachesPath:
|
|
2204
|
-
agentProfilePath:
|
|
2205
|
-
reviewProfilePath:
|
|
2259
|
+
tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve14(monorepoRoot, "TSAPITests"),
|
|
2260
|
+
taskRepoCommitsPath: resolve14(stateDir, "task-repo-commits.json"),
|
|
2261
|
+
baseRepoPinsPath: resolve14(stateDir, "base-repo-pins.json"),
|
|
2262
|
+
failedApproachesPath: resolve14(stateDir, "failed_approaches.md"),
|
|
2263
|
+
agentProfilePath: resolve14(stateDir, "agent-profile.json"),
|
|
2264
|
+
reviewProfilePath: resolve14(stateDir, "review-profile.json")
|
|
2206
2265
|
};
|
|
2207
2266
|
}
|
|
2208
2267
|
function normalizeRelativeScopePath(inputPath) {
|
|
@@ -2260,34 +2319,34 @@ function monorepoSearchCandidates(inputPath) {
|
|
|
2260
2319
|
}
|
|
2261
2320
|
|
|
2262
2321
|
// packages/runtime/src/control-plane/state-sync/repo.ts
|
|
2263
|
-
import { existsSync as
|
|
2264
|
-
import { resolve as
|
|
2322
|
+
import { existsSync as existsSync15 } from "fs";
|
|
2323
|
+
import { resolve as resolve16 } from "path";
|
|
2265
2324
|
|
|
2266
2325
|
// packages/runtime/src/control-plane/repos/layout.ts
|
|
2267
|
-
import { existsSync as
|
|
2268
|
-
import { basename as basename5, dirname as
|
|
2326
|
+
import { existsSync as existsSync14 } from "fs";
|
|
2327
|
+
import { basename as basename5, dirname as dirname9, join as join3, resolve as resolve15 } from "path";
|
|
2269
2328
|
function resolveRepoStateDir(projectRoot) {
|
|
2270
|
-
const normalizedProjectRoot =
|
|
2271
|
-
const projectParent =
|
|
2329
|
+
const normalizedProjectRoot = resolve15(projectRoot);
|
|
2330
|
+
const projectParent = dirname9(normalizedProjectRoot);
|
|
2272
2331
|
if (basename5(projectParent) === ".worktrees") {
|
|
2273
|
-
const ownerRoot =
|
|
2274
|
-
const ownerHasRepoMarkers =
|
|
2332
|
+
const ownerRoot = dirname9(projectParent);
|
|
2333
|
+
const ownerHasRepoMarkers = existsSync14(resolve15(ownerRoot, ".git")) || existsSync14(resolve15(ownerRoot, ".rig", "state"));
|
|
2275
2334
|
if (ownerHasRepoMarkers) {
|
|
2276
|
-
return
|
|
2335
|
+
return resolve15(ownerRoot, ".rig", "state");
|
|
2277
2336
|
}
|
|
2278
2337
|
}
|
|
2279
|
-
return
|
|
2338
|
+
return resolve15(projectRoot, ".rig", "state");
|
|
2280
2339
|
}
|
|
2281
2340
|
function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
2282
|
-
const normalizedProjectRoot =
|
|
2341
|
+
const normalizedProjectRoot = resolve15(projectRoot);
|
|
2283
2342
|
const entry = getManagedRepoEntry(repoId);
|
|
2284
2343
|
const stateDir = resolveRepoStateDir(normalizedProjectRoot);
|
|
2285
2344
|
const metadataRelativePath = join3("repos", entry.id);
|
|
2286
|
-
const metadataRoot =
|
|
2345
|
+
const metadataRoot = resolve15(stateDir, metadataRelativePath);
|
|
2287
2346
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
2288
|
-
const runsInsideTaskWorktree = runtimeWorkspace &&
|
|
2347
|
+
const runsInsideTaskWorktree = runtimeWorkspace && resolve15(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname9(normalizedProjectRoot)) === ".worktrees";
|
|
2289
2348
|
const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
|
|
2290
|
-
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ?
|
|
2349
|
+
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve15(process.env[entry.checkoutEnvVar].trim()) : resolve15(normalizedProjectRoot, entry.alias);
|
|
2291
2350
|
return {
|
|
2292
2351
|
projectRoot: normalizedProjectRoot,
|
|
2293
2352
|
repoId: entry.id,
|
|
@@ -2295,12 +2354,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
|
2295
2354
|
defaultBranch: entry.defaultBranch,
|
|
2296
2355
|
remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
|
|
2297
2356
|
checkoutRoot,
|
|
2298
|
-
worktreesRoot:
|
|
2357
|
+
worktreesRoot: resolve15(checkoutRoot, ".worktrees"),
|
|
2299
2358
|
stateDir,
|
|
2300
2359
|
metadataRoot,
|
|
2301
2360
|
metadataRelativePath,
|
|
2302
|
-
mirrorRoot:
|
|
2303
|
-
mirrorStatePath:
|
|
2361
|
+
mirrorRoot: resolve15(metadataRoot, "mirror.git"),
|
|
2362
|
+
mirrorStatePath: resolve15(metadataRoot, "mirror-state.json"),
|
|
2304
2363
|
mirrorStateRelativePath: join3(metadataRelativePath, "mirror-state.json")
|
|
2305
2364
|
};
|
|
2306
2365
|
}
|
|
@@ -2322,7 +2381,7 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
2322
2381
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2323
2382
|
try {
|
|
2324
2383
|
const layout = resolveMonorepoRepoLayout(projectRoot);
|
|
2325
|
-
if (
|
|
2384
|
+
if (existsSync15(resolve16(layout.mirrorRoot, "HEAD"))) {
|
|
2326
2385
|
return layout.mirrorRoot;
|
|
2327
2386
|
}
|
|
2328
2387
|
} catch {}
|
|
@@ -2333,8 +2392,8 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
2333
2392
|
var DEFAULT_READ_DEPS = {
|
|
2334
2393
|
fetchRef: nativeFetchRef,
|
|
2335
2394
|
readBlobAtRef: nativeReadBlobAtRef,
|
|
2336
|
-
exists:
|
|
2337
|
-
readFile: (path) =>
|
|
2395
|
+
exists: existsSync16,
|
|
2396
|
+
readFile: (path) => readFileSync10(path, "utf8")
|
|
2338
2397
|
};
|
|
2339
2398
|
function parseIssueStatus(rawStatus) {
|
|
2340
2399
|
const normalized = normalizeTaskLifecycleStatus(rawStatus);
|
|
@@ -2415,12 +2474,12 @@ function shouldPreferLocalTrackerState(options) {
|
|
|
2415
2474
|
if (runtimeContextPath) {
|
|
2416
2475
|
return true;
|
|
2417
2476
|
}
|
|
2418
|
-
return
|
|
2477
|
+
return existsSync16(resolve17(runtimeWorkspace, ".rig", "runtime-context.json"));
|
|
2419
2478
|
}
|
|
2420
2479
|
function readLocalTrackerState(projectRoot, deps) {
|
|
2421
2480
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2422
|
-
const issuesPath =
|
|
2423
|
-
const taskStatePath =
|
|
2481
|
+
const issuesPath = resolve17(monorepoRoot, ".beads", "issues.jsonl");
|
|
2482
|
+
const taskStatePath = resolve17(monorepoRoot, ".beads", "task-state.json");
|
|
2424
2483
|
return projectSyncedTrackerSnapshot({
|
|
2425
2484
|
source: "local",
|
|
2426
2485
|
issuesBaseOid: null,
|
|
@@ -2482,7 +2541,7 @@ function readValidationDescriptions(projectRoot) {
|
|
|
2482
2541
|
return readValidationDescriptionMap(raw);
|
|
2483
2542
|
}
|
|
2484
2543
|
function readSourceValidationDescriptions(projectRoot) {
|
|
2485
|
-
const rootRaw = readJsonFile(
|
|
2544
|
+
const rootRaw = readJsonFile(resolve18(projectRoot, "rig", "task-config.json"), {});
|
|
2486
2545
|
const sourcePath = findSourceTaskConfigPath(projectRoot);
|
|
2487
2546
|
const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
|
|
2488
2547
|
const rootDescriptions = readValidationDescriptionMap(rootRaw);
|
|
@@ -2558,15 +2617,15 @@ function readValidationDescriptionsFromMeta(meta) {
|
|
|
2558
2617
|
return meta.validation_descriptions;
|
|
2559
2618
|
}
|
|
2560
2619
|
function readLocalSourceTaskStateEnvelope(projectRoot) {
|
|
2561
|
-
const taskStatePath =
|
|
2620
|
+
const taskStatePath = resolve18(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
|
|
2562
2621
|
return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
|
|
2563
2622
|
}
|
|
2564
2623
|
function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
|
|
2565
|
-
const issuesPath =
|
|
2566
|
-
if (!
|
|
2624
|
+
const issuesPath = resolve18(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
2625
|
+
if (!existsSync17(issuesPath)) {
|
|
2567
2626
|
return null;
|
|
2568
2627
|
}
|
|
2569
|
-
for (const line of
|
|
2628
|
+
for (const line of readFileSync11(issuesPath, "utf8").split(/\r?\n/)) {
|
|
2570
2629
|
const trimmed = line.trim();
|
|
2571
2630
|
if (!trimmed) {
|
|
2572
2631
|
continue;
|
|
@@ -2607,25 +2666,25 @@ function lookupTask(projectRoot, input) {
|
|
|
2607
2666
|
function artifactDirForId(projectRoot, id) {
|
|
2608
2667
|
const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
2609
2668
|
if (workspaceDir) {
|
|
2610
|
-
const worktreeArtifacts =
|
|
2611
|
-
if (
|
|
2669
|
+
const worktreeArtifacts = resolve18(workspaceDir, "artifacts", id);
|
|
2670
|
+
if (existsSync17(worktreeArtifacts) || existsSync17(resolve18(workspaceDir, "artifacts"))) {
|
|
2612
2671
|
return worktreeArtifacts;
|
|
2613
2672
|
}
|
|
2614
2673
|
}
|
|
2615
2674
|
try {
|
|
2616
2675
|
const paths = resolveHarnessPaths(projectRoot);
|
|
2617
|
-
return
|
|
2676
|
+
return resolve18(paths.artifactsDir, id);
|
|
2618
2677
|
} catch {
|
|
2619
|
-
return
|
|
2678
|
+
return resolve18(resolveMonorepoRoot2(projectRoot), "artifacts", id);
|
|
2620
2679
|
}
|
|
2621
2680
|
}
|
|
2622
2681
|
function resolveTaskConfigPath(projectRoot) {
|
|
2623
2682
|
const paths = resolveHarnessPaths(projectRoot);
|
|
2624
|
-
if (
|
|
2683
|
+
if (existsSync17(paths.taskConfigPath)) {
|
|
2625
2684
|
return paths.taskConfigPath;
|
|
2626
2685
|
}
|
|
2627
2686
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
2628
|
-
if (
|
|
2687
|
+
if (existsSync17(candidate)) {
|
|
2629
2688
|
return candidate;
|
|
2630
2689
|
}
|
|
2631
2690
|
}
|
|
@@ -2633,7 +2692,7 @@ function resolveTaskConfigPath(projectRoot) {
|
|
|
2633
2692
|
}
|
|
2634
2693
|
function findSourceTaskConfigPath(projectRoot) {
|
|
2635
2694
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
2636
|
-
if (
|
|
2695
|
+
if (existsSync17(candidate)) {
|
|
2637
2696
|
return candidate;
|
|
2638
2697
|
}
|
|
2639
2698
|
}
|
|
@@ -2646,7 +2705,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
|
|
|
2646
2705
|
const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
|
|
2647
2706
|
if (sourcePath && synced.updated) {
|
|
2648
2707
|
try {
|
|
2649
|
-
|
|
2708
|
+
writeFileSync7(sourcePath, `${JSON.stringify(synced.config, null, 2)}
|
|
2650
2709
|
`, "utf-8");
|
|
2651
2710
|
} catch {}
|
|
2652
2711
|
}
|
|
@@ -2698,12 +2757,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
|
|
|
2698
2757
|
return !candidate.role;
|
|
2699
2758
|
}
|
|
2700
2759
|
function readSourceIssueRecords(projectRoot) {
|
|
2701
|
-
const issuesPath =
|
|
2702
|
-
if (!
|
|
2760
|
+
const issuesPath = resolve18(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
2761
|
+
if (!existsSync17(issuesPath)) {
|
|
2703
2762
|
return [];
|
|
2704
2763
|
}
|
|
2705
2764
|
const records = [];
|
|
2706
|
-
for (const line of
|
|
2765
|
+
for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
2707
2766
|
const trimmed = line.trim();
|
|
2708
2767
|
if (!trimmed) {
|
|
2709
2768
|
continue;
|
|
@@ -2759,19 +2818,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
|
|
|
2759
2818
|
if (!sourcePath) {
|
|
2760
2819
|
return {};
|
|
2761
2820
|
}
|
|
2762
|
-
const directory =
|
|
2763
|
-
if (!
|
|
2821
|
+
const directory = resolve18(projectRoot, sourcePath);
|
|
2822
|
+
if (!existsSync17(directory)) {
|
|
2764
2823
|
return {};
|
|
2765
2824
|
}
|
|
2766
2825
|
const config = {};
|
|
2767
2826
|
for (const name of readdirSync3(directory)) {
|
|
2768
2827
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
2769
2828
|
continue;
|
|
2770
|
-
const file =
|
|
2829
|
+
const file = resolve18(directory, name);
|
|
2771
2830
|
try {
|
|
2772
2831
|
if (!statSync3(file).isFile())
|
|
2773
2832
|
continue;
|
|
2774
|
-
const raw = JSON.parse(
|
|
2833
|
+
const raw = JSON.parse(readFileSync11(file, "utf8"));
|
|
2775
2834
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
2776
2835
|
continue;
|
|
2777
2836
|
const record = raw;
|
|
@@ -2813,10 +2872,10 @@ function firstStringList2(...candidates) {
|
|
|
2813
2872
|
return [];
|
|
2814
2873
|
}
|
|
2815
2874
|
function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
2816
|
-
const jsonPath =
|
|
2817
|
-
if (
|
|
2875
|
+
const jsonPath = resolve18(projectRoot, "rig.config.json");
|
|
2876
|
+
if (existsSync17(jsonPath)) {
|
|
2818
2877
|
try {
|
|
2819
|
-
const parsed = JSON.parse(
|
|
2878
|
+
const parsed = JSON.parse(readFileSync11(jsonPath, "utf8"));
|
|
2820
2879
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2821
2880
|
const taskSource = parsed.taskSource;
|
|
2822
2881
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -2828,12 +2887,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
2828
2887
|
return null;
|
|
2829
2888
|
}
|
|
2830
2889
|
}
|
|
2831
|
-
const tsPath =
|
|
2832
|
-
if (!
|
|
2890
|
+
const tsPath = resolve18(projectRoot, "rig.config.ts");
|
|
2891
|
+
if (!existsSync17(tsPath)) {
|
|
2833
2892
|
return null;
|
|
2834
2893
|
}
|
|
2835
2894
|
try {
|
|
2836
|
-
const source =
|
|
2895
|
+
const source = readFileSync11(tsPath, "utf8");
|
|
2837
2896
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
2838
2897
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
2839
2898
|
if (kind !== "files") {
|
|
@@ -2847,23 +2906,23 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
2847
2906
|
function sourceTaskConfigCandidates(projectRoot) {
|
|
2848
2907
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
2849
2908
|
return [
|
|
2850
|
-
runtimeContext?.monorepoMainRoot ?
|
|
2851
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
2852
|
-
|
|
2909
|
+
runtimeContext?.monorepoMainRoot ? resolve18(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
2910
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve18(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
2911
|
+
resolve18(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
|
|
2853
2912
|
].filter(Boolean);
|
|
2854
2913
|
}
|
|
2855
2914
|
|
|
2856
2915
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
2857
|
-
import { existsSync as
|
|
2858
|
-
import { resolve as
|
|
2916
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
2917
|
+
import { resolve as resolve23 } from "path";
|
|
2859
2918
|
|
|
2860
2919
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
2861
|
-
import { existsSync as
|
|
2862
|
-
import { dirname as
|
|
2920
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync8, rmSync as rmSync5, statSync as statSync4 } from "fs";
|
|
2921
|
+
import { dirname as dirname11, resolve as resolve22 } from "path";
|
|
2863
2922
|
|
|
2864
2923
|
// packages/runtime/src/binary-run.ts
|
|
2865
|
-
import { chmodSync as chmodSync2, cpSync, existsSync as
|
|
2866
|
-
import { basename as basename7, dirname as
|
|
2924
|
+
import { chmodSync as chmodSync2, cpSync, existsSync as existsSync18, mkdirSync as mkdirSync7, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
2925
|
+
import { basename as basename7, dirname as dirname10, resolve as resolve19 } from "path";
|
|
2867
2926
|
import { fileURLToPath } from "url";
|
|
2868
2927
|
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
2869
2928
|
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
@@ -2889,9 +2948,9 @@ async function buildRuntimeBinary(options) {
|
|
|
2889
2948
|
});
|
|
2890
2949
|
}
|
|
2891
2950
|
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
2892
|
-
const tempBuildDir =
|
|
2893
|
-
const tempOutputPath =
|
|
2894
|
-
|
|
2951
|
+
const tempBuildDir = resolve19(dirname10(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
2952
|
+
const tempOutputPath = resolve19(tempBuildDir, basename7(options.outputPath));
|
|
2953
|
+
mkdirSync7(tempBuildDir, { recursive: true });
|
|
2895
2954
|
await withTemporaryEnv({
|
|
2896
2955
|
...options.env,
|
|
2897
2956
|
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
@@ -2916,7 +2975,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
2916
2975
|
`);
|
|
2917
2976
|
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
2918
2977
|
}
|
|
2919
|
-
if (!
|
|
2978
|
+
if (!existsSync18(tempOutputPath)) {
|
|
2920
2979
|
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
2921
2980
|
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
2922
2981
|
}
|
|
@@ -2948,8 +3007,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
|
|
|
2948
3007
|
function resolveRuntimeBinaryBuildOptions(options) {
|
|
2949
3008
|
return {
|
|
2950
3009
|
...options,
|
|
2951
|
-
entrypoint:
|
|
2952
|
-
outputPath:
|
|
3010
|
+
entrypoint: resolve19(options.cwd, options.sourcePath),
|
|
3011
|
+
outputPath: resolve19(options.outputPath)
|
|
2953
3012
|
};
|
|
2954
3013
|
}
|
|
2955
3014
|
function shouldUseRuntimeBinaryBuildWorker() {
|
|
@@ -2963,7 +3022,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
|
|
|
2963
3022
|
}
|
|
2964
3023
|
async function buildRuntimeBinaryViaWorker(options) {
|
|
2965
3024
|
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
2966
|
-
if (!workerSourcePath || !
|
|
3025
|
+
if (!workerSourcePath || !existsSync18(workerSourcePath)) {
|
|
2967
3026
|
await buildRuntimeBinaryInProcess(options, {
|
|
2968
3027
|
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
2969
3028
|
buildKey: createRuntimeBinaryBuildKey({
|
|
@@ -3000,7 +3059,7 @@ async function buildRuntimeBinaryViaWorker(options) {
|
|
|
3000
3059
|
}
|
|
3001
3060
|
}
|
|
3002
3061
|
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
3003
|
-
return
|
|
3062
|
+
return resolve19(dirname10(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
3004
3063
|
}
|
|
3005
3064
|
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
3006
3065
|
const envRoots = [
|
|
@@ -3009,13 +3068,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
|
3009
3068
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
3010
3069
|
].filter(Boolean);
|
|
3011
3070
|
for (const root of envRoots) {
|
|
3012
|
-
const candidate =
|
|
3013
|
-
if (
|
|
3071
|
+
const candidate = resolve19(root, "packages/runtime/src/binary-build-worker.ts");
|
|
3072
|
+
if (existsSync18(candidate)) {
|
|
3014
3073
|
return candidate;
|
|
3015
3074
|
}
|
|
3016
3075
|
}
|
|
3017
|
-
const localCandidate =
|
|
3018
|
-
return
|
|
3076
|
+
const localCandidate = resolve19(import.meta.dir, "binary-build-worker.ts");
|
|
3077
|
+
return existsSync18(localCandidate) ? localCandidate : null;
|
|
3019
3078
|
}
|
|
3020
3079
|
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
3021
3080
|
const bunPath = Bun.which("bun");
|
|
@@ -3051,7 +3110,7 @@ function createRuntimeBinaryBuildKey(input) {
|
|
|
3051
3110
|
});
|
|
3052
3111
|
}
|
|
3053
3112
|
async function isRuntimeBinaryBuildFresh(input) {
|
|
3054
|
-
if (!
|
|
3113
|
+
if (!existsSync18(input.outputPath) || !existsSync18(input.manifestPath)) {
|
|
3055
3114
|
return false;
|
|
3056
3115
|
}
|
|
3057
3116
|
let manifest = null;
|
|
@@ -3064,7 +3123,7 @@ async function isRuntimeBinaryBuildFresh(input) {
|
|
|
3064
3123
|
return false;
|
|
3065
3124
|
}
|
|
3066
3125
|
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
3067
|
-
if (!
|
|
3126
|
+
if (!existsSync18(filePath)) {
|
|
3068
3127
|
return false;
|
|
3069
3128
|
}
|
|
3070
3129
|
if (await sha256File(filePath) !== expectedDigest) {
|
|
@@ -3077,7 +3136,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
|
|
|
3077
3136
|
const inputs = {};
|
|
3078
3137
|
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
3079
3138
|
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
3080
|
-
if (!normalized || !
|
|
3139
|
+
if (!normalized || !existsSync18(normalized)) {
|
|
3081
3140
|
continue;
|
|
3082
3141
|
}
|
|
3083
3142
|
inputs[normalized] = await sha256File(normalized);
|
|
@@ -3100,7 +3159,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
|
|
|
3100
3159
|
if (inputPath.startsWith("<")) {
|
|
3101
3160
|
return null;
|
|
3102
3161
|
}
|
|
3103
|
-
return
|
|
3162
|
+
return resolve19(cwd, inputPath);
|
|
3104
3163
|
}
|
|
3105
3164
|
async function sha256File(path) {
|
|
3106
3165
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
@@ -3116,8 +3175,8 @@ function sortRecord(value) {
|
|
|
3116
3175
|
async function runSerializedRuntimeBinaryBuild(action) {
|
|
3117
3176
|
const previous = runtimeBinaryBuildQueue;
|
|
3118
3177
|
let release;
|
|
3119
|
-
runtimeBinaryBuildQueue = new Promise((
|
|
3120
|
-
release =
|
|
3178
|
+
runtimeBinaryBuildQueue = new Promise((resolve20) => {
|
|
3179
|
+
release = resolve20;
|
|
3121
3180
|
});
|
|
3122
3181
|
await previous;
|
|
3123
3182
|
try {
|
|
@@ -3162,11 +3221,11 @@ async function withTemporaryCwd(cwd, action) {
|
|
|
3162
3221
|
}
|
|
3163
3222
|
|
|
3164
3223
|
// packages/runtime/src/control-plane/runtime/provisioning-env.ts
|
|
3165
|
-
import { delimiter, resolve as
|
|
3224
|
+
import { delimiter, resolve as resolve21 } from "path";
|
|
3166
3225
|
|
|
3167
3226
|
// packages/runtime/src/control-plane/runtime/runtime-paths.ts
|
|
3168
|
-
import { existsSync as
|
|
3169
|
-
import { resolve as
|
|
3227
|
+
import { existsSync as existsSync19, readdirSync as readdirSync4, realpathSync } from "fs";
|
|
3228
|
+
import { resolve as resolve20 } from "path";
|
|
3170
3229
|
|
|
3171
3230
|
// packages/runtime/src/control-plane/runtime/sandbox/utils.ts
|
|
3172
3231
|
function uniq(values) {
|
|
@@ -3184,7 +3243,7 @@ function resolveBunBinaryPath() {
|
|
|
3184
3243
|
}
|
|
3185
3244
|
const home = process.env.HOME?.trim();
|
|
3186
3245
|
const fallbackCandidates = [
|
|
3187
|
-
home ?
|
|
3246
|
+
home ? resolve20(home, ".bun/bin/bun") : "",
|
|
3188
3247
|
"/opt/homebrew/bin/bun",
|
|
3189
3248
|
"/usr/local/bin/bun",
|
|
3190
3249
|
"/usr/bin/bun"
|
|
@@ -3212,8 +3271,8 @@ function resolveClaudeBinaryPath() {
|
|
|
3212
3271
|
}
|
|
3213
3272
|
const home = process.env.HOME?.trim();
|
|
3214
3273
|
const fallbackCandidates = [
|
|
3215
|
-
home ?
|
|
3216
|
-
home ?
|
|
3274
|
+
home ? resolve20(home, ".local/bin/claude") : "",
|
|
3275
|
+
home ? resolve20(home, ".local/share/claude/local/claude") : "",
|
|
3217
3276
|
"/opt/homebrew/bin/claude",
|
|
3218
3277
|
"/usr/local/bin/claude",
|
|
3219
3278
|
"/usr/bin/claude"
|
|
@@ -3227,51 +3286,51 @@ function resolveClaudeBinaryPath() {
|
|
|
3227
3286
|
throw new Error("claude not found in PATH");
|
|
3228
3287
|
}
|
|
3229
3288
|
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
3230
|
-
return
|
|
3289
|
+
return resolve20(bunBinaryPath, "../..");
|
|
3231
3290
|
}
|
|
3232
3291
|
function resolveClaudeInstallDir() {
|
|
3233
3292
|
const realPath = resolveClaudeBinaryPath();
|
|
3234
|
-
return
|
|
3293
|
+
return resolve20(realPath, "..");
|
|
3235
3294
|
}
|
|
3236
3295
|
function resolveNodeInstallDir() {
|
|
3237
3296
|
const preferredNode = resolvePreferredNodeBinary();
|
|
3238
3297
|
if (!preferredNode)
|
|
3239
3298
|
return null;
|
|
3240
3299
|
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
3241
|
-
if (explicitNode &&
|
|
3242
|
-
return preferredNode.endsWith("/bin/node") ?
|
|
3300
|
+
if (explicitNode && resolve20(explicitNode) === resolve20(preferredNode)) {
|
|
3301
|
+
return preferredNode.endsWith("/bin/node") ? resolve20(preferredNode, "../..") : resolve20(preferredNode, "..");
|
|
3243
3302
|
}
|
|
3244
3303
|
try {
|
|
3245
3304
|
const realPath = realpathSync(preferredNode);
|
|
3246
3305
|
if (realPath.endsWith("/bin/node")) {
|
|
3247
|
-
return
|
|
3306
|
+
return resolve20(realPath, "../..");
|
|
3248
3307
|
}
|
|
3249
|
-
return
|
|
3308
|
+
return resolve20(realPath, "..");
|
|
3250
3309
|
} catch {
|
|
3251
|
-
return
|
|
3310
|
+
return resolve20(preferredNode, "..");
|
|
3252
3311
|
}
|
|
3253
3312
|
}
|
|
3254
3313
|
function resolvePreferredNodeBinary() {
|
|
3255
3314
|
const candidates = [];
|
|
3256
3315
|
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
3257
3316
|
if (envNode) {
|
|
3258
|
-
const explicit =
|
|
3259
|
-
if (
|
|
3317
|
+
const explicit = resolve20(envNode);
|
|
3318
|
+
if (existsSync19(explicit)) {
|
|
3260
3319
|
return explicit;
|
|
3261
3320
|
}
|
|
3262
3321
|
}
|
|
3263
3322
|
const nvmBin = process.env.NVM_BIN?.trim();
|
|
3264
3323
|
if (nvmBin) {
|
|
3265
|
-
candidates.push(
|
|
3324
|
+
candidates.push(resolve20(nvmBin, "node"));
|
|
3266
3325
|
}
|
|
3267
3326
|
const home = process.env.HOME?.trim();
|
|
3268
3327
|
if (home) {
|
|
3269
|
-
const nvmVersionsDir =
|
|
3270
|
-
if (
|
|
3328
|
+
const nvmVersionsDir = resolve20(home, ".nvm/versions/node");
|
|
3329
|
+
if (existsSync19(nvmVersionsDir)) {
|
|
3271
3330
|
try {
|
|
3272
3331
|
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/, "")));
|
|
3273
3332
|
for (const versionDir of versionDirs) {
|
|
3274
|
-
candidates.push(
|
|
3333
|
+
candidates.push(resolve20(nvmVersionsDir, versionDir, "bin/node"));
|
|
3275
3334
|
}
|
|
3276
3335
|
} catch {}
|
|
3277
3336
|
}
|
|
@@ -3280,8 +3339,8 @@ function resolvePreferredNodeBinary() {
|
|
|
3280
3339
|
if (whichNode) {
|
|
3281
3340
|
candidates.push(whichNode);
|
|
3282
3341
|
}
|
|
3283
|
-
const deduped = uniq(candidates.map((candidate) =>
|
|
3284
|
-
const existing = deduped.filter((candidate) =>
|
|
3342
|
+
const deduped = uniq(candidates.map((candidate) => resolve20(candidate)));
|
|
3343
|
+
const existing = deduped.filter((candidate) => existsSync19(candidate));
|
|
3285
3344
|
if (existing.length === 0) {
|
|
3286
3345
|
return null;
|
|
3287
3346
|
}
|
|
@@ -3295,7 +3354,7 @@ function resolvePreferredNodeBinary() {
|
|
|
3295
3354
|
return existing[0] ?? null;
|
|
3296
3355
|
}
|
|
3297
3356
|
function inferNodeMajor(nodeBinaryPath) {
|
|
3298
|
-
const normalized =
|
|
3357
|
+
const normalized = resolve20(nodeBinaryPath).replace(/\\/g, "/");
|
|
3299
3358
|
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
3300
3359
|
if (!match) {
|
|
3301
3360
|
return null;
|
|
@@ -3307,8 +3366,8 @@ function normalizeExecutablePath(candidate) {
|
|
|
3307
3366
|
if (!candidate) {
|
|
3308
3367
|
return "";
|
|
3309
3368
|
}
|
|
3310
|
-
const normalized =
|
|
3311
|
-
if (!
|
|
3369
|
+
const normalized = resolve20(candidate);
|
|
3370
|
+
if (!existsSync19(normalized)) {
|
|
3312
3371
|
return "";
|
|
3313
3372
|
}
|
|
3314
3373
|
try {
|
|
@@ -3318,7 +3377,7 @@ function normalizeExecutablePath(candidate) {
|
|
|
3318
3377
|
}
|
|
3319
3378
|
}
|
|
3320
3379
|
function looksLikeRuntimeGateway(candidate) {
|
|
3321
|
-
const normalized =
|
|
3380
|
+
const normalized = resolve20(candidate).replace(/\\/g, "/");
|
|
3322
3381
|
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
3323
3382
|
}
|
|
3324
3383
|
|
|
@@ -3339,7 +3398,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3339
3398
|
try {
|
|
3340
3399
|
return resolveClaudeInstallDir();
|
|
3341
3400
|
} catch {
|
|
3342
|
-
return
|
|
3401
|
+
return resolve21(claudeBinary, "..");
|
|
3343
3402
|
}
|
|
3344
3403
|
})() : "";
|
|
3345
3404
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -3349,8 +3408,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3349
3408
|
`${bunDir}/bin`,
|
|
3350
3409
|
claudeDir,
|
|
3351
3410
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
3352
|
-
realHome ?
|
|
3353
|
-
realHome ?
|
|
3411
|
+
realHome ? resolve21(realHome, ".local/bin") : "",
|
|
3412
|
+
realHome ? resolve21(realHome, ".cargo/bin") : "",
|
|
3354
3413
|
...inheritedPath,
|
|
3355
3414
|
"/usr/local/bin",
|
|
3356
3415
|
"/usr/local/sbin",
|
|
@@ -3381,9 +3440,9 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3381
3440
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
3382
3441
|
function resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext) {
|
|
3383
3442
|
if (runtimeContext) {
|
|
3384
|
-
return
|
|
3443
|
+
return resolve22(runtimeContext.binDir, "validators", binaryName);
|
|
3385
3444
|
}
|
|
3386
|
-
return
|
|
3445
|
+
return resolve22(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
|
|
3387
3446
|
}
|
|
3388
3447
|
async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
3389
3448
|
const match = checkId.match(/^([a-z][\w-]*):([a-z][\w-]*)$/);
|
|
@@ -3398,19 +3457,19 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
3398
3457
|
const binaryName = `${category}-${check}`;
|
|
3399
3458
|
const binaryPath = resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
3400
3459
|
const hostProjectRoot = runtimeContext?.hostProjectRoot?.trim() || projectRoot;
|
|
3401
|
-
const sourcePath =
|
|
3402
|
-
if (!
|
|
3460
|
+
const sourcePath = resolve22(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
|
|
3461
|
+
if (!existsSync20(sourcePath)) {
|
|
3403
3462
|
return null;
|
|
3404
3463
|
}
|
|
3405
3464
|
const sourceMtime = statSync4(sourcePath).mtimeMs;
|
|
3406
|
-
const binaryExists =
|
|
3465
|
+
const binaryExists = existsSync20(binaryPath);
|
|
3407
3466
|
const binaryMtime = binaryExists ? statSync4(binaryPath).mtimeMs : 0;
|
|
3408
3467
|
if (!binaryExists || sourceMtime > binaryMtime) {
|
|
3409
3468
|
if (binaryExists) {
|
|
3410
3469
|
rmSync5(binaryPath, { force: true });
|
|
3411
3470
|
rmSync5(`${binaryPath}.build-manifest.json`, { force: true });
|
|
3412
3471
|
}
|
|
3413
|
-
|
|
3472
|
+
mkdirSync8(dirname11(binaryPath), { recursive: true });
|
|
3414
3473
|
await buildRuntimeBinary({
|
|
3415
3474
|
sourcePath: `packages/runtime/src/control-plane/validators/${category}/${check}.ts`,
|
|
3416
3475
|
outputPath: binaryPath,
|
|
@@ -3419,7 +3478,7 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
3419
3478
|
env: runtimeProvisioningEnv()
|
|
3420
3479
|
});
|
|
3421
3480
|
}
|
|
3422
|
-
return
|
|
3481
|
+
return existsSync20(binaryPath) ? binaryPath : null;
|
|
3423
3482
|
}
|
|
3424
3483
|
|
|
3425
3484
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
@@ -3456,20 +3515,20 @@ async function readTaskSourceValidation(projectRoot, taskId) {
|
|
|
3456
3515
|
function resolveValidationPaths(projectRoot, taskId, runtimeContext) {
|
|
3457
3516
|
if (runtimeContext) {
|
|
3458
3517
|
return {
|
|
3459
|
-
taskLogDir:
|
|
3460
|
-
artifactDir:
|
|
3518
|
+
taskLogDir: resolve23(runtimeContext.logsDir, taskId),
|
|
3519
|
+
artifactDir: resolve23(runtimeContext.workspaceDir, "artifacts", taskId)
|
|
3461
3520
|
};
|
|
3462
3521
|
}
|
|
3463
3522
|
const paths = resolveHarnessPaths(projectRoot);
|
|
3464
3523
|
return {
|
|
3465
|
-
taskLogDir:
|
|
3466
|
-
artifactDir:
|
|
3524
|
+
taskLogDir: resolve23(paths.logsDir, taskId),
|
|
3525
|
+
artifactDir: resolve23(paths.artifactsDir, taskId)
|
|
3467
3526
|
};
|
|
3468
3527
|
}
|
|
3469
3528
|
async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext) {
|
|
3470
3529
|
const binaryName = checkId.replace(":", "-");
|
|
3471
3530
|
const binaryPath = await ensureValidatorBinary(projectRoot, checkId, runtimeContext) ?? resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
3472
|
-
if (!
|
|
3531
|
+
if (!existsSync21(binaryPath)) {
|
|
3473
3532
|
return {
|
|
3474
3533
|
result: {
|
|
3475
3534
|
id: checkId,
|
|
@@ -3480,7 +3539,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
3480
3539
|
};
|
|
3481
3540
|
}
|
|
3482
3541
|
const validatorCwd = runtimeContext?.workspaceDir || resolveMonorepoRoot(projectRoot);
|
|
3483
|
-
const runtimeShellPath = runtimeContext ?
|
|
3542
|
+
const runtimeShellPath = runtimeContext ? resolve23(runtimeContext.binDir, "rig-shell") : "";
|
|
3484
3543
|
const monorepoMainRoot = runtimeContext?.monorepoMainRoot || process.env.MONOREPO_MAIN_ROOT?.trim() || resolveMonorepoRoot(projectRoot);
|
|
3485
3544
|
const validatorEnv = {
|
|
3486
3545
|
PROJECT_RIG_ROOT: runtimeContext?.hostProjectRoot || projectRoot,
|
|
@@ -3495,7 +3554,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
3495
3554
|
validatorEnv.RIG_LOGS_DIR = runtimeContext.logsDir;
|
|
3496
3555
|
validatorEnv.RIG_RUNTIME_BIN_DIR = runtimeContext.binDir;
|
|
3497
3556
|
}
|
|
3498
|
-
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath &&
|
|
3557
|
+
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync21(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
|
|
3499
3558
|
try {
|
|
3500
3559
|
const result = JSON.parse(stdout.trim());
|
|
3501
3560
|
return { result, exitCode };
|
|
@@ -3535,8 +3594,8 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3535
3594
|
const configuredValidation = stringArray(taskConfig[taskId]?.validation);
|
|
3536
3595
|
const commands = resolvedContext?.validation?.length ? resolvedContext.validation : configuredValidation.length > 0 ? configuredValidation : sourceValidation.validation;
|
|
3537
3596
|
const { taskLogDir, artifactDir } = resolveValidationPaths(projectRoot, taskId, resolvedContext);
|
|
3538
|
-
|
|
3539
|
-
|
|
3597
|
+
mkdirSync9(taskLogDir, { recursive: true });
|
|
3598
|
+
mkdirSync9(artifactDir, { recursive: true });
|
|
3540
3599
|
if (commands.length === 0) {
|
|
3541
3600
|
const skipped = {
|
|
3542
3601
|
status: "skipped",
|
|
@@ -3545,7 +3604,7 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3545
3604
|
failed: 0,
|
|
3546
3605
|
categories: []
|
|
3547
3606
|
};
|
|
3548
|
-
|
|
3607
|
+
writeFileSync9(resolve23(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
|
|
3549
3608
|
`, "utf-8");
|
|
3550
3609
|
return skipped;
|
|
3551
3610
|
}
|
|
@@ -3580,18 +3639,18 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3580
3639
|
exit_code: 2,
|
|
3581
3640
|
duration_seconds: 0
|
|
3582
3641
|
});
|
|
3583
|
-
const logFile2 =
|
|
3584
|
-
|
|
3585
|
-
|
|
3642
|
+
const logFile2 = resolve23(taskLogDir, `invalid-entry-validation.log`);
|
|
3643
|
+
mkdirSync9(taskLogDir, { recursive: true });
|
|
3644
|
+
writeFileSync9(logFile2, `=== ${nowIso()} :: ${cmd} ===
|
|
3586
3645
|
Invalid validation entry: not a check-ID. All entries must use format "category:check-name".
|
|
3587
3646
|
`, "utf-8");
|
|
3588
3647
|
continue;
|
|
3589
3648
|
}
|
|
3590
3649
|
const { result, exitCode } = await dispatchValidator(cmd, effectiveRegistry, validatorCtx, (id) => runValidatorBinary(projectRoot, taskId, id, resolvedContext));
|
|
3591
3650
|
const durationSeconds = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
|
|
3592
|
-
const logFile =
|
|
3593
|
-
|
|
3594
|
-
|
|
3651
|
+
const logFile = resolve23(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
|
|
3652
|
+
mkdirSync9(taskLogDir, { recursive: true });
|
|
3653
|
+
writeFileSync9(logFile, `=== ${nowIso()} :: ${cmd} ===
|
|
3595
3654
|
${JSON.stringify(result, null, 2)}
|
|
3596
3655
|
`, "utf-8");
|
|
3597
3656
|
if (result.passed) {
|
|
@@ -3613,15 +3672,15 @@ ${JSON.stringify(result, null, 2)}
|
|
|
3613
3672
|
failed,
|
|
3614
3673
|
categories
|
|
3615
3674
|
};
|
|
3616
|
-
|
|
3617
|
-
|
|
3675
|
+
mkdirSync9(artifactDir, { recursive: true });
|
|
3676
|
+
writeFileSync9(resolve23(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
|
|
3618
3677
|
`, "utf-8");
|
|
3619
3678
|
return summary;
|
|
3620
3679
|
}
|
|
3621
3680
|
|
|
3622
3681
|
// packages/runtime/src/control-plane/native/verifier.ts
|
|
3623
|
-
import { existsSync as
|
|
3624
|
-
import { resolve as
|
|
3682
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
3683
|
+
import { resolve as resolve24 } from "path";
|
|
3625
3684
|
|
|
3626
3685
|
// packages/runtime/src/control-plane/native/pr-review-gate.ts
|
|
3627
3686
|
function parseJsonObject(value) {
|
|
@@ -4872,11 +4931,11 @@ async function verifyTask(options) {
|
|
|
4872
4931
|
const taskId = options.taskId;
|
|
4873
4932
|
const normalizedTaskId = lookupTask(options.projectRoot, taskId);
|
|
4874
4933
|
const artifactDir = artifactDirForId(options.projectRoot, taskId);
|
|
4875
|
-
|
|
4876
|
-
const validationSummaryPath =
|
|
4877
|
-
const reviewFeedbackPath =
|
|
4878
|
-
const reviewStatePath =
|
|
4879
|
-
const greptileRawPath =
|
|
4934
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
4935
|
+
const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
|
|
4936
|
+
const reviewFeedbackPath = resolve24(artifactDir, "review-feedback.md");
|
|
4937
|
+
const reviewStatePath = resolve24(artifactDir, "review-state.json");
|
|
4938
|
+
const greptileRawPath = resolve24(artifactDir, "review-greptile-raw.json");
|
|
4880
4939
|
const prStates = readPrMetadata(options.projectRoot, taskId);
|
|
4881
4940
|
const prState = prStates[0] || null;
|
|
4882
4941
|
const localReasons = [];
|
|
@@ -4888,7 +4947,7 @@ async function verifyTask(options) {
|
|
|
4888
4947
|
if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
|
|
4889
4948
|
localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
|
|
4890
4949
|
}
|
|
4891
|
-
if (!
|
|
4950
|
+
if (!existsSync22(validationSummaryPath)) {
|
|
4892
4951
|
localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
|
|
4893
4952
|
} else {
|
|
4894
4953
|
const summary = await parseValidationSummary(validationSummaryPath);
|
|
@@ -4897,13 +4956,13 @@ async function verifyTask(options) {
|
|
|
4897
4956
|
}
|
|
4898
4957
|
}
|
|
4899
4958
|
for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
|
|
4900
|
-
const requiredPath =
|
|
4901
|
-
if (!
|
|
4959
|
+
const requiredPath = resolve24(artifactDir, file);
|
|
4960
|
+
if (!existsSync22(requiredPath)) {
|
|
4902
4961
|
localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
|
|
4903
4962
|
}
|
|
4904
4963
|
}
|
|
4905
|
-
const taskResultPath =
|
|
4906
|
-
if (
|
|
4964
|
+
const taskResultPath = resolve24(artifactDir, "task-result.json");
|
|
4965
|
+
if (existsSync22(taskResultPath)) {
|
|
4907
4966
|
const taskResult = await readJsonFile2(taskResultPath);
|
|
4908
4967
|
const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
|
|
4909
4968
|
if (artifactStatus === "partial") {
|
|
@@ -4916,8 +4975,8 @@ async function verifyTask(options) {
|
|
|
4916
4975
|
localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
|
|
4917
4976
|
}
|
|
4918
4977
|
}
|
|
4919
|
-
const nextActionsPath =
|
|
4920
|
-
if (
|
|
4978
|
+
const nextActionsPath = resolve24(artifactDir, "next-actions.md");
|
|
4979
|
+
if (existsSync22(nextActionsPath)) {
|
|
4921
4980
|
const nextActionsContent = await Bun.file(nextActionsPath).text();
|
|
4922
4981
|
if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
|
|
4923
4982
|
localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
|
|
@@ -4948,7 +5007,7 @@ async function verifyTask(options) {
|
|
|
4948
5007
|
aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
|
|
4949
5008
|
}
|
|
4950
5009
|
if (persistArtifacts && ai.rawResponse) {
|
|
4951
|
-
|
|
5010
|
+
writeFileSync10(greptileRawPath, `${ai.rawResponse}
|
|
4952
5011
|
`, "utf-8");
|
|
4953
5012
|
}
|
|
4954
5013
|
} else if (!options.skipAiReview && reviewMode === "off") {
|
|
@@ -5191,7 +5250,7 @@ function evaluateSourceCloseoutChecks(prState, prLabel) {
|
|
|
5191
5250
|
if (!Array.isArray(checks) || checks.length === 0) {
|
|
5192
5251
|
return [`[Source Issue] PR ${prLabel} must have green check evidence before completion.`];
|
|
5193
5252
|
}
|
|
5194
|
-
const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0);
|
|
5253
|
+
const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0, { mergeStateStatus: prState.mergeStateStatus });
|
|
5195
5254
|
if (ciGate.verdict === "APPROVE") {
|
|
5196
5255
|
return [];
|
|
5197
5256
|
}
|
|
@@ -5287,7 +5346,7 @@ function isAcceptedValidationSummary(summary) {
|
|
|
5287
5346
|
return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
|
|
5288
5347
|
}
|
|
5289
5348
|
async function loadReviewMode(reviewProfilePath, fallback) {
|
|
5290
|
-
const parsed =
|
|
5349
|
+
const parsed = existsSync22(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
|
|
5291
5350
|
const mode = parsed?.mode;
|
|
5292
5351
|
if (mode === "off" || mode === "advisory" || mode === "required") {
|
|
5293
5352
|
return mode;
|
|
@@ -5298,7 +5357,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
|
|
|
5298
5357
|
return "advisory";
|
|
5299
5358
|
}
|
|
5300
5359
|
async function loadReviewProvider(reviewProfilePath, fallback) {
|
|
5301
|
-
const parsed =
|
|
5360
|
+
const parsed = existsSync22(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
|
|
5302
5361
|
const provider = parsed?.provider;
|
|
5303
5362
|
if (typeof provider === "string" && provider.trim().length > 0) {
|
|
5304
5363
|
return provider;
|
|
@@ -5457,7 +5516,7 @@ function writeFeedbackFile(options) {
|
|
|
5457
5516
|
if (options.aiRawFeedback) {
|
|
5458
5517
|
lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
|
|
5459
5518
|
}
|
|
5460
|
-
|
|
5519
|
+
writeFileSync10(options.output, `${lines.join(`
|
|
5461
5520
|
`)}
|
|
5462
5521
|
`, "utf-8");
|
|
5463
5522
|
}
|
|
@@ -5474,7 +5533,7 @@ function writeReviewStateFile(options) {
|
|
|
5474
5533
|
ai_warnings: options.aiWarnings,
|
|
5475
5534
|
updated_at: nowIso()
|
|
5476
5535
|
};
|
|
5477
|
-
|
|
5536
|
+
writeFileSync10(options.output, `${JSON.stringify(payload, null, 2)}
|
|
5478
5537
|
`, "utf-8");
|
|
5479
5538
|
}
|
|
5480
5539
|
async function runGreptileReviewForPr(options) {
|
|
@@ -5555,7 +5614,7 @@ async function runGreptileReviewForPr(options) {
|
|
|
5555
5614
|
}
|
|
5556
5615
|
await Bun.sleep(options.pollIntervalMs);
|
|
5557
5616
|
}
|
|
5558
|
-
const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber);
|
|
5617
|
+
const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
|
|
5559
5618
|
if (ciGate.verdict !== "APPROVE") {
|
|
5560
5619
|
return {
|
|
5561
5620
|
verdict: ciGate.verdict,
|
|
@@ -5813,7 +5872,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
|
|
|
5813
5872
|
}
|
|
5814
5873
|
await Bun.sleep(options.pollIntervalMs);
|
|
5815
5874
|
}
|
|
5816
|
-
const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber);
|
|
5875
|
+
const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
|
|
5817
5876
|
if (ciGate.verdict !== "APPROVE") {
|
|
5818
5877
|
return {
|
|
5819
5878
|
verdict: ciGate.verdict,
|
|
@@ -6168,19 +6227,31 @@ function loadGithubPullRequestCheckRollup(projectRoot, repoName, prNumber) {
|
|
|
6168
6227
|
]);
|
|
6169
6228
|
return response.statusCheckRollup || [];
|
|
6170
6229
|
}
|
|
6171
|
-
function evaluatePullRequestCiChecks(checks, repoName, prNumber) {
|
|
6172
|
-
const
|
|
6173
|
-
const label = (check.name || check.context || "").toLowerCase();
|
|
6174
|
-
return label.length > 0 && !label.includes("greptile");
|
|
6175
|
-
});
|
|
6176
|
-
const pending = nonGreptileChecks.filter((check) => {
|
|
6230
|
+
function evaluatePullRequestCiChecks(checks, repoName, prNumber, options = {}) {
|
|
6231
|
+
const isPendingCheck2 = (check) => {
|
|
6177
6232
|
if ((check.__typename || "") === "CheckRun") {
|
|
6178
6233
|
return (check.status || "").toUpperCase() !== "COMPLETED";
|
|
6179
6234
|
}
|
|
6180
6235
|
const state = (check.state || check.status || "").toUpperCase();
|
|
6181
6236
|
return state === "PENDING" || state === "EXPECTED" || state === "QUEUED" || state === "IN_PROGRESS";
|
|
6237
|
+
};
|
|
6238
|
+
const pendingGreptile = checks.filter((check) => {
|
|
6239
|
+
const label = (check.name || check.context || "").toLowerCase();
|
|
6240
|
+
return label.includes("greptile") && isPendingCheck2(check);
|
|
6182
6241
|
});
|
|
6183
|
-
if (
|
|
6242
|
+
if (pendingGreptile.length > 0) {
|
|
6243
|
+
return {
|
|
6244
|
+
verdict: "SKIP",
|
|
6245
|
+
reasons: pendingGreptile.map((check) => `[CI] ${repoName}#${prNumber} mandatory Greptile check is still pending: ${check.name || check.context || "unknown"}.`)
|
|
6246
|
+
};
|
|
6247
|
+
}
|
|
6248
|
+
const nonGreptileChecks = checks.filter((check) => {
|
|
6249
|
+
const label = (check.name || check.context || "").toLowerCase();
|
|
6250
|
+
return label.length > 0 && !label.includes("greptile");
|
|
6251
|
+
});
|
|
6252
|
+
const pending = nonGreptileChecks.filter(isPendingCheck2);
|
|
6253
|
+
const mergeClean = (options.mergeStateStatus || "").toUpperCase() === "CLEAN";
|
|
6254
|
+
if (pending.length > 0 && !mergeClean) {
|
|
6184
6255
|
return {
|
|
6185
6256
|
verdict: "SKIP",
|
|
6186
6257
|
reasons: pending.map((check) => `[CI] ${repoName}#${prNumber} check is still pending: ${check.name || check.context || "unknown"}.`)
|
|
@@ -6261,7 +6332,7 @@ function filterActionableGithubGreptileThreads(threads) {
|
|
|
6261
6332
|
}
|
|
6262
6333
|
function resolvePrRepoRoot(projectRoot, prState) {
|
|
6263
6334
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6264
|
-
if (prState.target === "monorepo" && runtimeWorkspace &&
|
|
6335
|
+
if (prState.target === "monorepo" && runtimeWorkspace && existsSync22(resolve24(runtimeWorkspace, ".git"))) {
|
|
6265
6336
|
return runtimeWorkspace;
|
|
6266
6337
|
}
|
|
6267
6338
|
const paths = resolveHarnessPaths(projectRoot);
|
|
@@ -6633,16 +6704,16 @@ async function taskDeps(projectRoot, taskId) {
|
|
|
6633
6704
|
for (const dep of deps) {
|
|
6634
6705
|
const artifactDir = artifactDirForId(projectRoot, dep);
|
|
6635
6706
|
console.log(`=== ${dep} ===`);
|
|
6636
|
-
if (!
|
|
6707
|
+
if (!existsSync23(artifactDir)) {
|
|
6637
6708
|
console.log(` (no artifacts yet)
|
|
6638
6709
|
`);
|
|
6639
6710
|
continue;
|
|
6640
6711
|
}
|
|
6641
|
-
printArtifactSection(
|
|
6642
|
-
printArtifactSection(
|
|
6643
|
-
const changedFiles =
|
|
6644
|
-
if (
|
|
6645
|
-
const lines =
|
|
6712
|
+
printArtifactSection(resolve25(artifactDir, "decision-log.md"), "--- Decisions ---");
|
|
6713
|
+
printArtifactSection(resolve25(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
|
|
6714
|
+
const changedFiles = resolve25(artifactDir, "changed-files.txt");
|
|
6715
|
+
if (existsSync23(changedFiles)) {
|
|
6716
|
+
const lines = readFileSync12(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
6646
6717
|
console.log(`--- Changed Files (${lines.length}) ---`);
|
|
6647
6718
|
for (const line of lines) {
|
|
6648
6719
|
console.log(line);
|
|
@@ -6687,12 +6758,12 @@ function taskRecord(projectRoot, type, text, taskId) {
|
|
|
6687
6758
|
throw new Error("No active task.");
|
|
6688
6759
|
}
|
|
6689
6760
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6690
|
-
|
|
6761
|
+
mkdirSync11(paths.stateDir, { recursive: true });
|
|
6691
6762
|
if (type === "decision") {
|
|
6692
|
-
const artifactDir =
|
|
6693
|
-
|
|
6763
|
+
const artifactDir = resolve25(paths.artifactsDir, activeTask);
|
|
6764
|
+
mkdirSync11(artifactDir, { recursive: true });
|
|
6694
6765
|
const timestamp = nowIso();
|
|
6695
|
-
appendFileSync(
|
|
6766
|
+
appendFileSync(resolve25(artifactDir, "decision-log.md"), `
|
|
6696
6767
|
### ${timestamp}
|
|
6697
6768
|
|
|
6698
6769
|
${text}
|
|
@@ -6702,14 +6773,14 @@ ${text}
|
|
|
6702
6773
|
return;
|
|
6703
6774
|
}
|
|
6704
6775
|
const failedPath = paths.failedApproachesPath;
|
|
6705
|
-
if (!
|
|
6706
|
-
|
|
6776
|
+
if (!existsSync23(failedPath)) {
|
|
6777
|
+
writeFileSync11(failedPath, `# Failed Approaches Log
|
|
6707
6778
|
|
|
6708
6779
|
This file records approaches that did not work.
|
|
6709
6780
|
|
|
6710
6781
|
`, "utf-8");
|
|
6711
6782
|
}
|
|
6712
|
-
const content =
|
|
6783
|
+
const content = readFileSync12(failedPath, "utf-8");
|
|
6713
6784
|
const attempts = (content.match(new RegExp(`^## ${escapeRegExp(activeTask)}\\b`, "gm")) || []).length + 1;
|
|
6714
6785
|
appendFileSync(failedPath, `
|
|
6715
6786
|
## ${activeTask} - Attempt ${attempts} (${nowIso()})
|
|
@@ -6726,40 +6797,40 @@ function taskArtifacts(projectRoot, taskId) {
|
|
|
6726
6797
|
throw new Error("No active task.");
|
|
6727
6798
|
}
|
|
6728
6799
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6729
|
-
const artifactDir =
|
|
6730
|
-
|
|
6800
|
+
const artifactDir = resolve25(paths.artifactsDir, activeTask);
|
|
6801
|
+
mkdirSync11(artifactDir, { recursive: true });
|
|
6731
6802
|
const changed = changedFilesForTask(projectRoot, activeTask, true);
|
|
6732
|
-
|
|
6803
|
+
writeFileSync11(resolve25(artifactDir, "changed-files.txt"), `${changed.join(`
|
|
6733
6804
|
`)}
|
|
6734
6805
|
`, "utf-8");
|
|
6735
6806
|
console.log(`changed-files.txt: ${changed.length} files`);
|
|
6736
|
-
const taskResultPath =
|
|
6737
|
-
if (!
|
|
6807
|
+
const taskResultPath = resolve25(artifactDir, "task-result.json");
|
|
6808
|
+
if (!existsSync23(taskResultPath)) {
|
|
6738
6809
|
const template = {
|
|
6739
6810
|
task_id: activeTask,
|
|
6740
6811
|
status: "completed",
|
|
6741
6812
|
summary: "TODO: Write a one-line summary of what you did",
|
|
6742
6813
|
completed_at: nowIso()
|
|
6743
6814
|
};
|
|
6744
|
-
|
|
6815
|
+
writeFileSync11(taskResultPath, `${JSON.stringify(template, null, 2)}
|
|
6745
6816
|
`, "utf-8");
|
|
6746
6817
|
console.log("task-result.json: created (update the summary!)");
|
|
6747
6818
|
} else {
|
|
6748
6819
|
console.log("task-result.json: already exists");
|
|
6749
6820
|
}
|
|
6750
|
-
const decisionLogPath =
|
|
6751
|
-
if (!
|
|
6821
|
+
const decisionLogPath = resolve25(artifactDir, "decision-log.md");
|
|
6822
|
+
if (!existsSync23(decisionLogPath)) {
|
|
6752
6823
|
const content = `# Decision Log: ${activeTask}
|
|
6753
6824
|
|
|
6754
6825
|
Record key decisions here using: rig-agent record decision "..."
|
|
6755
6826
|
`;
|
|
6756
|
-
|
|
6827
|
+
writeFileSync11(decisionLogPath, content, "utf-8");
|
|
6757
6828
|
console.log("decision-log.md: created (record your decisions!)");
|
|
6758
6829
|
} else {
|
|
6759
6830
|
console.log("decision-log.md: already exists");
|
|
6760
6831
|
}
|
|
6761
|
-
const nextActionsPath =
|
|
6762
|
-
if (!
|
|
6832
|
+
const nextActionsPath = resolve25(artifactDir, "next-actions.md");
|
|
6833
|
+
if (!existsSync23(nextActionsPath)) {
|
|
6763
6834
|
const content = [
|
|
6764
6835
|
`# Next Actions: ${activeTask}`,
|
|
6765
6836
|
"",
|
|
@@ -6776,13 +6847,13 @@ Record key decisions here using: rig-agent record decision "..."
|
|
|
6776
6847
|
""
|
|
6777
6848
|
].join(`
|
|
6778
6849
|
`);
|
|
6779
|
-
|
|
6850
|
+
writeFileSync11(nextActionsPath, content, "utf-8");
|
|
6780
6851
|
console.log("next-actions.md: created (add recommendations for downstream tasks!)");
|
|
6781
6852
|
} else {
|
|
6782
6853
|
console.log("next-actions.md: already exists");
|
|
6783
6854
|
}
|
|
6784
|
-
const validationSummaryPath =
|
|
6785
|
-
if (
|
|
6855
|
+
const validationSummaryPath = resolve25(artifactDir, "validation-summary.json");
|
|
6856
|
+
if (existsSync23(validationSummaryPath)) {
|
|
6786
6857
|
console.log("validation-summary.json: already exists");
|
|
6787
6858
|
} else {
|
|
6788
6859
|
console.log("validation-summary.json: not yet created (run: rig-agent validate)");
|
|
@@ -6873,7 +6944,7 @@ function collectTaskChangedFiles(projectRoot, taskId, includeCommitted) {
|
|
|
6873
6944
|
[projectRoot, ""],
|
|
6874
6945
|
[monorepoRepoRoot, ""]
|
|
6875
6946
|
]) {
|
|
6876
|
-
if (!
|
|
6947
|
+
if (!existsSync23(resolve25(repo, ".git"))) {
|
|
6877
6948
|
continue;
|
|
6878
6949
|
}
|
|
6879
6950
|
if (includeCommitted && repo === monorepoRepoRoot) {
|
|
@@ -6898,12 +6969,22 @@ function filterTaskChangedFiles(projectRoot, taskId, files, scoped) {
|
|
|
6898
6969
|
}
|
|
6899
6970
|
function resolveTaskMonorepoRoot(projectRoot) {
|
|
6900
6971
|
const runtimeWorkspace = loadRuntimeContextFromEnv()?.workspaceDir || process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6901
|
-
if (runtimeWorkspace &&
|
|
6902
|
-
return
|
|
6972
|
+
if (runtimeWorkspace && existsSync23(resolve25(runtimeWorkspace, ".git"))) {
|
|
6973
|
+
return resolve25(runtimeWorkspace);
|
|
6903
6974
|
}
|
|
6904
6975
|
return resolveHarnessPaths(projectRoot).monorepoRoot;
|
|
6905
6976
|
}
|
|
6906
6977
|
function collectCommittedMonorepoFiles(projectRoot, repo) {
|
|
6978
|
+
const defaultRef = runCapture(["git", "-C", repo, "rev-parse", "--abbrev-ref", "origin/HEAD"], projectRoot);
|
|
6979
|
+
if (defaultRef.exitCode === 0 && defaultRef.stdout.trim()) {
|
|
6980
|
+
const mergeBase = runCapture(["git", "-C", repo, "merge-base", "HEAD", defaultRef.stdout.trim()], projectRoot);
|
|
6981
|
+
if (mergeBase.exitCode === 0 && mergeBase.stdout.trim()) {
|
|
6982
|
+
const result = runCapture(["git", "-C", repo, "diff", "--name-only", `${mergeBase.stdout.trim()}..HEAD`], projectRoot);
|
|
6983
|
+
if (result.exitCode === 0) {
|
|
6984
|
+
return result.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
6985
|
+
}
|
|
6986
|
+
}
|
|
6987
|
+
}
|
|
6907
6988
|
const initialHeadCommit = resolveRuntimeInitialHeadCommit(projectRoot, repo);
|
|
6908
6989
|
if (initialHeadCommit) {
|
|
6909
6990
|
const result = runCapture(["git", "-C", repo, "diff", "--name-only", `${initialHeadCommit}..HEAD`], projectRoot);
|
|
@@ -6927,7 +7008,7 @@ function resolveRuntimeInitialHeadCommit(projectRoot, repo) {
|
|
|
6927
7008
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6928
7009
|
if (runtimeContext?.initialHeadCommits?.monorepo?.trim()) {
|
|
6929
7010
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6930
|
-
if (
|
|
7011
|
+
if (resolve25(monorepoRoot) === resolve25(repo)) {
|
|
6931
7012
|
return runtimeContext.initialHeadCommits.monorepo.trim();
|
|
6932
7013
|
}
|
|
6933
7014
|
}
|
|
@@ -6937,7 +7018,7 @@ function resolveMonorepoBaseCommit(projectRoot, repo) {
|
|
|
6937
7018
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6938
7019
|
if (runtimeContext?.monorepoBaseCommit?.trim()) {
|
|
6939
7020
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6940
|
-
if (
|
|
7021
|
+
if (resolve25(monorepoRoot) === resolve25(repo)) {
|
|
6941
7022
|
return runtimeContext.monorepoBaseCommit.trim();
|
|
6942
7023
|
}
|
|
6943
7024
|
}
|
|
@@ -6982,7 +7063,7 @@ function resolveRuntimeDirtyBaseline(projectRoot, repo) {
|
|
|
6982
7063
|
return new Set;
|
|
6983
7064
|
}
|
|
6984
7065
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6985
|
-
const selected =
|
|
7066
|
+
const selected = resolve25(repo) === resolve25(monorepoRoot) ? dirtyFiles.monorepo : resolve25(repo) === resolve25(projectRoot) ? dirtyFiles.project : undefined;
|
|
6986
7067
|
return new Set((selected || []).map((file) => normalizeChangedFilePath(file)).filter(Boolean));
|
|
6987
7068
|
}
|
|
6988
7069
|
function normalizeChangedFilePath(file) {
|
|
@@ -7082,12 +7163,12 @@ function printIndented(text) {
|
|
|
7082
7163
|
}
|
|
7083
7164
|
}
|
|
7084
7165
|
function readLocalBeadsTasks(projectRoot) {
|
|
7085
|
-
const issuesPath =
|
|
7086
|
-
if (!
|
|
7166
|
+
const issuesPath = resolve25(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
|
|
7167
|
+
if (!existsSync23(issuesPath)) {
|
|
7087
7168
|
return [];
|
|
7088
7169
|
}
|
|
7089
7170
|
const tasks = [];
|
|
7090
|
-
for (const line of
|
|
7171
|
+
for (const line of readFileSync12(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
7091
7172
|
const trimmed = line.trim();
|
|
7092
7173
|
if (!trimmed) {
|
|
7093
7174
|
continue;
|
|
@@ -7200,11 +7281,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
|
|
|
7200
7281
|
return [...ids].sort();
|
|
7201
7282
|
}
|
|
7202
7283
|
function printArtifactSection(path, header) {
|
|
7203
|
-
if (!
|
|
7284
|
+
if (!existsSync23(path)) {
|
|
7204
7285
|
return;
|
|
7205
7286
|
}
|
|
7206
7287
|
console.log(header);
|
|
7207
|
-
process.stdout.write(
|
|
7288
|
+
process.stdout.write(readFileSync12(path, "utf-8"));
|
|
7208
7289
|
console.log("");
|
|
7209
7290
|
}
|
|
7210
7291
|
function escapeRegExp(value) {
|
|
@@ -7244,8 +7325,8 @@ function isRuntimeGatewayGhPath(candidate) {
|
|
|
7244
7325
|
}
|
|
7245
7326
|
function resolveOptionalMonorepoRoot(projectRoot) {
|
|
7246
7327
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
7247
|
-
if (runtimeWorkspace &&
|
|
7248
|
-
return
|
|
7328
|
+
if (runtimeWorkspace && existsSync24(resolve26(runtimeWorkspace, ".git"))) {
|
|
7329
|
+
return resolve26(runtimeWorkspace);
|
|
7249
7330
|
}
|
|
7250
7331
|
try {
|
|
7251
7332
|
return resolveMonorepoRoot2(projectRoot);
|
|
@@ -7270,7 +7351,7 @@ function resolveGitBinary(projectRoot) {
|
|
|
7270
7351
|
if (!candidate || isRuntimeGatewayGitPath(candidate)) {
|
|
7271
7352
|
continue;
|
|
7272
7353
|
}
|
|
7273
|
-
if (
|
|
7354
|
+
if (existsSync24(candidate)) {
|
|
7274
7355
|
return candidate;
|
|
7275
7356
|
}
|
|
7276
7357
|
}
|
|
@@ -7330,11 +7411,11 @@ function gitPreflight(projectRoot, taskId, strict) {
|
|
|
7330
7411
|
const expected = resolvedTask ? `rig/${resolveTaskBranchId(projectRoot, resolvedTask)}` : "";
|
|
7331
7412
|
console.log("=== Git Flow Preflight ===");
|
|
7332
7413
|
let issues = 0;
|
|
7333
|
-
if (!
|
|
7414
|
+
if (!existsSync24(resolve26(projectRoot, ".git"))) {
|
|
7334
7415
|
console.log(`ERROR: project root is not a git repo (${projectRoot})`);
|
|
7335
7416
|
issues += 1;
|
|
7336
7417
|
}
|
|
7337
|
-
if (monorepoRoot &&
|
|
7418
|
+
if (monorepoRoot && existsSync24(resolve26(monorepoRoot, ".git"))) {
|
|
7338
7419
|
const monoBranch = branchName(projectRoot, monorepoRoot);
|
|
7339
7420
|
if (expected && monoBranch !== expected) {
|
|
7340
7421
|
console.log(`WARN: monorepo branch is ${monoBranch}, expected ${expected} for task ${resolvedTask}`);
|
|
@@ -7368,7 +7449,7 @@ function gitSyncBranch(projectRoot, taskId, targetRepo = "monorepo") {
|
|
|
7368
7449
|
}
|
|
7369
7450
|
const repoRoot = targetRepo === "monorepo" ? resolveOptionalMonorepoRoot(projectRoot) || resolveMonorepoRoot2(projectRoot) : projectRoot;
|
|
7370
7451
|
const repoLabel = targetRepo === "monorepo" ? "Monorepo" : "Project";
|
|
7371
|
-
if (!
|
|
7452
|
+
if (!existsSync24(resolve26(repoRoot, ".git"))) {
|
|
7372
7453
|
throw new Error(`${repoLabel} repo not found at ${repoRoot}`);
|
|
7373
7454
|
}
|
|
7374
7455
|
const branchId = resolveTaskBranchId(projectRoot, resolvedTask);
|
|
@@ -7412,8 +7493,8 @@ function gitCommit(options) {
|
|
|
7412
7493
|
function gitSnapshot(projectRoot, taskId, outputPath) {
|
|
7413
7494
|
const monorepoRoot = resolveOptionalMonorepoRoot(projectRoot);
|
|
7414
7495
|
const resolvedTask = taskId || safeCurrentTaskId(projectRoot);
|
|
7415
|
-
const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) :
|
|
7416
|
-
|
|
7496
|
+
const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) : resolve26(resolve26(projectRoot, ".rig", "state"), "git-state.txt"));
|
|
7497
|
+
mkdirSync12(dirname12(output), { recursive: true });
|
|
7417
7498
|
const lines = ["# Git Snapshot", `timestamp: ${nowIso()}`];
|
|
7418
7499
|
if (resolvedTask) {
|
|
7419
7500
|
lines.push(`task: ${resolvedTask}`);
|
|
@@ -7423,7 +7504,7 @@ function gitSnapshot(projectRoot, taskId, outputPath) {
|
|
|
7423
7504
|
if (monorepoRoot && monorepoRoot !== projectRoot) {
|
|
7424
7505
|
lines.push(...snapshotRepo(projectRoot, "monorepo", monorepoRoot));
|
|
7425
7506
|
}
|
|
7426
|
-
|
|
7507
|
+
writeFileSync12(output, `${lines.join(`
|
|
7427
7508
|
`)}
|
|
7428
7509
|
`, "utf-8");
|
|
7429
7510
|
return output;
|
|
@@ -7447,7 +7528,7 @@ function gitOpenPr(options) {
|
|
|
7447
7528
|
} else if (taskId) {
|
|
7448
7529
|
gitSyncBranch(options.projectRoot, taskId, "project");
|
|
7449
7530
|
}
|
|
7450
|
-
if (!
|
|
7531
|
+
if (!existsSync24(resolve26(repoRoot, ".git"))) {
|
|
7451
7532
|
throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
|
|
7452
7533
|
}
|
|
7453
7534
|
const branch = branchName(options.projectRoot, repoRoot);
|
|
@@ -7660,12 +7741,12 @@ function assertPrHasNoGitConflicts(prState, repoLabel, baseRef) {
|
|
|
7660
7741
|
}
|
|
7661
7742
|
function writePrMetadata(projectRoot, taskId, result) {
|
|
7662
7743
|
const dir = artifactDirForId(projectRoot, taskId);
|
|
7663
|
-
|
|
7664
|
-
const path =
|
|
7744
|
+
mkdirSync12(dir, { recursive: true });
|
|
7745
|
+
const path = resolve26(dir, "pr-state.json");
|
|
7665
7746
|
let prs = {};
|
|
7666
|
-
if (
|
|
7747
|
+
if (existsSync24(path)) {
|
|
7667
7748
|
try {
|
|
7668
|
-
const parsed = JSON.parse(
|
|
7749
|
+
const parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
7669
7750
|
if (parsed && typeof parsed === "object" && parsed.prs && typeof parsed.prs === "object") {
|
|
7670
7751
|
prs = parsed.prs;
|
|
7671
7752
|
}
|
|
@@ -7681,16 +7762,16 @@ function writePrMetadata(projectRoot, taskId, result) {
|
|
|
7681
7762
|
...primary || {},
|
|
7682
7763
|
updated_at: nowIso()
|
|
7683
7764
|
};
|
|
7684
|
-
|
|
7765
|
+
writeFileSync12(path, `${JSON.stringify(artifact, null, 2)}
|
|
7685
7766
|
`, "utf-8");
|
|
7686
7767
|
}
|
|
7687
7768
|
function readPrMetadata(projectRoot, taskId) {
|
|
7688
|
-
const path =
|
|
7689
|
-
if (!
|
|
7769
|
+
const path = resolve26(artifactDirForId(projectRoot, taskId), "pr-state.json");
|
|
7770
|
+
if (!existsSync24(path)) {
|
|
7690
7771
|
return [];
|
|
7691
7772
|
}
|
|
7692
7773
|
try {
|
|
7693
|
-
const parsed = JSON.parse(
|
|
7774
|
+
const parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
7694
7775
|
if (!parsed || typeof parsed !== "object") {
|
|
7695
7776
|
return [];
|
|
7696
7777
|
}
|
|
@@ -7703,8 +7784,8 @@ function readPrMetadata(projectRoot, taskId) {
|
|
|
7703
7784
|
}
|
|
7704
7785
|
}
|
|
7705
7786
|
function resolveArtifactSnapshot(projectRoot, taskId) {
|
|
7706
|
-
const artifactDir =
|
|
7707
|
-
return
|
|
7787
|
+
const artifactDir = resolve26(resolveHarnessPaths(projectRoot).artifactsDir, taskId);
|
|
7788
|
+
return resolve26(artifactDir, "git-state.txt");
|
|
7708
7789
|
}
|
|
7709
7790
|
function isGitOpenPrResult(value) {
|
|
7710
7791
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -7763,14 +7844,14 @@ function resolveGithubCliBinary(projectRoot) {
|
|
|
7763
7844
|
}
|
|
7764
7845
|
const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
|
|
7765
7846
|
for (const entry of explicitPathEntries) {
|
|
7766
|
-
candidates.add(
|
|
7847
|
+
candidates.add(resolve26(entry, "gh"));
|
|
7767
7848
|
}
|
|
7768
7849
|
const bunResolved = Bun.which("gh");
|
|
7769
7850
|
if (bunResolved) {
|
|
7770
7851
|
candidates.add(bunResolved);
|
|
7771
7852
|
}
|
|
7772
7853
|
for (const candidate of candidates) {
|
|
7773
|
-
if (candidate &&
|
|
7854
|
+
if (candidate && existsSync24(candidate) && !isRuntimeGatewayGhPath(candidate)) {
|
|
7774
7855
|
return candidate;
|
|
7775
7856
|
}
|
|
7776
7857
|
}
|
|
@@ -7800,7 +7881,7 @@ function resolveRepoNameWithOwner(projectRoot, repoRoot) {
|
|
|
7800
7881
|
return resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, repoRoot, repoRoot, visited);
|
|
7801
7882
|
}
|
|
7802
7883
|
function resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, gitRoot, cwd, visited) {
|
|
7803
|
-
const normalizedGitRoot =
|
|
7884
|
+
const normalizedGitRoot = resolve26(gitRoot);
|
|
7804
7885
|
if (visited.has(normalizedGitRoot)) {
|
|
7805
7886
|
return "";
|
|
7806
7887
|
}
|
|
@@ -7872,7 +7953,7 @@ function resolveNetworkRemoteName(projectRoot, repoRoot, repoNameWithOwner) {
|
|
|
7872
7953
|
return remotes.includes("origin") ? "origin" : remotes[0];
|
|
7873
7954
|
}
|
|
7874
7955
|
function gitQuery(projectRoot, gitRoot, cwd, ...args) {
|
|
7875
|
-
const gitArgs =
|
|
7956
|
+
const gitArgs = existsSync24(resolve26(gitRoot, ".git")) ? gitCmd(projectRoot, gitRoot, ...args) : [resolveGitBinary(projectRoot), "--git-dir", gitRoot, ...args];
|
|
7876
7957
|
return runCapture2(gitArgs, cwd, projectRoot);
|
|
7877
7958
|
}
|
|
7878
7959
|
function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
|
|
@@ -7890,9 +7971,9 @@ function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
|
|
|
7890
7971
|
} else if (/^[a-z][a-z0-9+.-]*:\/\//i.test(normalized) || /^[^@]+@[^:]+:.+$/.test(normalized)) {
|
|
7891
7972
|
return "";
|
|
7892
7973
|
} else if (!isAbsolute2(normalized)) {
|
|
7893
|
-
candidate =
|
|
7974
|
+
candidate = resolve26(gitRoot, normalized);
|
|
7894
7975
|
}
|
|
7895
|
-
return
|
|
7976
|
+
return existsSync24(candidate) ? candidate : "";
|
|
7896
7977
|
}
|
|
7897
7978
|
function normalizeGithubRepoNameWithOwner(value) {
|
|
7898
7979
|
const normalized = value.trim();
|
|
@@ -8019,7 +8100,7 @@ function inferReviewerFromChangedFiles(projectRoot, repoRoot, baseRef, branchRef
|
|
|
8019
8100
|
return best;
|
|
8020
8101
|
}
|
|
8021
8102
|
function snapshotRepo(projectRoot, label, repo) {
|
|
8022
|
-
if (!
|
|
8103
|
+
if (!existsSync24(resolve26(repo, ".git"))) {
|
|
8023
8104
|
return [`## ${label}`, `repo: ${repo}`, "status: unavailable", ""];
|
|
8024
8105
|
}
|
|
8025
8106
|
const status = runCapture2(gitCmd(projectRoot, repo, "status", "--short"), projectRoot).stdout.trim();
|
|
@@ -8042,7 +8123,7 @@ function snapshotRepo(projectRoot, label, repo) {
|
|
|
8042
8123
|
];
|
|
8043
8124
|
}
|
|
8044
8125
|
function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files, changedFilesManifest) {
|
|
8045
|
-
if (!
|
|
8126
|
+
if (!existsSync24(resolve26(repo, ".git"))) {
|
|
8046
8127
|
console.log(`Skipping ${label}: repo not available (${repo})`);
|
|
8047
8128
|
return;
|
|
8048
8129
|
}
|
|
@@ -8074,18 +8155,18 @@ function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files
|
|
|
8074
8155
|
console.log(`Committed ${label}: ${message}`);
|
|
8075
8156
|
}
|
|
8076
8157
|
function readChangedFilesManifest(projectRoot, taskId) {
|
|
8077
|
-
const manifestPath =
|
|
8078
|
-
if (!
|
|
8158
|
+
const manifestPath = resolve26(artifactDirForId(projectRoot, taskId), "changed-files.txt");
|
|
8159
|
+
if (!existsSync24(manifestPath)) {
|
|
8079
8160
|
return [];
|
|
8080
8161
|
}
|
|
8081
|
-
const files =
|
|
8162
|
+
const files = readFileSync13(manifestPath, "utf-8").split(/\r?\n/).map((line) => normalizeChangedFilePath2(line)).filter(Boolean);
|
|
8082
8163
|
return [...new Set(files)];
|
|
8083
8164
|
}
|
|
8084
8165
|
function refreshChangedFilesManifest(projectRoot, taskId) {
|
|
8085
|
-
const manifestPath =
|
|
8086
|
-
|
|
8166
|
+
const manifestPath = resolve26(artifactDirForId(projectRoot, taskId), "changed-files.txt");
|
|
8167
|
+
mkdirSync12(dirname12(manifestPath), { recursive: true });
|
|
8087
8168
|
const changedFiles = changedFilesForTask(projectRoot, taskId, true);
|
|
8088
|
-
|
|
8169
|
+
writeFileSync12(manifestPath, `${changedFiles.join(`
|
|
8089
8170
|
`)}
|
|
8090
8171
|
`, "utf-8");
|
|
8091
8172
|
return manifestPath;
|
|
@@ -8198,7 +8279,7 @@ function repoHasPathChange(projectRoot, repoRoot, relativePath) {
|
|
|
8198
8279
|
return result.exitCode === 0 && result.stdout.trim().length > 0;
|
|
8199
8280
|
}
|
|
8200
8281
|
function stageExcludePathspecs(repoRoot) {
|
|
8201
|
-
const patterns =
|
|
8282
|
+
const patterns = existsSync24(resolve26(repoRoot, ".rig", "task-config.json")) ? [...TASK_RUNTIME_STAGE_EXCLUDES, ...GENERATED_STAGE_EXCLUDES] : [".rig/**", ...GENERATED_STAGE_EXCLUDES];
|
|
8202
8283
|
return patterns.map((pattern) => `:(glob,exclude)${pattern}`);
|
|
8203
8284
|
}
|
|
8204
8285
|
function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
@@ -8208,7 +8289,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
|
8208
8289
|
}
|
|
8209
8290
|
let current = repoRoot;
|
|
8210
8291
|
for (let index = 0;index < parts.length - 1; index += 1) {
|
|
8211
|
-
current =
|
|
8292
|
+
current = resolve26(current, parts[index]);
|
|
8212
8293
|
try {
|
|
8213
8294
|
if (lstatSync(current).isSymbolicLink()) {
|
|
8214
8295
|
return true;
|
|
@@ -8220,7 +8301,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
|
8220
8301
|
return false;
|
|
8221
8302
|
}
|
|
8222
8303
|
function printRepoStatus(projectRoot, label, repo, expectedBranch) {
|
|
8223
|
-
if (!
|
|
8304
|
+
if (!existsSync24(resolve26(repo, ".git"))) {
|
|
8224
8305
|
console.log(`${label}: unavailable (${repo})`);
|
|
8225
8306
|
return;
|
|
8226
8307
|
}
|
|
@@ -8256,7 +8337,7 @@ function resolveTaskBranchId(projectRoot, taskId) {
|
|
|
8256
8337
|
}
|
|
8257
8338
|
} catch {}
|
|
8258
8339
|
const artifactDir = artifactDirForId(projectRoot, taskId);
|
|
8259
|
-
if (
|
|
8340
|
+
if (existsSync24(artifactDir)) {
|
|
8260
8341
|
return taskId;
|
|
8261
8342
|
}
|
|
8262
8343
|
throw new Error(`Unknown task id: ${taskId}`);
|
|
@@ -8292,11 +8373,11 @@ function runCapture2(command, cwd, projectRoot = cwd) {
|
|
|
8292
8373
|
}
|
|
8293
8374
|
function runtimeGitEnv(projectRoot) {
|
|
8294
8375
|
const { ctx, runtimeRoot } = resolveRuntimeMetadata(projectRoot);
|
|
8295
|
-
const runtimeHome = runtimeRoot ?
|
|
8296
|
-
const runtimeTmp = runtimeRoot ?
|
|
8297
|
-
const runtimeCache = runtimeRoot ?
|
|
8298
|
-
const runtimeKnownHosts = runtimeHome ?
|
|
8299
|
-
const runtimeKey = runtimeHome ?
|
|
8376
|
+
const runtimeHome = runtimeRoot ? resolve26(runtimeRoot, "home") : "";
|
|
8377
|
+
const runtimeTmp = runtimeRoot ? resolve26(runtimeRoot, "tmp") : "";
|
|
8378
|
+
const runtimeCache = runtimeRoot ? resolve26(runtimeRoot, "cache") : "";
|
|
8379
|
+
const runtimeKnownHosts = runtimeHome ? resolve26(runtimeHome, ".ssh", "known_hosts") : "";
|
|
8380
|
+
const runtimeKey = runtimeHome ? resolve26(runtimeHome, ".ssh", "rig-agent-key") : "";
|
|
8300
8381
|
const env = {};
|
|
8301
8382
|
if (ctx?.workspaceDir) {
|
|
8302
8383
|
env.PROJECT_RIG_ROOT = projectRoot;
|
|
@@ -8309,14 +8390,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
8309
8390
|
if (runtimeRoot) {
|
|
8310
8391
|
env.RIG_RUNTIME_HOME = runtimeRoot;
|
|
8311
8392
|
}
|
|
8312
|
-
if (runtimeHome &&
|
|
8393
|
+
if (runtimeHome && existsSync24(runtimeHome)) {
|
|
8313
8394
|
env.HOME = runtimeHome;
|
|
8314
8395
|
env.OPENSSL_CONF = ensureRuntimeOpenSslConfig(runtimeHome);
|
|
8315
8396
|
}
|
|
8316
|
-
if (runtimeTmp &&
|
|
8397
|
+
if (runtimeTmp && existsSync24(runtimeTmp)) {
|
|
8317
8398
|
env.TMPDIR = runtimeTmp;
|
|
8318
8399
|
}
|
|
8319
|
-
if (runtimeCache &&
|
|
8400
|
+
if (runtimeCache && existsSync24(runtimeCache)) {
|
|
8320
8401
|
env.XDG_CACHE_HOME = runtimeCache;
|
|
8321
8402
|
}
|
|
8322
8403
|
const workspaceSecrets = loadDotEnvSecrets(ctx?.workspaceDir || projectRoot, process.env);
|
|
@@ -8360,14 +8441,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
8360
8441
|
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
8361
8442
|
applyGitHubCredentialHelperEnv(env);
|
|
8362
8443
|
}
|
|
8363
|
-
if (runtimeKnownHosts &&
|
|
8444
|
+
if (runtimeKnownHosts && existsSync24(runtimeKnownHosts)) {
|
|
8364
8445
|
const sshParts = [
|
|
8365
8446
|
"ssh",
|
|
8366
8447
|
`-o UserKnownHostsFile="${runtimeKnownHosts}"`,
|
|
8367
8448
|
"-o StrictHostKeyChecking=yes",
|
|
8368
8449
|
"-F /dev/null"
|
|
8369
8450
|
];
|
|
8370
|
-
if (runtimeKey &&
|
|
8451
|
+
if (runtimeKey && existsSync24(runtimeKey)) {
|
|
8371
8452
|
sshParts.splice(1, 0, `-i "${runtimeKey}"`, "-o IdentitiesOnly=yes");
|
|
8372
8453
|
}
|
|
8373
8454
|
env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
@@ -8388,12 +8469,12 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
|
8388
8469
|
if (!runtimeRoot) {
|
|
8389
8470
|
return {};
|
|
8390
8471
|
}
|
|
8391
|
-
const path =
|
|
8392
|
-
if (!
|
|
8472
|
+
const path = resolve26(runtimeRoot, "runtime-secrets.json");
|
|
8473
|
+
if (!existsSync24(path)) {
|
|
8393
8474
|
return {};
|
|
8394
8475
|
}
|
|
8395
8476
|
try {
|
|
8396
|
-
const parsed = JSON.parse(
|
|
8477
|
+
const parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
8397
8478
|
const entries = Object.entries(parsed).filter((entry) => typeof entry[1] === "string");
|
|
8398
8479
|
return Object.fromEntries(entries);
|
|
8399
8480
|
} catch {
|
|
@@ -8401,13 +8482,13 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
|
8401
8482
|
}
|
|
8402
8483
|
}
|
|
8403
8484
|
function ensureRuntimeOpenSslConfig(runtimeHome) {
|
|
8404
|
-
const sslDir =
|
|
8405
|
-
const sslConfig =
|
|
8406
|
-
if (!
|
|
8407
|
-
|
|
8485
|
+
const sslDir = resolve26(runtimeHome, ".ssl");
|
|
8486
|
+
const sslConfig = resolve26(sslDir, "openssl.cnf");
|
|
8487
|
+
if (!existsSync24(sslDir)) {
|
|
8488
|
+
mkdirSync12(sslDir, { recursive: true });
|
|
8408
8489
|
}
|
|
8409
|
-
if (!
|
|
8410
|
-
|
|
8490
|
+
if (!existsSync24(sslConfig)) {
|
|
8491
|
+
writeFileSync12(sslConfig, `# Rig runtime OpenSSL config placeholder
|
|
8411
8492
|
`);
|
|
8412
8493
|
}
|
|
8413
8494
|
return sslConfig;
|
|
@@ -8425,29 +8506,29 @@ function resolveRuntimeMetadata(projectRoot) {
|
|
|
8425
8506
|
if (contextFile) {
|
|
8426
8507
|
return {
|
|
8427
8508
|
ctx,
|
|
8428
|
-
runtimeRoot:
|
|
8509
|
+
runtimeRoot: dirname12(resolve26(contextFile))
|
|
8429
8510
|
};
|
|
8430
8511
|
}
|
|
8431
8512
|
const inferredContextFile = findRuntimeContextFile2(projectRoot);
|
|
8432
|
-
if (
|
|
8513
|
+
if (existsSync24(inferredContextFile)) {
|
|
8433
8514
|
try {
|
|
8434
8515
|
ctx = loadRuntimeContext(inferredContextFile);
|
|
8435
8516
|
} catch {}
|
|
8436
8517
|
return {
|
|
8437
8518
|
ctx,
|
|
8438
|
-
runtimeRoot:
|
|
8519
|
+
runtimeRoot: dirname12(inferredContextFile)
|
|
8439
8520
|
};
|
|
8440
8521
|
}
|
|
8441
8522
|
return { ctx, runtimeRoot: "" };
|
|
8442
8523
|
}
|
|
8443
8524
|
function findRuntimeContextFile2(startPath) {
|
|
8444
|
-
let current =
|
|
8525
|
+
let current = resolve26(startPath);
|
|
8445
8526
|
while (true) {
|
|
8446
|
-
const candidate =
|
|
8447
|
-
if (
|
|
8527
|
+
const candidate = resolve26(current, "runtime-context.json");
|
|
8528
|
+
if (existsSync24(candidate)) {
|
|
8448
8529
|
return candidate;
|
|
8449
8530
|
}
|
|
8450
|
-
const parent =
|
|
8531
|
+
const parent = dirname12(current);
|
|
8451
8532
|
if (parent === current) {
|
|
8452
8533
|
return "";
|
|
8453
8534
|
}
|
|
@@ -8456,7 +8537,7 @@ function findRuntimeContextFile2(startPath) {
|
|
|
8456
8537
|
}
|
|
8457
8538
|
|
|
8458
8539
|
// packages/runtime/src/control-plane/native/profile-ops.ts
|
|
8459
|
-
import { existsSync as
|
|
8540
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "fs";
|
|
8460
8541
|
var DEFAULTS = {
|
|
8461
8542
|
model: parseEnvOrDefault(process.env.DEFAULT_AGENT_MODEL, ["claude", "gpt-codex", "pi"], "pi"),
|
|
8462
8543
|
runtime: parseEnvOrDefault(process.env.DEFAULT_AGENT_RUNTIME, ["claude-code", "codex-app-server", "pi"], "pi"),
|
|
@@ -8471,7 +8552,7 @@ function parseEnvOrDefault(value, allowed, fallback) {
|
|
|
8471
8552
|
return allowed.includes(value) ? value : fallback;
|
|
8472
8553
|
}
|
|
8473
8554
|
async function readProfileFile(path) {
|
|
8474
|
-
if (!
|
|
8555
|
+
if (!existsSync25(path)) {
|
|
8475
8556
|
return null;
|
|
8476
8557
|
}
|
|
8477
8558
|
try {
|
|
@@ -8524,14 +8605,14 @@ async function setProfile(projectRoot, options) {
|
|
|
8524
8605
|
plugin = model === "gpt-codex" ? "codex" : model === "pi" ? "pi" : "claude";
|
|
8525
8606
|
}
|
|
8526
8607
|
const paths = resolveHarnessPaths(projectRoot);
|
|
8527
|
-
|
|
8608
|
+
mkdirSync13(paths.stateDir, { recursive: true });
|
|
8528
8609
|
const next = {
|
|
8529
8610
|
model,
|
|
8530
8611
|
runtime,
|
|
8531
8612
|
agent_plugin: plugin,
|
|
8532
8613
|
updated_at: new Date().toISOString()
|
|
8533
8614
|
};
|
|
8534
|
-
|
|
8615
|
+
writeFileSync13(paths.agentProfilePath, `${JSON.stringify(next, null, 2)}
|
|
8535
8616
|
`, "utf-8");
|
|
8536
8617
|
await showProfile(projectRoot, false);
|
|
8537
8618
|
}
|
|
@@ -8567,13 +8648,13 @@ async function setReviewProfile(projectRoot, mode, provider) {
|
|
|
8567
8648
|
throw new Error(`Invalid provider: ${resolvedProvider}. Supported: greptile.`);
|
|
8568
8649
|
}
|
|
8569
8650
|
const paths = resolveHarnessPaths(projectRoot);
|
|
8570
|
-
|
|
8651
|
+
mkdirSync13(paths.stateDir, { recursive: true });
|
|
8571
8652
|
const next = {
|
|
8572
8653
|
mode,
|
|
8573
8654
|
provider: resolvedProvider,
|
|
8574
8655
|
updated_at: new Date().toISOString()
|
|
8575
8656
|
};
|
|
8576
|
-
|
|
8657
|
+
writeFileSync13(paths.reviewProfilePath, `${JSON.stringify(next, null, 2)}
|
|
8577
8658
|
`, "utf-8");
|
|
8578
8659
|
await showReviewProfile(projectRoot);
|
|
8579
8660
|
}
|
|
@@ -8611,44 +8692,44 @@ async function loadReviewProfile(path) {
|
|
|
8611
8692
|
}
|
|
8612
8693
|
|
|
8613
8694
|
// packages/runtime/src/control-plane/native/repo-ops.ts
|
|
8614
|
-
import { existsSync as
|
|
8615
|
-
import { basename as basename8, dirname as
|
|
8695
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync17, readFileSync as readFileSync15, readdirSync as readdirSync6, rmSync as rmSync7, writeFileSync as writeFileSync15 } from "fs";
|
|
8696
|
+
import { basename as basename8, dirname as dirname14, resolve as resolve30 } from "path";
|
|
8616
8697
|
// packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
|
|
8617
|
-
import { existsSync as
|
|
8618
|
-
import { resolve as
|
|
8698
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync15, realpathSync as realpathSync2 } from "fs";
|
|
8699
|
+
import { resolve as resolve28 } from "path";
|
|
8619
8700
|
|
|
8620
8701
|
// packages/runtime/src/control-plane/authority-files.ts
|
|
8621
|
-
import { existsSync as
|
|
8622
|
-
import { dirname as
|
|
8702
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync14, readFileSync as readFileSync14, writeFileSync as writeFileSync14, appendFileSync as appendFileSync2, copyFileSync as copyFileSync3, statSync as statSync5, readdirSync as readdirSync5, chmodSync as chmodSync3 } from "fs";
|
|
8703
|
+
import { dirname as dirname13, join as join4, relative, resolve as resolve27 } from "path";
|
|
8623
8704
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
8624
8705
|
function resolveAuthorityProjectStateDir(projectRoot) {
|
|
8625
8706
|
const explicit = process.env.RIG_STATE_DIR?.trim();
|
|
8626
8707
|
if (explicit) {
|
|
8627
|
-
return
|
|
8708
|
+
return resolve27(explicit);
|
|
8628
8709
|
}
|
|
8629
|
-
return
|
|
8710
|
+
return resolve27(resolve27(projectRoot), ".rig", "state");
|
|
8630
8711
|
}
|
|
8631
8712
|
function readJsonAtPath(path, fallback) {
|
|
8632
|
-
if (!
|
|
8713
|
+
if (!existsSync26(path)) {
|
|
8633
8714
|
return fallback;
|
|
8634
8715
|
}
|
|
8635
8716
|
try {
|
|
8636
|
-
return JSON.parse(
|
|
8717
|
+
return JSON.parse(readFileSync14(path, "utf-8"));
|
|
8637
8718
|
} catch {
|
|
8638
8719
|
return fallback;
|
|
8639
8720
|
}
|
|
8640
8721
|
}
|
|
8641
8722
|
function writeJsonAtPath(path, value) {
|
|
8642
|
-
|
|
8643
|
-
|
|
8723
|
+
mkdirSync14(dirname13(path), { recursive: true });
|
|
8724
|
+
writeFileSync14(path, `${JSON.stringify(value, null, 2)}
|
|
8644
8725
|
`, "utf8");
|
|
8645
8726
|
return path;
|
|
8646
8727
|
}
|
|
8647
8728
|
function readAuthorityProjectStateJson(projectRoot, relativePath, fallback) {
|
|
8648
|
-
return readJsonAtPath(
|
|
8729
|
+
return readJsonAtPath(resolve27(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
|
|
8649
8730
|
}
|
|
8650
8731
|
function writeAuthorityProjectStateJson(projectRoot, relativePath, value) {
|
|
8651
|
-
return writeJsonAtPath(
|
|
8732
|
+
return writeJsonAtPath(resolve27(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
|
|
8652
8733
|
}
|
|
8653
8734
|
|
|
8654
8735
|
// packages/runtime/src/control-plane/repos/mirror/state.ts
|
|
@@ -8708,7 +8789,7 @@ function sameExistingPath(left, right) {
|
|
|
8708
8789
|
try {
|
|
8709
8790
|
return realpathSync2(left) === realpathSync2(right);
|
|
8710
8791
|
} catch {
|
|
8711
|
-
return
|
|
8792
|
+
return resolve28(left) === resolve28(right);
|
|
8712
8793
|
}
|
|
8713
8794
|
}
|
|
8714
8795
|
function repoLooksUsable(repoRoot, projectRoot) {
|
|
@@ -8744,7 +8825,7 @@ function resolveMirrorRemoteUrl(layout) {
|
|
|
8744
8825
|
}
|
|
8745
8826
|
}
|
|
8746
8827
|
}
|
|
8747
|
-
if (
|
|
8828
|
+
if (existsSync27(resolve28(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
|
|
8748
8829
|
const checkoutOrigin = runGit(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
8749
8830
|
if (checkoutOrigin.exitCode === 0) {
|
|
8750
8831
|
const currentOrigin = checkoutOrigin.stdout.trim();
|
|
@@ -8757,9 +8838,9 @@ function resolveMirrorRemoteUrl(layout) {
|
|
|
8757
8838
|
}
|
|
8758
8839
|
function ensureManagedRepoMirror(projectRoot, repoId) {
|
|
8759
8840
|
const layout = resolveManagedRepoLayout(projectRoot, repoId);
|
|
8760
|
-
|
|
8841
|
+
mkdirSync15(layout.metadataRoot, { recursive: true });
|
|
8761
8842
|
const remoteUrl = resolveMirrorRemoteUrl(layout);
|
|
8762
|
-
if (!
|
|
8843
|
+
if (!existsSync27(resolve28(layout.mirrorRoot, "HEAD"))) {
|
|
8763
8844
|
ensureGitSuccess(runGit(["git", "init", "--bare", layout.mirrorRoot], layout.projectRoot), ["git", "init", "--bare", layout.mirrorRoot]);
|
|
8764
8845
|
}
|
|
8765
8846
|
const getOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
@@ -8779,8 +8860,8 @@ function ensureManagedRepoMirror(projectRoot, repoId) {
|
|
|
8779
8860
|
return layout;
|
|
8780
8861
|
}
|
|
8781
8862
|
// packages/runtime/src/control-plane/repos/mirror/refresh.ts
|
|
8782
|
-
import { existsSync as
|
|
8783
|
-
import { resolve as
|
|
8863
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync16, realpathSync as realpathSync3, rmSync as rmSync6 } from "fs";
|
|
8864
|
+
import { resolve as resolve29 } from "path";
|
|
8784
8865
|
function nowIso3() {
|
|
8785
8866
|
return new Date().toISOString();
|
|
8786
8867
|
}
|
|
@@ -8807,7 +8888,7 @@ function sameExistingPath2(left, right) {
|
|
|
8807
8888
|
try {
|
|
8808
8889
|
return realpathSync3(left) === realpathSync3(right);
|
|
8809
8890
|
} catch {
|
|
8810
|
-
return
|
|
8891
|
+
return resolve29(left) === resolve29(right);
|
|
8811
8892
|
}
|
|
8812
8893
|
}
|
|
8813
8894
|
function ensureMirrorHead(layout) {
|
|
@@ -8853,12 +8934,12 @@ function checkoutLooksUsable2(layout) {
|
|
|
8853
8934
|
return probe.exitCode === 0 && sameExistingPath2(probe.stdout.trim(), layout.checkoutRoot);
|
|
8854
8935
|
}
|
|
8855
8936
|
function ensureCheckoutFromMirror(layout) {
|
|
8856
|
-
|
|
8857
|
-
const gitPath =
|
|
8858
|
-
if (
|
|
8937
|
+
mkdirSync16(resolve29(layout.checkoutRoot, ".."), { recursive: true });
|
|
8938
|
+
const gitPath = resolve29(layout.checkoutRoot, ".git");
|
|
8939
|
+
if (existsSync28(layout.checkoutRoot) && (!existsSync28(gitPath) || !checkoutLooksUsable2(layout))) {
|
|
8859
8940
|
rmSync6(layout.checkoutRoot, { recursive: true, force: true });
|
|
8860
8941
|
}
|
|
8861
|
-
if (!
|
|
8942
|
+
if (!existsSync28(gitPath)) {
|
|
8862
8943
|
ensureGitSuccess2(runGit2(["git", "clone", layout.mirrorRoot, layout.checkoutRoot], layout.projectRoot), ["git", "clone", layout.mirrorRoot, layout.checkoutRoot]);
|
|
8863
8944
|
}
|
|
8864
8945
|
const getOrigin = runGit2(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
@@ -8959,7 +9040,7 @@ function repoDiscover(projectRoot, taskId) {
|
|
|
8959
9040
|
}
|
|
8960
9041
|
function repoBaseline(projectRoot, refresh = false) {
|
|
8961
9042
|
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
8962
|
-
if (!refresh &&
|
|
9043
|
+
if (!refresh && existsSync29(paths.baseRepoPinsPath)) {
|
|
8963
9044
|
const baseline = readJsonFile(paths.baseRepoPinsPath, { recorded_at: nowIso(), repos: {} });
|
|
8964
9045
|
return baseline.repos || {};
|
|
8965
9046
|
}
|
|
@@ -8983,8 +9064,8 @@ function ensureMonorepoReady(projectRoot) {
|
|
|
8983
9064
|
}
|
|
8984
9065
|
function persistBaselinePins(projectRoot, repos) {
|
|
8985
9066
|
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
8986
|
-
|
|
8987
|
-
|
|
9067
|
+
mkdirSync17(resolve30(paths.baseRepoPinsPath, ".."), { recursive: true });
|
|
9068
|
+
writeFileSync15(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
|
|
8988
9069
|
`, "utf-8");
|
|
8989
9070
|
return repos;
|
|
8990
9071
|
}
|
|
@@ -9063,28 +9144,28 @@ function readRepoDiscoveryTaskConfig(projectRoot) {
|
|
|
9063
9144
|
function resolveRepoDiscoveryPaths(projectRoot) {
|
|
9064
9145
|
const monorepoRoot = resolveMonorepoRepoLayout(projectRoot).checkoutRoot;
|
|
9065
9146
|
const explicitHostProjectRoot = (process.env.RIG_HOST_PROJECT_ROOT || "").trim();
|
|
9066
|
-
const normalizedProjectRoot =
|
|
9147
|
+
const normalizedProjectRoot = resolve30(projectRoot);
|
|
9067
9148
|
const hostProjectRoot = explicitHostProjectRoot && shouldUseHostProjectStateRoot(normalizedProjectRoot) ? explicitHostProjectRoot : normalizedProjectRoot;
|
|
9068
|
-
const stateDir =
|
|
9149
|
+
const stateDir = resolve30(hostProjectRoot, ".rig", "state");
|
|
9069
9150
|
return {
|
|
9070
9151
|
monorepoRoot,
|
|
9071
|
-
taskRepoCommitsPath:
|
|
9072
|
-
baseRepoPinsPath:
|
|
9152
|
+
taskRepoCommitsPath: resolve30(stateDir, "task-repo-commits.json"),
|
|
9153
|
+
baseRepoPinsPath: resolve30(stateDir, "base-repo-pins.json")
|
|
9073
9154
|
};
|
|
9074
9155
|
}
|
|
9075
9156
|
function shouldUseHostProjectStateRoot(projectRoot) {
|
|
9076
9157
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
9077
|
-
if (runtimeWorkspace &&
|
|
9158
|
+
if (runtimeWorkspace && resolve30(runtimeWorkspace) === projectRoot) {
|
|
9078
9159
|
return true;
|
|
9079
9160
|
}
|
|
9080
|
-
return basename8(
|
|
9161
|
+
return basename8(dirname14(projectRoot)) === ".worktrees";
|
|
9081
9162
|
}
|
|
9082
9163
|
function readPinFromArtifact(projectRoot, depTask, repoKey) {
|
|
9083
|
-
const snapshot =
|
|
9084
|
-
if (!
|
|
9164
|
+
const snapshot = resolve30(artifactDirForId(projectRoot, depTask), "git-state.txt");
|
|
9165
|
+
if (!existsSync29(snapshot)) {
|
|
9085
9166
|
return "";
|
|
9086
9167
|
}
|
|
9087
|
-
const content =
|
|
9168
|
+
const content = readFileSync15(snapshot, "utf-8");
|
|
9088
9169
|
const chunk = content.split(/\r?\n/);
|
|
9089
9170
|
let inSection = false;
|
|
9090
9171
|
for (const line of chunk) {
|
|
@@ -9106,12 +9187,12 @@ function repoPath(projectRoot, key) {
|
|
|
9106
9187
|
if (managed) {
|
|
9107
9188
|
return managed.checkoutRoot;
|
|
9108
9189
|
}
|
|
9109
|
-
return key.startsWith("/") ? key :
|
|
9190
|
+
return key.startsWith("/") ? key : resolve30(projectRoot, key);
|
|
9110
9191
|
}
|
|
9111
9192
|
function applyPins(projectRoot, pins) {
|
|
9112
9193
|
for (const [key, commit] of Object.entries(pins)) {
|
|
9113
9194
|
const path = repoPath(projectRoot, key);
|
|
9114
|
-
if (!
|
|
9195
|
+
if (!existsSync29(resolve30(path, ".git"))) {
|
|
9115
9196
|
throw new Error(`Repo for pin not available: ${key} (${path})`);
|
|
9116
9197
|
}
|
|
9117
9198
|
let hasCommit = runGitCapture(["git", "-C", path, "cat-file", "-e", `${commit}^{commit}`], projectRoot).exitCode === 0;
|
|
@@ -9140,7 +9221,7 @@ function verifyPins(projectRoot, pins) {
|
|
|
9140
9221
|
let ok = true;
|
|
9141
9222
|
for (const [key, expected] of Object.entries(pins)) {
|
|
9142
9223
|
const path = repoPath(projectRoot, key);
|
|
9143
|
-
if (!
|
|
9224
|
+
if (!existsSync29(resolve30(path, ".git"))) {
|
|
9144
9225
|
console.error(`ERROR: repo missing during pin verification: ${key}`);
|
|
9145
9226
|
ok = false;
|
|
9146
9227
|
continue;
|
|
@@ -9165,23 +9246,23 @@ function resolveRuntimeGitEnv() {
|
|
|
9165
9246
|
GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND
|
|
9166
9247
|
};
|
|
9167
9248
|
}
|
|
9168
|
-
const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ?
|
|
9169
|
-
const runtimeHome = runtimeRoot ?
|
|
9249
|
+
const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ? resolve30(process.env.RIG_RUNTIME_CONTEXT_FILE, "..") : inferRuntimeRootFromWorkspace(process.cwd()));
|
|
9250
|
+
const runtimeHome = runtimeRoot ? resolve30(runtimeRoot, "home") : process.env.HOME?.trim() || "";
|
|
9170
9251
|
if (!runtimeHome) {
|
|
9171
9252
|
return;
|
|
9172
9253
|
}
|
|
9173
|
-
const knownHostsPath =
|
|
9174
|
-
if (!
|
|
9254
|
+
const knownHostsPath = resolve30(runtimeHome, ".ssh", "known_hosts");
|
|
9255
|
+
if (!existsSync29(knownHostsPath)) {
|
|
9175
9256
|
return { HOME: runtimeHome };
|
|
9176
9257
|
}
|
|
9177
|
-
const agentSshKey =
|
|
9258
|
+
const agentSshKey = resolve30(runtimeHome, ".ssh", "rig-agent-key");
|
|
9178
9259
|
const sshParts = [
|
|
9179
9260
|
"ssh",
|
|
9180
9261
|
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
9181
9262
|
"-o StrictHostKeyChecking=yes",
|
|
9182
9263
|
"-F /dev/null"
|
|
9183
9264
|
];
|
|
9184
|
-
if (
|
|
9265
|
+
if (existsSync29(agentSshKey)) {
|
|
9185
9266
|
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
9186
9267
|
}
|
|
9187
9268
|
return {
|
|
@@ -9191,24 +9272,24 @@ function resolveRuntimeGitEnv() {
|
|
|
9191
9272
|
}
|
|
9192
9273
|
function inferRuntimeRootFromWorkspace(cwd) {
|
|
9193
9274
|
const contextPath = findRuntimeContextFile3(cwd);
|
|
9194
|
-
if (!contextPath || !
|
|
9275
|
+
if (!contextPath || !existsSync29(contextPath)) {
|
|
9195
9276
|
return "";
|
|
9196
9277
|
}
|
|
9197
9278
|
try {
|
|
9198
9279
|
loadRuntimeContext(contextPath);
|
|
9199
|
-
return
|
|
9280
|
+
return resolve30(contextPath, "..");
|
|
9200
9281
|
} catch {
|
|
9201
9282
|
return "";
|
|
9202
9283
|
}
|
|
9203
9284
|
}
|
|
9204
9285
|
function findRuntimeContextFile3(startPath) {
|
|
9205
|
-
let current =
|
|
9286
|
+
let current = resolve30(startPath);
|
|
9206
9287
|
while (true) {
|
|
9207
|
-
const candidate =
|
|
9208
|
-
if (
|
|
9288
|
+
const candidate = resolve30(current, "runtime-context.json");
|
|
9289
|
+
if (existsSync29(candidate)) {
|
|
9209
9290
|
return candidate;
|
|
9210
9291
|
}
|
|
9211
|
-
const parent =
|
|
9292
|
+
const parent = resolve30(current, "..");
|
|
9212
9293
|
if (parent === current) {
|
|
9213
9294
|
return "";
|
|
9214
9295
|
}
|
|
@@ -9217,13 +9298,13 @@ function findRuntimeContextFile3(startPath) {
|
|
|
9217
9298
|
}
|
|
9218
9299
|
|
|
9219
9300
|
// packages/runtime/src/control-plane/memory-sync/cli.ts
|
|
9220
|
-
import { existsSync as
|
|
9301
|
+
import { existsSync as existsSync30 } from "fs";
|
|
9221
9302
|
import { randomUUID } from "crypto";
|
|
9222
9303
|
|
|
9223
9304
|
// packages/runtime/src/control-plane/memory-sync/db.ts
|
|
9224
9305
|
import { Database } from "bun:sqlite";
|
|
9225
|
-
import { mkdirSync as
|
|
9226
|
-
import { dirname as
|
|
9306
|
+
import { mkdirSync as mkdirSync18 } from "fs";
|
|
9307
|
+
import { dirname as dirname15 } from "path";
|
|
9227
9308
|
|
|
9228
9309
|
// packages/runtime/src/control-plane/memory-sync/types.ts
|
|
9229
9310
|
var NO_MATCH_RETRIEVAL_CANONICAL_KEY = "__memory_recall__:none";
|
|
@@ -9819,7 +9900,7 @@ async function validateEventTargets(executor, event) {
|
|
|
9819
9900
|
}
|
|
9820
9901
|
}
|
|
9821
9902
|
async function openMemoryDb(dbPath) {
|
|
9822
|
-
|
|
9903
|
+
mkdirSync18(dirname15(dbPath), { recursive: true });
|
|
9823
9904
|
const sqlite = new Database(dbPath, { create: true, strict: true });
|
|
9824
9905
|
const client = createMemoryDbClient(sqlite);
|
|
9825
9906
|
const db = {
|
|
@@ -10238,7 +10319,7 @@ function formatMemoryQueryResults(results) {
|
|
|
10238
10319
|
}
|
|
10239
10320
|
|
|
10240
10321
|
// packages/runtime/src/control-plane/memory-sync/read.ts
|
|
10241
|
-
import { mkdtempSync, rmSync as rmSync8, writeFileSync as
|
|
10322
|
+
import { mkdtempSync, rmSync as rmSync8, writeFileSync as writeFileSync16 } from "fs";
|
|
10242
10323
|
import { tmpdir as tmpdir5 } from "os";
|
|
10243
10324
|
import { join as join5 } from "path";
|
|
10244
10325
|
var CANONICAL_MEMORY_DB_PATH = "rig/memory/project-memory.db";
|
|
@@ -10267,7 +10348,7 @@ async function readCanonicalMemoryDb(projectRoot, deps = {}) {
|
|
|
10267
10348
|
try {
|
|
10268
10349
|
try {
|
|
10269
10350
|
const bytes = readDeps.readBlobBytesAtRef(repoPath2, baseOid, CANONICAL_MEMORY_DB_PATH);
|
|
10270
|
-
|
|
10351
|
+
writeFileSync16(dbPath, bytes);
|
|
10271
10352
|
} catch (error) {
|
|
10272
10353
|
if (!isMissingCanonicalMemoryBlobError(error)) {
|
|
10273
10354
|
throw error;
|
|
@@ -10425,7 +10506,7 @@ function requireRuntimeMemoryContext(runtimeContext) {
|
|
|
10425
10506
|
}
|
|
10426
10507
|
async function ensureRuntimeMemoryUsable(runtimeContext) {
|
|
10427
10508
|
const memory = requireRuntimeMemoryContext(runtimeContext);
|
|
10428
|
-
if (!
|
|
10509
|
+
if (!existsSync30(memory.hydratedPath)) {
|
|
10429
10510
|
throw new Error(`Shared memory database is missing: ${memory.hydratedPath}`);
|
|
10430
10511
|
}
|
|
10431
10512
|
const db = await openMemoryDb(memory.hydratedPath);
|
|
@@ -10726,8 +10807,8 @@ async function executeHarnessCommand(projectRoot, args, eventBus, pluginHostCtx)
|
|
|
10726
10807
|
}
|
|
10727
10808
|
case "completion-verification":
|
|
10728
10809
|
case "completition-verification": {
|
|
10729
|
-
const hookPath =
|
|
10730
|
-
if (!
|
|
10810
|
+
const hookPath = resolve31(projectRoot, ".rig/bin/hooks/completion-verification");
|
|
10811
|
+
if (!existsSync31(hookPath)) {
|
|
10731
10812
|
throw new Error(`completion-verification hook binary not found: ${hookPath}`);
|
|
10732
10813
|
}
|
|
10733
10814
|
const proc = Bun.spawn([hookPath], {
|
|
@@ -11029,10 +11110,10 @@ function printHelp() {
|
|
|
11029
11110
|
}
|
|
11030
11111
|
|
|
11031
11112
|
// packages/runtime/src/control-plane/native/root-resolver.ts
|
|
11032
|
-
import { existsSync as
|
|
11033
|
-
import { dirname as
|
|
11113
|
+
import { existsSync as existsSync32, readFileSync as readFileSync16 } from "fs";
|
|
11114
|
+
import { dirname as dirname16, parse, resolve as resolve32 } from "path";
|
|
11034
11115
|
function hasProjectMarker(candidate) {
|
|
11035
|
-
return
|
|
11116
|
+
return existsSync32(resolve32(candidate, RIG_DEFINITION_DIRNAME)) || existsSync32(resolve32(candidate, RIG_STATE_DIRNAME));
|
|
11036
11117
|
}
|
|
11037
11118
|
function resolveProjectRoot(options) {
|
|
11038
11119
|
const cwd = options?.cwd || process.cwd();
|
|
@@ -11049,23 +11130,23 @@ function resolveProjectRoot(options) {
|
|
|
11049
11130
|
if (configRoot && hasProjectMarker(configRoot)) {
|
|
11050
11131
|
return configRoot;
|
|
11051
11132
|
}
|
|
11052
|
-
let fileDir =
|
|
11133
|
+
let fileDir = resolve32(fallbackFromDir);
|
|
11053
11134
|
for (let i = 0;i < 5; i += 1) {
|
|
11054
11135
|
if (hasProjectMarker(fileDir)) {
|
|
11055
11136
|
return fileDir;
|
|
11056
11137
|
}
|
|
11057
|
-
fileDir =
|
|
11138
|
+
fileDir = dirname16(fileDir);
|
|
11058
11139
|
}
|
|
11059
11140
|
return cwd;
|
|
11060
11141
|
}
|
|
11061
11142
|
function walkUpForRoot(start) {
|
|
11062
|
-
let searchDir =
|
|
11143
|
+
let searchDir = resolve32(start);
|
|
11063
11144
|
const root = parse(searchDir).root || "/";
|
|
11064
11145
|
while (searchDir !== root) {
|
|
11065
11146
|
if (hasProjectMarker(searchDir)) {
|
|
11066
11147
|
return searchDir;
|
|
11067
11148
|
}
|
|
11068
|
-
searchDir =
|
|
11149
|
+
searchDir = dirname16(searchDir);
|
|
11069
11150
|
}
|
|
11070
11151
|
if (hasProjectMarker(root)) {
|
|
11071
11152
|
return root;
|
|
@@ -11073,12 +11154,12 @@ function walkUpForRoot(start) {
|
|
|
11073
11154
|
return "";
|
|
11074
11155
|
}
|
|
11075
11156
|
function readConfiguredRoot() {
|
|
11076
|
-
const configPath =
|
|
11077
|
-
if (!
|
|
11157
|
+
const configPath = resolve32(process.env.HOME || "~", ".config", "project-rig", "root");
|
|
11158
|
+
if (!existsSync32(configPath)) {
|
|
11078
11159
|
return "";
|
|
11079
11160
|
}
|
|
11080
11161
|
try {
|
|
11081
|
-
const value =
|
|
11162
|
+
const value = readFileSync16(configPath, "utf-8").split(/\r?\n/)[0]?.trim() || "";
|
|
11082
11163
|
return value;
|
|
11083
11164
|
} catch {
|
|
11084
11165
|
return "";
|
|
@@ -11088,9 +11169,9 @@ function readConfiguredRoot() {
|
|
|
11088
11169
|
// packages/runtime/src/control-plane/runtime/events.ts
|
|
11089
11170
|
import { appendFile, mkdir } from "fs/promises";
|
|
11090
11171
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
11091
|
-
import { dirname as
|
|
11172
|
+
import { dirname as dirname17, resolve as resolve33 } from "path";
|
|
11092
11173
|
async function appendEvent(eventsFile, event) {
|
|
11093
|
-
await mkdir(
|
|
11174
|
+
await mkdir(dirname17(eventsFile), { recursive: true });
|
|
11094
11175
|
await appendFile(eventsFile, `${JSON.stringify(event)}
|
|
11095
11176
|
`, "utf-8");
|
|
11096
11177
|
}
|
|
@@ -11152,7 +11233,7 @@ class GeneralCliEventBus {
|
|
|
11152
11233
|
runtimeBuses = new Map;
|
|
11153
11234
|
constructor(options) {
|
|
11154
11235
|
this.runId = options.runId || randomUUID2();
|
|
11155
|
-
this.eventsFile = options.eventsFile ??
|
|
11236
|
+
this.eventsFile = options.eventsFile ?? resolve33(options.projectRoot, ".rig", "logs", "control-plane.events.jsonl");
|
|
11156
11237
|
}
|
|
11157
11238
|
getRunId() {
|
|
11158
11239
|
return this.runId;
|
|
@@ -11205,7 +11286,7 @@ function resolveHarnessPluginMode(options) {
|
|
|
11205
11286
|
async function main() {
|
|
11206
11287
|
const projectRoot = resolveProjectRoot({
|
|
11207
11288
|
cwd: process.cwd(),
|
|
11208
|
-
fallbackFromDir:
|
|
11289
|
+
fallbackFromDir: resolve34(import.meta.dir, "../..")
|
|
11209
11290
|
});
|
|
11210
11291
|
process.env.PROJECT_RIG_ROOT = projectRoot;
|
|
11211
11292
|
process.chdir(projectRoot);
|