@h-rig/runtime 0.0.6-alpha.3 → 0.0.6-alpha.30
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 +1165 -785
- package/dist/bin/rig-agent.js +458 -389
- package/dist/src/control-plane/agent-wrapper.js +1191 -504
- package/dist/src/control-plane/authority-files.js +12 -6
- package/dist/src/control-plane/harness-main.js +2186 -1786
- package/dist/src/control-plane/hooks/completion-verification.js +2084 -1019
- package/dist/src/control-plane/hooks/inject-context.js +193 -139
- package/dist/src/control-plane/hooks/submodule-branch.js +603 -545
- package/dist/src/control-plane/hooks/task-runtime-start.js +603 -545
- package/dist/src/control-plane/materialize-task-config.js +64 -8
- package/dist/src/control-plane/native/git-ops.js +90 -64
- package/dist/src/control-plane/native/harness-cli.js +1989 -682
- package/dist/src/control-plane/native/pr-automation.js +1657 -54
- package/dist/src/control-plane/native/pr-review-gate.js +1455 -0
- package/dist/src/control-plane/native/repo-ops.js +3 -0
- package/dist/src/control-plane/native/run-ops.js +39 -13
- package/dist/src/control-plane/native/task-ops.js +1819 -527
- package/dist/src/control-plane/native/validator.js +163 -109
- package/dist/src/control-plane/native/verifier.js +1616 -323
- package/dist/src/control-plane/native/workspace-ops.js +12 -6
- package/dist/src/control-plane/pi-sessiond/bin.js +793 -0
- package/dist/src/control-plane/pi-sessiond/client.js +41 -0
- package/dist/src/control-plane/pi-sessiond/event-hub.js +59 -0
- package/dist/src/control-plane/pi-sessiond/extension-ui-context.js +198 -0
- package/dist/src/control-plane/pi-sessiond/launcher.js +173 -0
- package/dist/src/control-plane/pi-sessiond/server.js +802 -0
- package/dist/src/control-plane/pi-sessiond/session-service.js +540 -0
- package/dist/src/control-plane/pi-sessiond/types.js +1 -0
- package/dist/src/control-plane/plugin-host-context.js +54 -0
- package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image/index.js +3 -0
- package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image.js +3 -0
- package/dist/src/control-plane/runtime/index.js +517 -722
- package/dist/src/control-plane/runtime/isolation/home.js +28 -6
- package/dist/src/control-plane/runtime/isolation/index.js +541 -461
- package/dist/src/control-plane/runtime/isolation/runner.js +28 -6
- package/dist/src/control-plane/runtime/isolation/shared.js +9 -6
- package/dist/src/control-plane/runtime/isolation.js +541 -461
- package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
- package/dist/src/control-plane/runtime/queue.js +458 -385
- package/dist/src/control-plane/runtime/snapshot/task-run.js +3 -0
- package/dist/src/control-plane/runtime/task-run-snapshot.js +3 -0
- package/dist/src/control-plane/skill-materializer.js +46 -0
- package/dist/src/control-plane/tasks/source-aware-task-config-source.js +14 -2
- package/dist/src/control-plane/tasks/source-lifecycle.js +86 -32
- package/dist/src/index.js +27 -298
- package/dist/src/layout.js +12 -7
- package/dist/src/local-server.js +20 -14
- package/native/darwin-arm64/rig-git +0 -0
- package/native/darwin-arm64/rig-git.build-manifest.json +1 -1
- package/native/darwin-arm64/rig-shell +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +1 -1
- package/native/darwin-arm64/rig-tools +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +1 -1
- package/native/darwin-arm64/runtime-native.dylib +0 -0
- package/package.json +8 -6
- package/dist/src/control-plane/runtime/plugins.js +0 -1131
- package/dist/src/plugins.js +0 -329
package/dist/bin/rig-agent.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// packages/runtime/bin/rig-agent.ts
|
|
5
|
-
import { existsSync as
|
|
6
|
-
import { dirname as dirname17, resolve as
|
|
5
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync17, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
6
|
+
import { dirname as dirname17, resolve as resolve32 } from "path";
|
|
7
7
|
|
|
8
8
|
// packages/runtime/src/control-plane/controlled-bash.ts
|
|
9
9
|
import { readFileSync as readFileSync3 } from "fs";
|
|
@@ -3616,13 +3616,13 @@ class GeneralCliEventBus {
|
|
|
3616
3616
|
}
|
|
3617
3617
|
|
|
3618
3618
|
// packages/runtime/src/control-plane/native/git-ops.ts
|
|
3619
|
-
import { existsSync as
|
|
3620
|
-
import { dirname as dirname14, isAbsolute as isAbsolute2, resolve as
|
|
3619
|
+
import { existsSync as existsSync23, lstatSync, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
|
|
3620
|
+
import { dirname as dirname14, isAbsolute as isAbsolute2, resolve as resolve27 } from "path";
|
|
3621
3621
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3622
3622
|
|
|
3623
3623
|
// packages/runtime/src/control-plane/native/task-ops.ts
|
|
3624
|
-
import { appendFileSync, existsSync as
|
|
3625
|
-
import { resolve as
|
|
3624
|
+
import { appendFileSync, existsSync as existsSync22, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync10 } from "fs";
|
|
3625
|
+
import { resolve as resolve26 } from "path";
|
|
3626
3626
|
|
|
3627
3627
|
// packages/runtime/src/control-plane/runtime/tooling/shell.ts
|
|
3628
3628
|
import { tmpdir as tmpdir4 } from "os";
|
|
@@ -3983,6 +3983,49 @@ function safeReadJson(path) {
|
|
|
3983
3983
|
}
|
|
3984
3984
|
}
|
|
3985
3985
|
|
|
3986
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
3987
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync8, readdirSync, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
3988
|
+
import { resolve as resolve14 } from "path";
|
|
3989
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
3990
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
3991
|
+
function skillDirName(id) {
|
|
3992
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
3993
|
+
}
|
|
3994
|
+
async function materializeSkills(projectRoot, entries) {
|
|
3995
|
+
const skillsRoot = resolve14(projectRoot, ".pi", "skills");
|
|
3996
|
+
if (existsSync11(skillsRoot)) {
|
|
3997
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
3998
|
+
const dir = resolve14(skillsRoot, name);
|
|
3999
|
+
if (existsSync11(resolve14(dir, MARKER_FILENAME))) {
|
|
4000
|
+
rmSync4(dir, { recursive: true, force: true });
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
const written = [];
|
|
4005
|
+
for (const { pluginName, skill } of entries) {
|
|
4006
|
+
const sourcePath = resolve14(projectRoot, skill.path);
|
|
4007
|
+
if (!existsSync11(sourcePath)) {
|
|
4008
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
4009
|
+
continue;
|
|
4010
|
+
}
|
|
4011
|
+
let body;
|
|
4012
|
+
try {
|
|
4013
|
+
await loadSkill(sourcePath);
|
|
4014
|
+
body = readFileSync8(sourcePath, "utf-8");
|
|
4015
|
+
} catch (err) {
|
|
4016
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
4017
|
+
continue;
|
|
4018
|
+
}
|
|
4019
|
+
const dir = resolve14(skillsRoot, skillDirName(skill.id));
|
|
4020
|
+
mkdirSync6(dir, { recursive: true });
|
|
4021
|
+
writeFileSync5(resolve14(dir, "SKILL.md"), body, "utf-8");
|
|
4022
|
+
writeFileSync5(resolve14(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
4023
|
+
`, "utf-8");
|
|
4024
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
4025
|
+
}
|
|
4026
|
+
return written;
|
|
4027
|
+
}
|
|
4028
|
+
|
|
3986
4029
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
3987
4030
|
async function buildPluginHostContext(projectRoot) {
|
|
3988
4031
|
let config;
|
|
@@ -4019,6 +4062,17 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
4019
4062
|
} catch (err) {
|
|
4020
4063
|
console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
4021
4064
|
}
|
|
4065
|
+
try {
|
|
4066
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
4067
|
+
pluginName: plugin.name,
|
|
4068
|
+
skill
|
|
4069
|
+
})));
|
|
4070
|
+
if (skillEntries.length > 0) {
|
|
4071
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
4072
|
+
}
|
|
4073
|
+
} catch (err) {
|
|
4074
|
+
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
4075
|
+
}
|
|
4022
4076
|
return {
|
|
4023
4077
|
config,
|
|
4024
4078
|
pluginHost,
|
|
@@ -4032,12 +4086,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
4032
4086
|
|
|
4033
4087
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
4034
4088
|
import { spawnSync } from "child_process";
|
|
4035
|
-
import { existsSync as
|
|
4036
|
-
import { basename as basename4, join as join3, resolve as
|
|
4089
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
4090
|
+
import { basename as basename4, join as join3, resolve as resolve16 } from "path";
|
|
4037
4091
|
|
|
4038
4092
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
4039
|
-
import { existsSync as
|
|
4040
|
-
import { resolve as
|
|
4093
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
4094
|
+
import { resolve as resolve15 } from "path";
|
|
4041
4095
|
|
|
4042
4096
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
4043
4097
|
async function findTaskById(reader, id) {
|
|
@@ -4060,7 +4114,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
4060
4114
|
}
|
|
4061
4115
|
}
|
|
4062
4116
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
4063
|
-
const configPath = options.configPath ??
|
|
4117
|
+
const configPath = options.configPath ?? resolve15(projectRoot, ".rig", "task-config.json");
|
|
4064
4118
|
const reader = {
|
|
4065
4119
|
async listTasks() {
|
|
4066
4120
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -4071,8 +4125,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
4071
4125
|
};
|
|
4072
4126
|
return reader;
|
|
4073
4127
|
}
|
|
4074
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
4075
|
-
if (!
|
|
4128
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve15(projectRoot, ".rig", "task-config.json")) {
|
|
4129
|
+
if (!existsSync12(configPath)) {
|
|
4076
4130
|
return [];
|
|
4077
4131
|
}
|
|
4078
4132
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -4080,7 +4134,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve14(projectRoot,
|
|
|
4080
4134
|
}
|
|
4081
4135
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
4082
4136
|
try {
|
|
4083
|
-
const parsed = JSON.parse(
|
|
4137
|
+
const parsed = JSON.parse(readFileSync9(configPath, "utf8"));
|
|
4084
4138
|
if (isPlainRecord(parsed)) {
|
|
4085
4139
|
return parsed;
|
|
4086
4140
|
}
|
|
@@ -4164,7 +4218,7 @@ function isPlainRecord(candidate) {
|
|
|
4164
4218
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
4165
4219
|
var FILE_TASK_PATTERN = /\.(task\.)?json$/;
|
|
4166
4220
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
4167
|
-
const configPath = options.configPath ??
|
|
4221
|
+
const configPath = options.configPath ?? resolve16(projectRoot, ".rig", "task-config.json");
|
|
4168
4222
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
4169
4223
|
const spawnFn = options.spawn ?? spawnSync;
|
|
4170
4224
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -4247,10 +4301,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
4247
4301
|
return metadata;
|
|
4248
4302
|
}
|
|
4249
4303
|
function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
4250
|
-
const jsonPath =
|
|
4251
|
-
if (
|
|
4304
|
+
const jsonPath = resolve16(projectRoot, "rig.config.json");
|
|
4305
|
+
if (existsSync13(jsonPath)) {
|
|
4252
4306
|
try {
|
|
4253
|
-
const parsed = JSON.parse(
|
|
4307
|
+
const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
|
|
4254
4308
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
4255
4309
|
const source = parsed.taskSource;
|
|
4256
4310
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -4259,12 +4313,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
|
4259
4313
|
return null;
|
|
4260
4314
|
}
|
|
4261
4315
|
}
|
|
4262
|
-
const tsPath =
|
|
4263
|
-
if (!
|
|
4316
|
+
const tsPath = resolve16(projectRoot, "rig.config.ts");
|
|
4317
|
+
if (!existsSync13(tsPath)) {
|
|
4264
4318
|
return null;
|
|
4265
4319
|
}
|
|
4266
4320
|
try {
|
|
4267
|
-
const source =
|
|
4321
|
+
const source = readFileSync10(tsPath, "utf8");
|
|
4268
4322
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
4269
4323
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
4270
4324
|
if (kind !== "files") {
|
|
@@ -4284,10 +4338,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
4284
4338
|
return isPlainRecord2(entry) ? entry : null;
|
|
4285
4339
|
}
|
|
4286
4340
|
function readRawTaskConfig(configPath) {
|
|
4287
|
-
if (!
|
|
4341
|
+
if (!existsSync13(configPath)) {
|
|
4288
4342
|
return null;
|
|
4289
4343
|
}
|
|
4290
|
-
const parsed = JSON.parse(
|
|
4344
|
+
const parsed = JSON.parse(readFileSync10(configPath, "utf8"));
|
|
4291
4345
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
4292
4346
|
}
|
|
4293
4347
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -4295,12 +4349,12 @@ function stripLegacyTaskConfigMetadata2(raw) {
|
|
|
4295
4349
|
return tasks;
|
|
4296
4350
|
}
|
|
4297
4351
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
4298
|
-
const directory =
|
|
4299
|
-
if (!
|
|
4352
|
+
const directory = resolve16(projectRoot, sourcePath);
|
|
4353
|
+
if (!existsSync13(directory)) {
|
|
4300
4354
|
return [];
|
|
4301
4355
|
}
|
|
4302
4356
|
const tasks = [];
|
|
4303
|
-
for (const name of
|
|
4357
|
+
for (const name of readdirSync2(directory)) {
|
|
4304
4358
|
if (!FILE_TASK_PATTERN.test(name))
|
|
4305
4359
|
continue;
|
|
4306
4360
|
const inferredId = basename4(name).replace(FILE_TASK_PATTERN, "");
|
|
@@ -4311,11 +4365,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
4311
4365
|
return tasks;
|
|
4312
4366
|
}
|
|
4313
4367
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
4314
|
-
const file = findFileBackedTaskFile(
|
|
4368
|
+
const file = findFileBackedTaskFile(resolve16(projectRoot, sourcePath), taskId);
|
|
4315
4369
|
if (!file) {
|
|
4316
4370
|
return null;
|
|
4317
4371
|
}
|
|
4318
|
-
const raw = JSON.parse(
|
|
4372
|
+
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
4319
4373
|
if (!isPlainRecord2(raw)) {
|
|
4320
4374
|
return null;
|
|
4321
4375
|
}
|
|
@@ -4328,17 +4382,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
4328
4382
|
};
|
|
4329
4383
|
}
|
|
4330
4384
|
function findFileBackedTaskFile(directory, taskId) {
|
|
4331
|
-
if (!
|
|
4385
|
+
if (!existsSync13(directory)) {
|
|
4332
4386
|
return null;
|
|
4333
4387
|
}
|
|
4334
|
-
for (const name of
|
|
4388
|
+
for (const name of readdirSync2(directory)) {
|
|
4335
4389
|
if (!FILE_TASK_PATTERN.test(name))
|
|
4336
4390
|
continue;
|
|
4337
4391
|
const file = join3(directory, name);
|
|
4338
4392
|
try {
|
|
4339
4393
|
if (!statSync3(file).isFile())
|
|
4340
4394
|
continue;
|
|
4341
|
-
const raw = JSON.parse(
|
|
4395
|
+
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
4342
4396
|
const inferredId = basename4(file).replace(FILE_TASK_PATTERN, "");
|
|
4343
4397
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
4344
4398
|
if (id === taskId) {
|
|
@@ -4421,8 +4475,8 @@ function githubStatusFor(issue) {
|
|
|
4421
4475
|
return "open";
|
|
4422
4476
|
}
|
|
4423
4477
|
function selectedGitHubEnv() {
|
|
4424
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
4425
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
4478
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
4479
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
4426
4480
|
}
|
|
4427
4481
|
function ghSpawnOptions() {
|
|
4428
4482
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -4498,8 +4552,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
|
|
|
4498
4552
|
}
|
|
4499
4553
|
|
|
4500
4554
|
// packages/runtime/src/control-plane/native/task-state.ts
|
|
4501
|
-
import { existsSync as
|
|
4502
|
-
import { basename as basename6, resolve as
|
|
4555
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12, readdirSync as readdirSync3, statSync as statSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
4556
|
+
import { basename as basename6, resolve as resolve20 } from "path";
|
|
4503
4557
|
|
|
4504
4558
|
// packages/runtime/src/control-plane/state-sync/types.ts
|
|
4505
4559
|
var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
|
|
@@ -4607,38 +4661,38 @@ function readTaskStateMetadataEnvelope(raw) {
|
|
|
4607
4661
|
};
|
|
4608
4662
|
}
|
|
4609
4663
|
// packages/runtime/src/control-plane/state-sync/read.ts
|
|
4610
|
-
import { existsSync as
|
|
4611
|
-
import { resolve as
|
|
4664
|
+
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
|
|
4665
|
+
import { resolve as resolve19 } from "path";
|
|
4612
4666
|
|
|
4613
4667
|
// packages/runtime/src/control-plane/state-sync/repo.ts
|
|
4614
|
-
import { existsSync as
|
|
4615
|
-
import { resolve as
|
|
4668
|
+
import { existsSync as existsSync15 } from "fs";
|
|
4669
|
+
import { resolve as resolve18 } from "path";
|
|
4616
4670
|
|
|
4617
4671
|
// packages/runtime/src/control-plane/repos/layout.ts
|
|
4618
|
-
import { existsSync as
|
|
4619
|
-
import { basename as basename5, dirname as dirname11, join as join4, resolve as
|
|
4672
|
+
import { existsSync as existsSync14 } from "fs";
|
|
4673
|
+
import { basename as basename5, dirname as dirname11, join as join4, resolve as resolve17 } from "path";
|
|
4620
4674
|
function resolveRepoStateDir(projectRoot) {
|
|
4621
|
-
const normalizedProjectRoot =
|
|
4675
|
+
const normalizedProjectRoot = resolve17(projectRoot);
|
|
4622
4676
|
const projectParent = dirname11(normalizedProjectRoot);
|
|
4623
4677
|
if (basename5(projectParent) === ".worktrees") {
|
|
4624
4678
|
const ownerRoot = dirname11(projectParent);
|
|
4625
|
-
const ownerHasRepoMarkers =
|
|
4679
|
+
const ownerHasRepoMarkers = existsSync14(resolve17(ownerRoot, ".git")) || existsSync14(resolve17(ownerRoot, ".rig", "state"));
|
|
4626
4680
|
if (ownerHasRepoMarkers) {
|
|
4627
|
-
return
|
|
4681
|
+
return resolve17(ownerRoot, ".rig", "state");
|
|
4628
4682
|
}
|
|
4629
4683
|
}
|
|
4630
|
-
return
|
|
4684
|
+
return resolve17(projectRoot, ".rig", "state");
|
|
4631
4685
|
}
|
|
4632
4686
|
function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
4633
|
-
const normalizedProjectRoot =
|
|
4687
|
+
const normalizedProjectRoot = resolve17(projectRoot);
|
|
4634
4688
|
const entry = getManagedRepoEntry(repoId);
|
|
4635
4689
|
const stateDir = resolveRepoStateDir(normalizedProjectRoot);
|
|
4636
4690
|
const metadataRelativePath = join4("repos", entry.id);
|
|
4637
|
-
const metadataRoot =
|
|
4691
|
+
const metadataRoot = resolve17(stateDir, metadataRelativePath);
|
|
4638
4692
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
4639
|
-
const runsInsideTaskWorktree = runtimeWorkspace &&
|
|
4693
|
+
const runsInsideTaskWorktree = runtimeWorkspace && resolve17(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname11(normalizedProjectRoot)) === ".worktrees";
|
|
4640
4694
|
const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
|
|
4641
|
-
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ?
|
|
4695
|
+
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve17(process.env[entry.checkoutEnvVar].trim()) : resolve17(normalizedProjectRoot, entry.alias);
|
|
4642
4696
|
return {
|
|
4643
4697
|
projectRoot: normalizedProjectRoot,
|
|
4644
4698
|
repoId: entry.id,
|
|
@@ -4646,12 +4700,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
|
4646
4700
|
defaultBranch: entry.defaultBranch,
|
|
4647
4701
|
remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
|
|
4648
4702
|
checkoutRoot,
|
|
4649
|
-
worktreesRoot:
|
|
4703
|
+
worktreesRoot: resolve17(checkoutRoot, ".worktrees"),
|
|
4650
4704
|
stateDir,
|
|
4651
4705
|
metadataRoot,
|
|
4652
4706
|
metadataRelativePath,
|
|
4653
|
-
mirrorRoot:
|
|
4654
|
-
mirrorStatePath:
|
|
4707
|
+
mirrorRoot: resolve17(metadataRoot, "mirror.git"),
|
|
4708
|
+
mirrorStatePath: resolve17(metadataRoot, "mirror-state.json"),
|
|
4655
4709
|
mirrorStateRelativePath: join4(metadataRelativePath, "mirror-state.json")
|
|
4656
4710
|
};
|
|
4657
4711
|
}
|
|
@@ -4673,7 +4727,7 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
4673
4727
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
4674
4728
|
try {
|
|
4675
4729
|
const layout = resolveMonorepoRepoLayout(projectRoot);
|
|
4676
|
-
if (
|
|
4730
|
+
if (existsSync15(resolve18(layout.mirrorRoot, "HEAD"))) {
|
|
4677
4731
|
return layout.mirrorRoot;
|
|
4678
4732
|
}
|
|
4679
4733
|
} catch {}
|
|
@@ -4684,8 +4738,8 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
4684
4738
|
var DEFAULT_READ_DEPS2 = {
|
|
4685
4739
|
fetchRef: nativeFetchRef,
|
|
4686
4740
|
readBlobAtRef: nativeReadBlobAtRef,
|
|
4687
|
-
exists:
|
|
4688
|
-
readFile: (path) =>
|
|
4741
|
+
exists: existsSync16,
|
|
4742
|
+
readFile: (path) => readFileSync11(path, "utf8")
|
|
4689
4743
|
};
|
|
4690
4744
|
function parseIssueStatus(rawStatus) {
|
|
4691
4745
|
const normalized = normalizeTaskLifecycleStatus(rawStatus);
|
|
@@ -4766,12 +4820,12 @@ function shouldPreferLocalTrackerState(options) {
|
|
|
4766
4820
|
if (runtimeContextPath) {
|
|
4767
4821
|
return true;
|
|
4768
4822
|
}
|
|
4769
|
-
return
|
|
4823
|
+
return existsSync16(resolve19(runtimeWorkspace, ".rig", "runtime-context.json"));
|
|
4770
4824
|
}
|
|
4771
4825
|
function readLocalTrackerState(projectRoot, deps) {
|
|
4772
4826
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
4773
|
-
const issuesPath =
|
|
4774
|
-
const taskStatePath =
|
|
4827
|
+
const issuesPath = resolve19(monorepoRoot, ".beads", "issues.jsonl");
|
|
4828
|
+
const taskStatePath = resolve19(monorepoRoot, ".beads", "task-state.json");
|
|
4775
4829
|
return projectSyncedTrackerSnapshot({
|
|
4776
4830
|
source: "local",
|
|
4777
4831
|
issuesBaseOid: null,
|
|
@@ -4833,7 +4887,7 @@ function readValidationDescriptions(projectRoot) {
|
|
|
4833
4887
|
return readValidationDescriptionMap(raw);
|
|
4834
4888
|
}
|
|
4835
4889
|
function readSourceValidationDescriptions(projectRoot) {
|
|
4836
|
-
const rootRaw = readJsonFile(
|
|
4890
|
+
const rootRaw = readJsonFile(resolve20(projectRoot, "rig", "task-config.json"), {});
|
|
4837
4891
|
const sourcePath = findSourceTaskConfigPath(projectRoot);
|
|
4838
4892
|
const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
|
|
4839
4893
|
const rootDescriptions = readValidationDescriptionMap(rootRaw);
|
|
@@ -4909,15 +4963,15 @@ function readValidationDescriptionsFromMeta(meta) {
|
|
|
4909
4963
|
return meta.validation_descriptions;
|
|
4910
4964
|
}
|
|
4911
4965
|
function readLocalSourceTaskStateEnvelope(projectRoot) {
|
|
4912
|
-
const taskStatePath =
|
|
4966
|
+
const taskStatePath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
|
|
4913
4967
|
return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
|
|
4914
4968
|
}
|
|
4915
4969
|
function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
|
|
4916
|
-
const issuesPath =
|
|
4917
|
-
if (!
|
|
4970
|
+
const issuesPath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
4971
|
+
if (!existsSync17(issuesPath)) {
|
|
4918
4972
|
return null;
|
|
4919
4973
|
}
|
|
4920
|
-
for (const line of
|
|
4974
|
+
for (const line of readFileSync12(issuesPath, "utf8").split(/\r?\n/)) {
|
|
4921
4975
|
const trimmed = line.trim();
|
|
4922
4976
|
if (!trimmed) {
|
|
4923
4977
|
continue;
|
|
@@ -4958,25 +5012,25 @@ function lookupTask(projectRoot, input) {
|
|
|
4958
5012
|
function artifactDirForId(projectRoot, id) {
|
|
4959
5013
|
const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
4960
5014
|
if (workspaceDir) {
|
|
4961
|
-
const worktreeArtifacts =
|
|
4962
|
-
if (
|
|
5015
|
+
const worktreeArtifacts = resolve20(workspaceDir, "artifacts", id);
|
|
5016
|
+
if (existsSync17(worktreeArtifacts) || existsSync17(resolve20(workspaceDir, "artifacts"))) {
|
|
4963
5017
|
return worktreeArtifacts;
|
|
4964
5018
|
}
|
|
4965
5019
|
}
|
|
4966
5020
|
try {
|
|
4967
5021
|
const paths = resolveHarnessPaths(projectRoot);
|
|
4968
|
-
return
|
|
5022
|
+
return resolve20(paths.artifactsDir, id);
|
|
4969
5023
|
} catch {
|
|
4970
|
-
return
|
|
5024
|
+
return resolve20(resolveMonorepoRoot2(projectRoot), "artifacts", id);
|
|
4971
5025
|
}
|
|
4972
5026
|
}
|
|
4973
5027
|
function resolveTaskConfigPath(projectRoot) {
|
|
4974
5028
|
const paths = resolveHarnessPaths(projectRoot);
|
|
4975
|
-
if (
|
|
5029
|
+
if (existsSync17(paths.taskConfigPath)) {
|
|
4976
5030
|
return paths.taskConfigPath;
|
|
4977
5031
|
}
|
|
4978
5032
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
4979
|
-
if (
|
|
5033
|
+
if (existsSync17(candidate)) {
|
|
4980
5034
|
return candidate;
|
|
4981
5035
|
}
|
|
4982
5036
|
}
|
|
@@ -4984,7 +5038,7 @@ function resolveTaskConfigPath(projectRoot) {
|
|
|
4984
5038
|
}
|
|
4985
5039
|
function findSourceTaskConfigPath(projectRoot) {
|
|
4986
5040
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
4987
|
-
if (
|
|
5041
|
+
if (existsSync17(candidate)) {
|
|
4988
5042
|
return candidate;
|
|
4989
5043
|
}
|
|
4990
5044
|
}
|
|
@@ -4997,7 +5051,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
|
|
|
4997
5051
|
const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
|
|
4998
5052
|
if (sourcePath && synced.updated) {
|
|
4999
5053
|
try {
|
|
5000
|
-
|
|
5054
|
+
writeFileSync7(sourcePath, `${JSON.stringify(synced.config, null, 2)}
|
|
5001
5055
|
`, "utf-8");
|
|
5002
5056
|
} catch {}
|
|
5003
5057
|
}
|
|
@@ -5049,12 +5103,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
|
|
|
5049
5103
|
return !candidate.role;
|
|
5050
5104
|
}
|
|
5051
5105
|
function readSourceIssueRecords(projectRoot) {
|
|
5052
|
-
const issuesPath =
|
|
5053
|
-
if (!
|
|
5106
|
+
const issuesPath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
5107
|
+
if (!existsSync17(issuesPath)) {
|
|
5054
5108
|
return [];
|
|
5055
5109
|
}
|
|
5056
5110
|
const records = [];
|
|
5057
|
-
for (const line of
|
|
5111
|
+
for (const line of readFileSync12(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
5058
5112
|
const trimmed = line.trim();
|
|
5059
5113
|
if (!trimmed) {
|
|
5060
5114
|
continue;
|
|
@@ -5110,19 +5164,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
|
|
|
5110
5164
|
if (!sourcePath) {
|
|
5111
5165
|
return {};
|
|
5112
5166
|
}
|
|
5113
|
-
const directory =
|
|
5114
|
-
if (!
|
|
5167
|
+
const directory = resolve20(projectRoot, sourcePath);
|
|
5168
|
+
if (!existsSync17(directory)) {
|
|
5115
5169
|
return {};
|
|
5116
5170
|
}
|
|
5117
5171
|
const config = {};
|
|
5118
|
-
for (const name of
|
|
5172
|
+
for (const name of readdirSync3(directory)) {
|
|
5119
5173
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
5120
5174
|
continue;
|
|
5121
|
-
const file =
|
|
5175
|
+
const file = resolve20(directory, name);
|
|
5122
5176
|
try {
|
|
5123
5177
|
if (!statSync4(file).isFile())
|
|
5124
5178
|
continue;
|
|
5125
|
-
const raw = JSON.parse(
|
|
5179
|
+
const raw = JSON.parse(readFileSync12(file, "utf8"));
|
|
5126
5180
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
5127
5181
|
continue;
|
|
5128
5182
|
const record = raw;
|
|
@@ -5164,10 +5218,10 @@ function firstStringList2(...candidates) {
|
|
|
5164
5218
|
return [];
|
|
5165
5219
|
}
|
|
5166
5220
|
function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
5167
|
-
const jsonPath =
|
|
5168
|
-
if (
|
|
5221
|
+
const jsonPath = resolve20(projectRoot, "rig.config.json");
|
|
5222
|
+
if (existsSync17(jsonPath)) {
|
|
5169
5223
|
try {
|
|
5170
|
-
const parsed = JSON.parse(
|
|
5224
|
+
const parsed = JSON.parse(readFileSync12(jsonPath, "utf8"));
|
|
5171
5225
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5172
5226
|
const taskSource = parsed.taskSource;
|
|
5173
5227
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -5179,12 +5233,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
5179
5233
|
return null;
|
|
5180
5234
|
}
|
|
5181
5235
|
}
|
|
5182
|
-
const tsPath =
|
|
5183
|
-
if (!
|
|
5236
|
+
const tsPath = resolve20(projectRoot, "rig.config.ts");
|
|
5237
|
+
if (!existsSync17(tsPath)) {
|
|
5184
5238
|
return null;
|
|
5185
5239
|
}
|
|
5186
5240
|
try {
|
|
5187
|
-
const source =
|
|
5241
|
+
const source = readFileSync12(tsPath, "utf8");
|
|
5188
5242
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
5189
5243
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
5190
5244
|
if (kind !== "files") {
|
|
@@ -5198,23 +5252,23 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
5198
5252
|
function sourceTaskConfigCandidates(projectRoot) {
|
|
5199
5253
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
5200
5254
|
return [
|
|
5201
|
-
runtimeContext?.monorepoMainRoot ?
|
|
5202
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
5203
|
-
|
|
5255
|
+
runtimeContext?.monorepoMainRoot ? resolve20(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
5256
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve20(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
5257
|
+
resolve20(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
|
|
5204
5258
|
].filter(Boolean);
|
|
5205
5259
|
}
|
|
5206
5260
|
|
|
5207
5261
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
5208
|
-
import { existsSync as
|
|
5209
|
-
import { resolve as
|
|
5262
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
5263
|
+
import { resolve as resolve25 } from "path";
|
|
5210
5264
|
|
|
5211
5265
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
5212
|
-
import { existsSync as
|
|
5213
|
-
import { dirname as dirname13, resolve as
|
|
5266
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync8, rmSync as rmSync6, statSync as statSync5 } from "fs";
|
|
5267
|
+
import { dirname as dirname13, resolve as resolve24 } from "path";
|
|
5214
5268
|
|
|
5215
5269
|
// packages/runtime/src/binary-run.ts
|
|
5216
|
-
import { chmodSync as chmodSync2, cpSync, existsSync as
|
|
5217
|
-
import { basename as basename7, dirname as dirname12, resolve as
|
|
5270
|
+
import { chmodSync as chmodSync2, cpSync, existsSync as existsSync18, mkdirSync as mkdirSync7, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "fs";
|
|
5271
|
+
import { basename as basename7, dirname as dirname12, resolve as resolve21 } from "path";
|
|
5218
5272
|
import { fileURLToPath } from "url";
|
|
5219
5273
|
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
5220
5274
|
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
@@ -5240,9 +5294,9 @@ async function buildRuntimeBinary(options) {
|
|
|
5240
5294
|
});
|
|
5241
5295
|
}
|
|
5242
5296
|
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
5243
|
-
const tempBuildDir =
|
|
5244
|
-
const tempOutputPath =
|
|
5245
|
-
|
|
5297
|
+
const tempBuildDir = resolve21(dirname12(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
5298
|
+
const tempOutputPath = resolve21(tempBuildDir, basename7(options.outputPath));
|
|
5299
|
+
mkdirSync7(tempBuildDir, { recursive: true });
|
|
5246
5300
|
await withTemporaryEnv({
|
|
5247
5301
|
...options.env,
|
|
5248
5302
|
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
@@ -5267,7 +5321,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
5267
5321
|
`);
|
|
5268
5322
|
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
5269
5323
|
}
|
|
5270
|
-
if (!
|
|
5324
|
+
if (!existsSync18(tempOutputPath)) {
|
|
5271
5325
|
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
5272
5326
|
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
5273
5327
|
}
|
|
@@ -5282,7 +5336,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
5282
5336
|
});
|
|
5283
5337
|
}
|
|
5284
5338
|
})).finally(() => {
|
|
5285
|
-
|
|
5339
|
+
rmSync5(tempBuildDir, { recursive: true, force: true });
|
|
5286
5340
|
});
|
|
5287
5341
|
}
|
|
5288
5342
|
function runBestEffortBuildGc() {
|
|
@@ -5299,8 +5353,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
|
|
|
5299
5353
|
function resolveRuntimeBinaryBuildOptions(options) {
|
|
5300
5354
|
return {
|
|
5301
5355
|
...options,
|
|
5302
|
-
entrypoint:
|
|
5303
|
-
outputPath:
|
|
5356
|
+
entrypoint: resolve21(options.cwd, options.sourcePath),
|
|
5357
|
+
outputPath: resolve21(options.outputPath)
|
|
5304
5358
|
};
|
|
5305
5359
|
}
|
|
5306
5360
|
function shouldUseRuntimeBinaryBuildWorker() {
|
|
@@ -5314,7 +5368,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
|
|
|
5314
5368
|
}
|
|
5315
5369
|
async function buildRuntimeBinaryViaWorker(options) {
|
|
5316
5370
|
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
5317
|
-
if (!workerSourcePath || !
|
|
5371
|
+
if (!workerSourcePath || !existsSync18(workerSourcePath)) {
|
|
5318
5372
|
await buildRuntimeBinaryInProcess(options, {
|
|
5319
5373
|
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
5320
5374
|
buildKey: createRuntimeBinaryBuildKey({
|
|
@@ -5345,13 +5399,13 @@ async function buildRuntimeBinaryViaWorker(options) {
|
|
|
5345
5399
|
new Response(build.stdout).text(),
|
|
5346
5400
|
new Response(build.stderr).text()
|
|
5347
5401
|
]);
|
|
5348
|
-
|
|
5402
|
+
rmSync5(payloadPath, { force: true });
|
|
5349
5403
|
if (exitCode !== 0) {
|
|
5350
5404
|
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
5351
5405
|
}
|
|
5352
5406
|
}
|
|
5353
5407
|
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
5354
|
-
return
|
|
5408
|
+
return resolve21(dirname12(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
5355
5409
|
}
|
|
5356
5410
|
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
5357
5411
|
const envRoots = [
|
|
@@ -5360,13 +5414,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
|
5360
5414
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
5361
5415
|
].filter(Boolean);
|
|
5362
5416
|
for (const root of envRoots) {
|
|
5363
|
-
const candidate =
|
|
5364
|
-
if (
|
|
5417
|
+
const candidate = resolve21(root, "packages/runtime/src/binary-build-worker.ts");
|
|
5418
|
+
if (existsSync18(candidate)) {
|
|
5365
5419
|
return candidate;
|
|
5366
5420
|
}
|
|
5367
5421
|
}
|
|
5368
|
-
const localCandidate =
|
|
5369
|
-
return
|
|
5422
|
+
const localCandidate = resolve21(import.meta.dir, "binary-build-worker.ts");
|
|
5423
|
+
return existsSync18(localCandidate) ? localCandidate : null;
|
|
5370
5424
|
}
|
|
5371
5425
|
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
5372
5426
|
const bunPath = Bun.which("bun");
|
|
@@ -5402,7 +5456,7 @@ function createRuntimeBinaryBuildKey(input) {
|
|
|
5402
5456
|
});
|
|
5403
5457
|
}
|
|
5404
5458
|
async function isRuntimeBinaryBuildFresh(input) {
|
|
5405
|
-
if (!
|
|
5459
|
+
if (!existsSync18(input.outputPath) || !existsSync18(input.manifestPath)) {
|
|
5406
5460
|
return false;
|
|
5407
5461
|
}
|
|
5408
5462
|
let manifest = null;
|
|
@@ -5415,7 +5469,7 @@ async function isRuntimeBinaryBuildFresh(input) {
|
|
|
5415
5469
|
return false;
|
|
5416
5470
|
}
|
|
5417
5471
|
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
5418
|
-
if (!
|
|
5472
|
+
if (!existsSync18(filePath)) {
|
|
5419
5473
|
return false;
|
|
5420
5474
|
}
|
|
5421
5475
|
if (await sha256File(filePath) !== expectedDigest) {
|
|
@@ -5428,7 +5482,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
|
|
|
5428
5482
|
const inputs = {};
|
|
5429
5483
|
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
5430
5484
|
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
5431
|
-
if (!normalized || !
|
|
5485
|
+
if (!normalized || !existsSync18(normalized)) {
|
|
5432
5486
|
continue;
|
|
5433
5487
|
}
|
|
5434
5488
|
inputs[normalized] = await sha256File(normalized);
|
|
@@ -5451,7 +5505,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
|
|
|
5451
5505
|
if (inputPath.startsWith("<")) {
|
|
5452
5506
|
return null;
|
|
5453
5507
|
}
|
|
5454
|
-
return
|
|
5508
|
+
return resolve21(cwd, inputPath);
|
|
5455
5509
|
}
|
|
5456
5510
|
async function sha256File(path) {
|
|
5457
5511
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
@@ -5467,8 +5521,8 @@ function sortRecord(value) {
|
|
|
5467
5521
|
async function runSerializedRuntimeBinaryBuild(action) {
|
|
5468
5522
|
const previous = runtimeBinaryBuildQueue;
|
|
5469
5523
|
let release;
|
|
5470
|
-
runtimeBinaryBuildQueue = new Promise((
|
|
5471
|
-
release =
|
|
5524
|
+
runtimeBinaryBuildQueue = new Promise((resolve22) => {
|
|
5525
|
+
release = resolve22;
|
|
5472
5526
|
});
|
|
5473
5527
|
await previous;
|
|
5474
5528
|
try {
|
|
@@ -5513,11 +5567,11 @@ async function withTemporaryCwd(cwd, action) {
|
|
|
5513
5567
|
}
|
|
5514
5568
|
|
|
5515
5569
|
// packages/runtime/src/control-plane/runtime/provisioning-env.ts
|
|
5516
|
-
import { delimiter, resolve as
|
|
5570
|
+
import { delimiter, resolve as resolve23 } from "path";
|
|
5517
5571
|
|
|
5518
5572
|
// packages/runtime/src/control-plane/runtime/runtime-paths.ts
|
|
5519
|
-
import { existsSync as
|
|
5520
|
-
import { resolve as
|
|
5573
|
+
import { existsSync as existsSync19, readdirSync as readdirSync4, realpathSync } from "fs";
|
|
5574
|
+
import { resolve as resolve22 } from "path";
|
|
5521
5575
|
|
|
5522
5576
|
// packages/runtime/src/control-plane/runtime/sandbox/utils.ts
|
|
5523
5577
|
function uniq(values) {
|
|
@@ -5535,7 +5589,7 @@ function resolveBunBinaryPath() {
|
|
|
5535
5589
|
}
|
|
5536
5590
|
const home = process.env.HOME?.trim();
|
|
5537
5591
|
const fallbackCandidates = [
|
|
5538
|
-
home ?
|
|
5592
|
+
home ? resolve22(home, ".bun/bin/bun") : "",
|
|
5539
5593
|
"/opt/homebrew/bin/bun",
|
|
5540
5594
|
"/usr/local/bin/bun",
|
|
5541
5595
|
"/usr/bin/bun"
|
|
@@ -5563,8 +5617,8 @@ function resolveClaudeBinaryPath() {
|
|
|
5563
5617
|
}
|
|
5564
5618
|
const home = process.env.HOME?.trim();
|
|
5565
5619
|
const fallbackCandidates = [
|
|
5566
|
-
home ?
|
|
5567
|
-
home ?
|
|
5620
|
+
home ? resolve22(home, ".local/bin/claude") : "",
|
|
5621
|
+
home ? resolve22(home, ".local/share/claude/local/claude") : "",
|
|
5568
5622
|
"/opt/homebrew/bin/claude",
|
|
5569
5623
|
"/usr/local/bin/claude",
|
|
5570
5624
|
"/usr/bin/claude"
|
|
@@ -5578,51 +5632,51 @@ function resolveClaudeBinaryPath() {
|
|
|
5578
5632
|
throw new Error("claude not found in PATH");
|
|
5579
5633
|
}
|
|
5580
5634
|
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
5581
|
-
return
|
|
5635
|
+
return resolve22(bunBinaryPath, "../..");
|
|
5582
5636
|
}
|
|
5583
5637
|
function resolveClaudeInstallDir() {
|
|
5584
5638
|
const realPath = resolveClaudeBinaryPath();
|
|
5585
|
-
return
|
|
5639
|
+
return resolve22(realPath, "..");
|
|
5586
5640
|
}
|
|
5587
5641
|
function resolveNodeInstallDir() {
|
|
5588
5642
|
const preferredNode = resolvePreferredNodeBinary();
|
|
5589
5643
|
if (!preferredNode)
|
|
5590
5644
|
return null;
|
|
5591
5645
|
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
5592
|
-
if (explicitNode &&
|
|
5593
|
-
return preferredNode.endsWith("/bin/node") ?
|
|
5646
|
+
if (explicitNode && resolve22(explicitNode) === resolve22(preferredNode)) {
|
|
5647
|
+
return preferredNode.endsWith("/bin/node") ? resolve22(preferredNode, "../..") : resolve22(preferredNode, "..");
|
|
5594
5648
|
}
|
|
5595
5649
|
try {
|
|
5596
5650
|
const realPath = realpathSync(preferredNode);
|
|
5597
5651
|
if (realPath.endsWith("/bin/node")) {
|
|
5598
|
-
return
|
|
5652
|
+
return resolve22(realPath, "../..");
|
|
5599
5653
|
}
|
|
5600
|
-
return
|
|
5654
|
+
return resolve22(realPath, "..");
|
|
5601
5655
|
} catch {
|
|
5602
|
-
return
|
|
5656
|
+
return resolve22(preferredNode, "..");
|
|
5603
5657
|
}
|
|
5604
5658
|
}
|
|
5605
5659
|
function resolvePreferredNodeBinary() {
|
|
5606
5660
|
const candidates = [];
|
|
5607
5661
|
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
5608
5662
|
if (envNode) {
|
|
5609
|
-
const explicit =
|
|
5610
|
-
if (
|
|
5663
|
+
const explicit = resolve22(envNode);
|
|
5664
|
+
if (existsSync19(explicit)) {
|
|
5611
5665
|
return explicit;
|
|
5612
5666
|
}
|
|
5613
5667
|
}
|
|
5614
5668
|
const nvmBin = process.env.NVM_BIN?.trim();
|
|
5615
5669
|
if (nvmBin) {
|
|
5616
|
-
candidates.push(
|
|
5670
|
+
candidates.push(resolve22(nvmBin, "node"));
|
|
5617
5671
|
}
|
|
5618
5672
|
const home = process.env.HOME?.trim();
|
|
5619
5673
|
if (home) {
|
|
5620
|
-
const nvmVersionsDir =
|
|
5621
|
-
if (
|
|
5674
|
+
const nvmVersionsDir = resolve22(home, ".nvm/versions/node");
|
|
5675
|
+
if (existsSync19(nvmVersionsDir)) {
|
|
5622
5676
|
try {
|
|
5623
|
-
const versionDirs =
|
|
5677
|
+
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/, "")));
|
|
5624
5678
|
for (const versionDir of versionDirs) {
|
|
5625
|
-
candidates.push(
|
|
5679
|
+
candidates.push(resolve22(nvmVersionsDir, versionDir, "bin/node"));
|
|
5626
5680
|
}
|
|
5627
5681
|
} catch {}
|
|
5628
5682
|
}
|
|
@@ -5631,8 +5685,8 @@ function resolvePreferredNodeBinary() {
|
|
|
5631
5685
|
if (whichNode) {
|
|
5632
5686
|
candidates.push(whichNode);
|
|
5633
5687
|
}
|
|
5634
|
-
const deduped = uniq(candidates.map((candidate) =>
|
|
5635
|
-
const existing = deduped.filter((candidate) =>
|
|
5688
|
+
const deduped = uniq(candidates.map((candidate) => resolve22(candidate)));
|
|
5689
|
+
const existing = deduped.filter((candidate) => existsSync19(candidate));
|
|
5636
5690
|
if (existing.length === 0) {
|
|
5637
5691
|
return null;
|
|
5638
5692
|
}
|
|
@@ -5646,7 +5700,7 @@ function resolvePreferredNodeBinary() {
|
|
|
5646
5700
|
return existing[0] ?? null;
|
|
5647
5701
|
}
|
|
5648
5702
|
function inferNodeMajor(nodeBinaryPath) {
|
|
5649
|
-
const normalized =
|
|
5703
|
+
const normalized = resolve22(nodeBinaryPath).replace(/\\/g, "/");
|
|
5650
5704
|
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
5651
5705
|
if (!match) {
|
|
5652
5706
|
return null;
|
|
@@ -5658,8 +5712,8 @@ function normalizeExecutablePath(candidate) {
|
|
|
5658
5712
|
if (!candidate) {
|
|
5659
5713
|
return "";
|
|
5660
5714
|
}
|
|
5661
|
-
const normalized =
|
|
5662
|
-
if (!
|
|
5715
|
+
const normalized = resolve22(candidate);
|
|
5716
|
+
if (!existsSync19(normalized)) {
|
|
5663
5717
|
return "";
|
|
5664
5718
|
}
|
|
5665
5719
|
try {
|
|
@@ -5669,7 +5723,7 @@ function normalizeExecutablePath(candidate) {
|
|
|
5669
5723
|
}
|
|
5670
5724
|
}
|
|
5671
5725
|
function looksLikeRuntimeGateway(candidate) {
|
|
5672
|
-
const normalized =
|
|
5726
|
+
const normalized = resolve22(candidate).replace(/\\/g, "/");
|
|
5673
5727
|
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
5674
5728
|
}
|
|
5675
5729
|
|
|
@@ -5690,7 +5744,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5690
5744
|
try {
|
|
5691
5745
|
return resolveClaudeInstallDir();
|
|
5692
5746
|
} catch {
|
|
5693
|
-
return
|
|
5747
|
+
return resolve23(claudeBinary, "..");
|
|
5694
5748
|
}
|
|
5695
5749
|
})() : "";
|
|
5696
5750
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -5700,8 +5754,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5700
5754
|
`${bunDir}/bin`,
|
|
5701
5755
|
claudeDir,
|
|
5702
5756
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
5703
|
-
realHome ?
|
|
5704
|
-
realHome ?
|
|
5757
|
+
realHome ? resolve23(realHome, ".local/bin") : "",
|
|
5758
|
+
realHome ? resolve23(realHome, ".cargo/bin") : "",
|
|
5705
5759
|
...inheritedPath,
|
|
5706
5760
|
"/usr/local/bin",
|
|
5707
5761
|
"/usr/local/sbin",
|
|
@@ -5732,9 +5786,9 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5732
5786
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
5733
5787
|
function resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext) {
|
|
5734
5788
|
if (runtimeContext) {
|
|
5735
|
-
return
|
|
5789
|
+
return resolve24(runtimeContext.binDir, "validators", binaryName);
|
|
5736
5790
|
}
|
|
5737
|
-
return
|
|
5791
|
+
return resolve24(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
|
|
5738
5792
|
}
|
|
5739
5793
|
async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
5740
5794
|
const match = checkId.match(/^([a-z][\w-]*):([a-z][\w-]*)$/);
|
|
@@ -5749,19 +5803,19 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
5749
5803
|
const binaryName = `${category}-${check}`;
|
|
5750
5804
|
const binaryPath = resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
5751
5805
|
const hostProjectRoot = runtimeContext?.hostProjectRoot?.trim() || projectRoot;
|
|
5752
|
-
const sourcePath =
|
|
5753
|
-
if (!
|
|
5806
|
+
const sourcePath = resolve24(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
|
|
5807
|
+
if (!existsSync20(sourcePath)) {
|
|
5754
5808
|
return null;
|
|
5755
5809
|
}
|
|
5756
5810
|
const sourceMtime = statSync5(sourcePath).mtimeMs;
|
|
5757
|
-
const binaryExists =
|
|
5811
|
+
const binaryExists = existsSync20(binaryPath);
|
|
5758
5812
|
const binaryMtime = binaryExists ? statSync5(binaryPath).mtimeMs : 0;
|
|
5759
5813
|
if (!binaryExists || sourceMtime > binaryMtime) {
|
|
5760
5814
|
if (binaryExists) {
|
|
5761
|
-
|
|
5762
|
-
|
|
5815
|
+
rmSync6(binaryPath, { force: true });
|
|
5816
|
+
rmSync6(`${binaryPath}.build-manifest.json`, { force: true });
|
|
5763
5817
|
}
|
|
5764
|
-
|
|
5818
|
+
mkdirSync8(dirname13(binaryPath), { recursive: true });
|
|
5765
5819
|
await buildRuntimeBinary({
|
|
5766
5820
|
sourcePath: `packages/runtime/src/control-plane/validators/${category}/${check}.ts`,
|
|
5767
5821
|
outputPath: binaryPath,
|
|
@@ -5770,7 +5824,7 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
5770
5824
|
env: runtimeProvisioningEnv()
|
|
5771
5825
|
});
|
|
5772
5826
|
}
|
|
5773
|
-
return
|
|
5827
|
+
return existsSync20(binaryPath) ? binaryPath : null;
|
|
5774
5828
|
}
|
|
5775
5829
|
|
|
5776
5830
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
@@ -5807,20 +5861,20 @@ async function readTaskSourceValidation(projectRoot, taskId) {
|
|
|
5807
5861
|
function resolveValidationPaths(projectRoot, taskId, runtimeContext) {
|
|
5808
5862
|
if (runtimeContext) {
|
|
5809
5863
|
return {
|
|
5810
|
-
taskLogDir:
|
|
5811
|
-
artifactDir:
|
|
5864
|
+
taskLogDir: resolve25(runtimeContext.logsDir, taskId),
|
|
5865
|
+
artifactDir: resolve25(runtimeContext.workspaceDir, "artifacts", taskId)
|
|
5812
5866
|
};
|
|
5813
5867
|
}
|
|
5814
5868
|
const paths = resolveHarnessPaths(projectRoot);
|
|
5815
5869
|
return {
|
|
5816
|
-
taskLogDir:
|
|
5817
|
-
artifactDir:
|
|
5870
|
+
taskLogDir: resolve25(paths.logsDir, taskId),
|
|
5871
|
+
artifactDir: resolve25(paths.artifactsDir, taskId)
|
|
5818
5872
|
};
|
|
5819
5873
|
}
|
|
5820
5874
|
async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext) {
|
|
5821
5875
|
const binaryName = checkId.replace(":", "-");
|
|
5822
5876
|
const binaryPath = await ensureValidatorBinary(projectRoot, checkId, runtimeContext) ?? resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
5823
|
-
if (!
|
|
5877
|
+
if (!existsSync21(binaryPath)) {
|
|
5824
5878
|
return {
|
|
5825
5879
|
result: {
|
|
5826
5880
|
id: checkId,
|
|
@@ -5831,7 +5885,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
5831
5885
|
};
|
|
5832
5886
|
}
|
|
5833
5887
|
const validatorCwd = runtimeContext?.workspaceDir || resolveMonorepoRoot(projectRoot);
|
|
5834
|
-
const runtimeShellPath = runtimeContext ?
|
|
5888
|
+
const runtimeShellPath = runtimeContext ? resolve25(runtimeContext.binDir, "rig-shell") : "";
|
|
5835
5889
|
const monorepoMainRoot = runtimeContext?.monorepoMainRoot || process.env.MONOREPO_MAIN_ROOT?.trim() || resolveMonorepoRoot(projectRoot);
|
|
5836
5890
|
const validatorEnv = {
|
|
5837
5891
|
PROJECT_RIG_ROOT: runtimeContext?.hostProjectRoot || projectRoot,
|
|
@@ -5846,7 +5900,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
5846
5900
|
validatorEnv.RIG_LOGS_DIR = runtimeContext.logsDir;
|
|
5847
5901
|
validatorEnv.RIG_RUNTIME_BIN_DIR = runtimeContext.binDir;
|
|
5848
5902
|
}
|
|
5849
|
-
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath &&
|
|
5903
|
+
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync21(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
|
|
5850
5904
|
try {
|
|
5851
5905
|
const result = JSON.parse(stdout.trim());
|
|
5852
5906
|
return { result, exitCode };
|
|
@@ -5886,8 +5940,8 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
5886
5940
|
const configuredValidation = stringArray(taskConfig[taskId]?.validation);
|
|
5887
5941
|
const commands = resolvedContext?.validation?.length ? resolvedContext.validation : configuredValidation.length > 0 ? configuredValidation : sourceValidation.validation;
|
|
5888
5942
|
const { taskLogDir, artifactDir } = resolveValidationPaths(projectRoot, taskId, resolvedContext);
|
|
5889
|
-
|
|
5890
|
-
|
|
5943
|
+
mkdirSync9(taskLogDir, { recursive: true });
|
|
5944
|
+
mkdirSync9(artifactDir, { recursive: true });
|
|
5891
5945
|
if (commands.length === 0) {
|
|
5892
5946
|
const skipped = {
|
|
5893
5947
|
status: "skipped",
|
|
@@ -5896,7 +5950,7 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
5896
5950
|
failed: 0,
|
|
5897
5951
|
categories: []
|
|
5898
5952
|
};
|
|
5899
|
-
|
|
5953
|
+
writeFileSync9(resolve25(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
|
|
5900
5954
|
`, "utf-8");
|
|
5901
5955
|
return skipped;
|
|
5902
5956
|
}
|
|
@@ -5931,18 +5985,18 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
5931
5985
|
exit_code: 2,
|
|
5932
5986
|
duration_seconds: 0
|
|
5933
5987
|
});
|
|
5934
|
-
const logFile2 =
|
|
5935
|
-
|
|
5936
|
-
|
|
5988
|
+
const logFile2 = resolve25(taskLogDir, `invalid-entry-validation.log`);
|
|
5989
|
+
mkdirSync9(taskLogDir, { recursive: true });
|
|
5990
|
+
writeFileSync9(logFile2, `=== ${nowIso()} :: ${cmd} ===
|
|
5937
5991
|
Invalid validation entry: not a check-ID. All entries must use format "category:check-name".
|
|
5938
5992
|
`, "utf-8");
|
|
5939
5993
|
continue;
|
|
5940
5994
|
}
|
|
5941
5995
|
const { result, exitCode } = await dispatchValidator(cmd, effectiveRegistry, validatorCtx, (id) => runValidatorBinary(projectRoot, taskId, id, resolvedContext));
|
|
5942
5996
|
const durationSeconds = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
|
|
5943
|
-
const logFile =
|
|
5944
|
-
|
|
5945
|
-
|
|
5997
|
+
const logFile = resolve25(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
|
|
5998
|
+
mkdirSync9(taskLogDir, { recursive: true });
|
|
5999
|
+
writeFileSync9(logFile, `=== ${nowIso()} :: ${cmd} ===
|
|
5946
6000
|
${JSON.stringify(result, null, 2)}
|
|
5947
6001
|
`, "utf-8");
|
|
5948
6002
|
if (result.passed) {
|
|
@@ -5964,8 +6018,8 @@ ${JSON.stringify(result, null, 2)}
|
|
|
5964
6018
|
failed,
|
|
5965
6019
|
categories
|
|
5966
6020
|
};
|
|
5967
|
-
|
|
5968
|
-
|
|
6021
|
+
mkdirSync9(artifactDir, { recursive: true });
|
|
6022
|
+
writeFileSync9(resolve25(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
|
|
5969
6023
|
`, "utf-8");
|
|
5970
6024
|
return summary;
|
|
5971
6025
|
}
|
|
@@ -6312,16 +6366,16 @@ async function taskDeps(projectRoot, taskId) {
|
|
|
6312
6366
|
for (const dep of deps) {
|
|
6313
6367
|
const artifactDir = artifactDirForId(projectRoot, dep);
|
|
6314
6368
|
console.log(`=== ${dep} ===`);
|
|
6315
|
-
if (!
|
|
6369
|
+
if (!existsSync22(artifactDir)) {
|
|
6316
6370
|
console.log(` (no artifacts yet)
|
|
6317
6371
|
`);
|
|
6318
6372
|
continue;
|
|
6319
6373
|
}
|
|
6320
|
-
printArtifactSection(
|
|
6321
|
-
printArtifactSection(
|
|
6322
|
-
const changedFiles =
|
|
6323
|
-
if (
|
|
6324
|
-
const lines =
|
|
6374
|
+
printArtifactSection(resolve26(artifactDir, "decision-log.md"), "--- Decisions ---");
|
|
6375
|
+
printArtifactSection(resolve26(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
|
|
6376
|
+
const changedFiles = resolve26(artifactDir, "changed-files.txt");
|
|
6377
|
+
if (existsSync22(changedFiles)) {
|
|
6378
|
+
const lines = readFileSync13(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
6325
6379
|
console.log(`--- Changed Files (${lines.length}) ---`);
|
|
6326
6380
|
for (const line of lines) {
|
|
6327
6381
|
console.log(line);
|
|
@@ -6366,12 +6420,12 @@ function taskRecord(projectRoot, type, text, taskId) {
|
|
|
6366
6420
|
throw new Error("No active task.");
|
|
6367
6421
|
}
|
|
6368
6422
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6369
|
-
|
|
6423
|
+
mkdirSync10(paths.stateDir, { recursive: true });
|
|
6370
6424
|
if (type === "decision") {
|
|
6371
|
-
const artifactDir =
|
|
6372
|
-
|
|
6425
|
+
const artifactDir = resolve26(paths.artifactsDir, activeTask);
|
|
6426
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
6373
6427
|
const timestamp = nowIso();
|
|
6374
|
-
appendFileSync(
|
|
6428
|
+
appendFileSync(resolve26(artifactDir, "decision-log.md"), `
|
|
6375
6429
|
### ${timestamp}
|
|
6376
6430
|
|
|
6377
6431
|
${text}
|
|
@@ -6381,15 +6435,15 @@ ${text}
|
|
|
6381
6435
|
return;
|
|
6382
6436
|
}
|
|
6383
6437
|
const failedPath = paths.failedApproachesPath;
|
|
6384
|
-
if (!
|
|
6385
|
-
|
|
6438
|
+
if (!existsSync22(failedPath)) {
|
|
6439
|
+
writeFileSync10(failedPath, `# Failed Approaches Log
|
|
6386
6440
|
|
|
6387
6441
|
This file records approaches that did not work.
|
|
6388
6442
|
|
|
6389
6443
|
`, "utf-8");
|
|
6390
6444
|
}
|
|
6391
|
-
const content =
|
|
6392
|
-
const attempts = (content.match(new RegExp(`^## ${
|
|
6445
|
+
const content = readFileSync13(failedPath, "utf-8");
|
|
6446
|
+
const attempts = (content.match(new RegExp(`^## ${escapeRegExp(activeTask)}\\b`, "gm")) || []).length + 1;
|
|
6393
6447
|
appendFileSync(failedPath, `
|
|
6394
6448
|
## ${activeTask} - Attempt ${attempts} (${nowIso()})
|
|
6395
6449
|
|
|
@@ -6405,40 +6459,40 @@ function taskArtifacts(projectRoot, taskId) {
|
|
|
6405
6459
|
throw new Error("No active task.");
|
|
6406
6460
|
}
|
|
6407
6461
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6408
|
-
const artifactDir =
|
|
6409
|
-
|
|
6462
|
+
const artifactDir = resolve26(paths.artifactsDir, activeTask);
|
|
6463
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
6410
6464
|
const changed = changedFilesForTask(projectRoot, activeTask, true);
|
|
6411
|
-
|
|
6465
|
+
writeFileSync10(resolve26(artifactDir, "changed-files.txt"), `${changed.join(`
|
|
6412
6466
|
`)}
|
|
6413
6467
|
`, "utf-8");
|
|
6414
6468
|
console.log(`changed-files.txt: ${changed.length} files`);
|
|
6415
|
-
const taskResultPath =
|
|
6416
|
-
if (!
|
|
6469
|
+
const taskResultPath = resolve26(artifactDir, "task-result.json");
|
|
6470
|
+
if (!existsSync22(taskResultPath)) {
|
|
6417
6471
|
const template = {
|
|
6418
6472
|
task_id: activeTask,
|
|
6419
6473
|
status: "completed",
|
|
6420
6474
|
summary: "TODO: Write a one-line summary of what you did",
|
|
6421
6475
|
completed_at: nowIso()
|
|
6422
6476
|
};
|
|
6423
|
-
|
|
6477
|
+
writeFileSync10(taskResultPath, `${JSON.stringify(template, null, 2)}
|
|
6424
6478
|
`, "utf-8");
|
|
6425
6479
|
console.log("task-result.json: created (update the summary!)");
|
|
6426
6480
|
} else {
|
|
6427
6481
|
console.log("task-result.json: already exists");
|
|
6428
6482
|
}
|
|
6429
|
-
const decisionLogPath =
|
|
6430
|
-
if (!
|
|
6483
|
+
const decisionLogPath = resolve26(artifactDir, "decision-log.md");
|
|
6484
|
+
if (!existsSync22(decisionLogPath)) {
|
|
6431
6485
|
const content = `# Decision Log: ${activeTask}
|
|
6432
6486
|
|
|
6433
6487
|
Record key decisions here using: rig-agent record decision "..."
|
|
6434
6488
|
`;
|
|
6435
|
-
|
|
6489
|
+
writeFileSync10(decisionLogPath, content, "utf-8");
|
|
6436
6490
|
console.log("decision-log.md: created (record your decisions!)");
|
|
6437
6491
|
} else {
|
|
6438
6492
|
console.log("decision-log.md: already exists");
|
|
6439
6493
|
}
|
|
6440
|
-
const nextActionsPath =
|
|
6441
|
-
if (!
|
|
6494
|
+
const nextActionsPath = resolve26(artifactDir, "next-actions.md");
|
|
6495
|
+
if (!existsSync22(nextActionsPath)) {
|
|
6442
6496
|
const content = [
|
|
6443
6497
|
`# Next Actions: ${activeTask}`,
|
|
6444
6498
|
"",
|
|
@@ -6455,13 +6509,13 @@ Record key decisions here using: rig-agent record decision "..."
|
|
|
6455
6509
|
""
|
|
6456
6510
|
].join(`
|
|
6457
6511
|
`);
|
|
6458
|
-
|
|
6512
|
+
writeFileSync10(nextActionsPath, content, "utf-8");
|
|
6459
6513
|
console.log("next-actions.md: created (add recommendations for downstream tasks!)");
|
|
6460
6514
|
} else {
|
|
6461
6515
|
console.log("next-actions.md: already exists");
|
|
6462
6516
|
}
|
|
6463
|
-
const validationSummaryPath =
|
|
6464
|
-
if (
|
|
6517
|
+
const validationSummaryPath = resolve26(artifactDir, "validation-summary.json");
|
|
6518
|
+
if (existsSync22(validationSummaryPath)) {
|
|
6465
6519
|
console.log("validation-summary.json: already exists");
|
|
6466
6520
|
} else {
|
|
6467
6521
|
console.log("validation-summary.json: not yet created (run: rig-agent validate)");
|
|
@@ -6475,8 +6529,8 @@ function taskArtifactDir(projectRoot, taskId) {
|
|
|
6475
6529
|
throw new Error("No active task.");
|
|
6476
6530
|
}
|
|
6477
6531
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6478
|
-
const artifactDir =
|
|
6479
|
-
|
|
6532
|
+
const artifactDir = resolve26(paths.artifactsDir, activeTask);
|
|
6533
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
6480
6534
|
return artifactDir;
|
|
6481
6535
|
}
|
|
6482
6536
|
function taskArtifactWrite(projectRoot, filename, content, taskId) {
|
|
@@ -6485,10 +6539,10 @@ function taskArtifactWrite(projectRoot, filename, content, taskId) {
|
|
|
6485
6539
|
throw new Error("No active task.");
|
|
6486
6540
|
}
|
|
6487
6541
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6488
|
-
const artifactDir =
|
|
6489
|
-
|
|
6490
|
-
const targetPath =
|
|
6491
|
-
|
|
6542
|
+
const artifactDir = resolve26(paths.artifactsDir, activeTask);
|
|
6543
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
6544
|
+
const targetPath = resolve26(artifactDir, filename);
|
|
6545
|
+
writeFileSync10(targetPath, content, "utf-8");
|
|
6492
6546
|
console.log(`Wrote: ${targetPath}`);
|
|
6493
6547
|
}
|
|
6494
6548
|
async function taskValidate(projectRoot, taskId, validatorRegistry) {
|
|
@@ -6549,7 +6603,7 @@ function collectTaskChangedFiles(projectRoot, taskId, includeCommitted) {
|
|
|
6549
6603
|
[projectRoot, ""],
|
|
6550
6604
|
[monorepoRepoRoot, ""]
|
|
6551
6605
|
]) {
|
|
6552
|
-
if (!
|
|
6606
|
+
if (!existsSync22(resolve26(repo, ".git"))) {
|
|
6553
6607
|
continue;
|
|
6554
6608
|
}
|
|
6555
6609
|
if (includeCommitted && repo === monorepoRepoRoot) {
|
|
@@ -6587,8 +6641,8 @@ function filterTaskChangedFiles(projectRoot, taskId, files, scoped) {
|
|
|
6587
6641
|
}
|
|
6588
6642
|
function resolveTaskMonorepoRoot(projectRoot) {
|
|
6589
6643
|
const runtimeWorkspace = loadRuntimeContextFromEnv()?.workspaceDir || process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6590
|
-
if (runtimeWorkspace &&
|
|
6591
|
-
return
|
|
6644
|
+
if (runtimeWorkspace && existsSync22(resolve26(runtimeWorkspace, ".git"))) {
|
|
6645
|
+
return resolve26(runtimeWorkspace);
|
|
6592
6646
|
}
|
|
6593
6647
|
return resolveHarnessPaths(projectRoot).monorepoRoot;
|
|
6594
6648
|
}
|
|
@@ -6616,7 +6670,7 @@ function resolveRuntimeInitialHeadCommit(projectRoot, repo) {
|
|
|
6616
6670
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6617
6671
|
if (runtimeContext?.initialHeadCommits?.monorepo?.trim()) {
|
|
6618
6672
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6619
|
-
if (
|
|
6673
|
+
if (resolve26(monorepoRoot) === resolve26(repo)) {
|
|
6620
6674
|
return runtimeContext.initialHeadCommits.monorepo.trim();
|
|
6621
6675
|
}
|
|
6622
6676
|
}
|
|
@@ -6626,7 +6680,7 @@ function resolveMonorepoBaseCommit(projectRoot, repo) {
|
|
|
6626
6680
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6627
6681
|
if (runtimeContext?.monorepoBaseCommit?.trim()) {
|
|
6628
6682
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6629
|
-
if (
|
|
6683
|
+
if (resolve26(monorepoRoot) === resolve26(repo)) {
|
|
6630
6684
|
return runtimeContext.monorepoBaseCommit.trim();
|
|
6631
6685
|
}
|
|
6632
6686
|
}
|
|
@@ -6660,7 +6714,7 @@ function resolveRuntimeDirtyBaseline(projectRoot, repo) {
|
|
|
6660
6714
|
return new Set;
|
|
6661
6715
|
}
|
|
6662
6716
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6663
|
-
const selected =
|
|
6717
|
+
const selected = resolve26(repo) === resolve26(monorepoRoot) ? dirtyFiles.monorepo : resolve26(repo) === resolve26(projectRoot) ? dirtyFiles.project : undefined;
|
|
6664
6718
|
return new Set((selected || []).map((file) => normalizeChangedFilePath(file)).filter(Boolean));
|
|
6665
6719
|
}
|
|
6666
6720
|
function normalizeChangedFilePath(file) {
|
|
@@ -6760,12 +6814,12 @@ function printIndented(text) {
|
|
|
6760
6814
|
}
|
|
6761
6815
|
}
|
|
6762
6816
|
function readLocalBeadsTasks(projectRoot) {
|
|
6763
|
-
const issuesPath =
|
|
6764
|
-
if (!
|
|
6817
|
+
const issuesPath = resolve26(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
|
|
6818
|
+
if (!existsSync22(issuesPath)) {
|
|
6765
6819
|
return [];
|
|
6766
6820
|
}
|
|
6767
6821
|
const tasks = [];
|
|
6768
|
-
for (const line of
|
|
6822
|
+
for (const line of readFileSync13(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
6769
6823
|
const trimmed = line.trim();
|
|
6770
6824
|
if (!trimmed) {
|
|
6771
6825
|
continue;
|
|
@@ -6878,14 +6932,14 @@ function taskDependencies(projectRoot, taskId, tracker) {
|
|
|
6878
6932
|
return [...ids].sort();
|
|
6879
6933
|
}
|
|
6880
6934
|
function printArtifactSection(path, header) {
|
|
6881
|
-
if (!
|
|
6935
|
+
if (!existsSync22(path)) {
|
|
6882
6936
|
return;
|
|
6883
6937
|
}
|
|
6884
6938
|
console.log(header);
|
|
6885
|
-
process.stdout.write(
|
|
6939
|
+
process.stdout.write(readFileSync13(path, "utf-8"));
|
|
6886
6940
|
console.log("");
|
|
6887
6941
|
}
|
|
6888
|
-
function
|
|
6942
|
+
function escapeRegExp(value) {
|
|
6889
6943
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6890
6944
|
}
|
|
6891
6945
|
function changedFilesForTask(projectRoot, taskId, scoped) {
|
|
@@ -6914,16 +6968,16 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
|
|
|
6914
6968
|
"task-result.json",
|
|
6915
6969
|
"validation-summary.json"
|
|
6916
6970
|
]);
|
|
6917
|
-
function resolveHostRigBinDir(root) {
|
|
6918
|
-
return resolve26(root, ".rig", "bin");
|
|
6919
|
-
}
|
|
6920
6971
|
function isRuntimeGatewayGitPath(candidate) {
|
|
6921
6972
|
return /\/\.rig\/bin\/git$/.test(candidate.replace(/\\/g, "/"));
|
|
6922
6973
|
}
|
|
6974
|
+
function isRuntimeGatewayGhPath(candidate) {
|
|
6975
|
+
return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
|
|
6976
|
+
}
|
|
6923
6977
|
function resolveOptionalMonorepoRoot(projectRoot) {
|
|
6924
6978
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6925
|
-
if (runtimeWorkspace &&
|
|
6926
|
-
return
|
|
6979
|
+
if (runtimeWorkspace && existsSync23(resolve27(runtimeWorkspace, ".git"))) {
|
|
6980
|
+
return resolve27(runtimeWorkspace);
|
|
6927
6981
|
}
|
|
6928
6982
|
try {
|
|
6929
6983
|
return resolveMonorepoRoot2(projectRoot);
|
|
@@ -6948,12 +7002,15 @@ function resolveGitBinary(projectRoot) {
|
|
|
6948
7002
|
if (!candidate || isRuntimeGatewayGitPath(candidate)) {
|
|
6949
7003
|
continue;
|
|
6950
7004
|
}
|
|
6951
|
-
if (
|
|
7005
|
+
if (existsSync23(candidate)) {
|
|
6952
7006
|
return candidate;
|
|
6953
7007
|
}
|
|
6954
7008
|
}
|
|
6955
7009
|
return "git";
|
|
6956
7010
|
}
|
|
7011
|
+
function escapeRegExp2(value) {
|
|
7012
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7013
|
+
}
|
|
6957
7014
|
function safeCurrentTaskId(projectRoot) {
|
|
6958
7015
|
try {
|
|
6959
7016
|
const taskId = currentTaskId(projectRoot);
|
|
@@ -7005,11 +7062,11 @@ function gitPreflight(projectRoot, taskId, strict) {
|
|
|
7005
7062
|
const expected = resolvedTask ? `rig/${resolveTaskBranchId(projectRoot, resolvedTask)}` : "";
|
|
7006
7063
|
console.log("=== Git Flow Preflight ===");
|
|
7007
7064
|
let issues = 0;
|
|
7008
|
-
if (!
|
|
7065
|
+
if (!existsSync23(resolve27(projectRoot, ".git"))) {
|
|
7009
7066
|
console.log(`ERROR: project root is not a git repo (${projectRoot})`);
|
|
7010
7067
|
issues += 1;
|
|
7011
7068
|
}
|
|
7012
|
-
if (monorepoRoot &&
|
|
7069
|
+
if (monorepoRoot && existsSync23(resolve27(monorepoRoot, ".git"))) {
|
|
7013
7070
|
const monoBranch = branchName(projectRoot, monorepoRoot);
|
|
7014
7071
|
if (expected && monoBranch !== expected) {
|
|
7015
7072
|
console.log(`WARN: monorepo branch is ${monoBranch}, expected ${expected} for task ${resolvedTask}`);
|
|
@@ -7043,7 +7100,7 @@ function gitSyncBranch(projectRoot, taskId, targetRepo = "monorepo") {
|
|
|
7043
7100
|
}
|
|
7044
7101
|
const repoRoot = targetRepo === "monorepo" ? resolveOptionalMonorepoRoot(projectRoot) || resolveMonorepoRoot2(projectRoot) : projectRoot;
|
|
7045
7102
|
const repoLabel = targetRepo === "monorepo" ? "Monorepo" : "Project";
|
|
7046
|
-
if (!
|
|
7103
|
+
if (!existsSync23(resolve27(repoRoot, ".git"))) {
|
|
7047
7104
|
throw new Error(`${repoLabel} repo not found at ${repoRoot}`);
|
|
7048
7105
|
}
|
|
7049
7106
|
const branchId = resolveTaskBranchId(projectRoot, resolvedTask);
|
|
@@ -7087,8 +7144,8 @@ function gitCommit(options) {
|
|
|
7087
7144
|
function gitSnapshot(projectRoot, taskId, outputPath) {
|
|
7088
7145
|
const monorepoRoot = resolveOptionalMonorepoRoot(projectRoot);
|
|
7089
7146
|
const resolvedTask = taskId || safeCurrentTaskId(projectRoot);
|
|
7090
|
-
const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) :
|
|
7091
|
-
|
|
7147
|
+
const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) : resolve27(resolve27(projectRoot, ".rig", "state"), "git-state.txt"));
|
|
7148
|
+
mkdirSync11(dirname14(output), { recursive: true });
|
|
7092
7149
|
const lines = ["# Git Snapshot", `timestamp: ${nowIso()}`];
|
|
7093
7150
|
if (resolvedTask) {
|
|
7094
7151
|
lines.push(`task: ${resolvedTask}`);
|
|
@@ -7098,7 +7155,7 @@ function gitSnapshot(projectRoot, taskId, outputPath) {
|
|
|
7098
7155
|
if (monorepoRoot && monorepoRoot !== projectRoot) {
|
|
7099
7156
|
lines.push(...snapshotRepo(projectRoot, "monorepo", monorepoRoot));
|
|
7100
7157
|
}
|
|
7101
|
-
|
|
7158
|
+
writeFileSync11(output, `${lines.join(`
|
|
7102
7159
|
`)}
|
|
7103
7160
|
`, "utf-8");
|
|
7104
7161
|
return output;
|
|
@@ -7122,7 +7179,7 @@ function gitOpenPr(options) {
|
|
|
7122
7179
|
} else if (taskId) {
|
|
7123
7180
|
gitSyncBranch(options.projectRoot, taskId, "project");
|
|
7124
7181
|
}
|
|
7125
|
-
if (!
|
|
7182
|
+
if (!existsSync23(resolve27(repoRoot, ".git"))) {
|
|
7126
7183
|
throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
|
|
7127
7184
|
}
|
|
7128
7185
|
const branch = branchName(options.projectRoot, repoRoot);
|
|
@@ -7167,10 +7224,11 @@ function gitOpenPr(options) {
|
|
|
7167
7224
|
"",
|
|
7168
7225
|
"## Task",
|
|
7169
7226
|
`- beads: ${taskId || "n/a"}`,
|
|
7227
|
+
...defaultPrRunLines(taskId, repoNameWithOwner),
|
|
7170
7228
|
"",
|
|
7171
7229
|
"## Review",
|
|
7172
7230
|
"- Completion verification will run validation, verifier review, and PR policy checks.",
|
|
7173
|
-
"- When repository policy allows it, Rig
|
|
7231
|
+
"- When repository policy allows it, Rig attempts an immediate strict-gated, head-locked merge after approval."
|
|
7174
7232
|
].join(`
|
|
7175
7233
|
`);
|
|
7176
7234
|
const preCheck = runCapture2(withGhRepo([gh, "pr", "list", "--state", "merged", "--head", branch, "--json", "url,mergedAt", "--jq", ".[0]"], repoNameWithOwner), repoRoot);
|
|
@@ -7258,6 +7316,30 @@ function gitOpenPr(options) {
|
|
|
7258
7316
|
}
|
|
7259
7317
|
return result;
|
|
7260
7318
|
}
|
|
7319
|
+
function defaultPrRunLines(taskId, repoNameWithOwner) {
|
|
7320
|
+
const lines = [];
|
|
7321
|
+
const runId = process.env.RIG_SERVER_RUN_ID?.trim();
|
|
7322
|
+
if (runId) {
|
|
7323
|
+
lines.push(`- Run: ${runId}`);
|
|
7324
|
+
}
|
|
7325
|
+
const closeout = defaultPrCloseoutLine(taskId, repoNameWithOwner);
|
|
7326
|
+
if (closeout) {
|
|
7327
|
+
lines.push(`- ${closeout}`);
|
|
7328
|
+
}
|
|
7329
|
+
return lines;
|
|
7330
|
+
}
|
|
7331
|
+
function defaultPrCloseoutLine(taskId, repoNameWithOwner) {
|
|
7332
|
+
const sourceIssueId = loadRuntimeContextFromEnv()?.sourceTask?.sourceIssueId;
|
|
7333
|
+
if (sourceIssueId) {
|
|
7334
|
+
const match = sourceIssueId.match(/^([^#]+)#(\d+)$/);
|
|
7335
|
+
if (match?.[1] && match[2]) {
|
|
7336
|
+
const sourceRepo = match[1];
|
|
7337
|
+
const issueNumber = match[2];
|
|
7338
|
+
return sourceRepo.toLowerCase() === repoNameWithOwner.toLowerCase() ? `Closes #${issueNumber}` : `Closes ${sourceRepo}#${issueNumber}`;
|
|
7339
|
+
}
|
|
7340
|
+
}
|
|
7341
|
+
return /^\d+$/.test(taskId) ? `Closes #${taskId}` : "";
|
|
7342
|
+
}
|
|
7261
7343
|
function readPrViewState(gh, repoRoot, repoNameWithOwner, prUrl) {
|
|
7262
7344
|
const view = runCapture2(withGhRepo([
|
|
7263
7345
|
gh,
|
|
@@ -7310,12 +7392,12 @@ function assertPrHasNoGitConflicts(prState, repoLabel, baseRef) {
|
|
|
7310
7392
|
}
|
|
7311
7393
|
function writePrMetadata(projectRoot, taskId, result) {
|
|
7312
7394
|
const dir = artifactDirForId(projectRoot, taskId);
|
|
7313
|
-
|
|
7314
|
-
const path =
|
|
7395
|
+
mkdirSync11(dir, { recursive: true });
|
|
7396
|
+
const path = resolve27(dir, "pr-state.json");
|
|
7315
7397
|
let prs = {};
|
|
7316
|
-
if (
|
|
7398
|
+
if (existsSync23(path)) {
|
|
7317
7399
|
try {
|
|
7318
|
-
const parsed = JSON.parse(
|
|
7400
|
+
const parsed = JSON.parse(readFileSync14(path, "utf-8"));
|
|
7319
7401
|
if (parsed && typeof parsed === "object" && parsed.prs && typeof parsed.prs === "object") {
|
|
7320
7402
|
prs = parsed.prs;
|
|
7321
7403
|
}
|
|
@@ -7331,12 +7413,12 @@ function writePrMetadata(projectRoot, taskId, result) {
|
|
|
7331
7413
|
...primary || {},
|
|
7332
7414
|
updated_at: nowIso()
|
|
7333
7415
|
};
|
|
7334
|
-
|
|
7416
|
+
writeFileSync11(path, `${JSON.stringify(artifact, null, 2)}
|
|
7335
7417
|
`, "utf-8");
|
|
7336
7418
|
}
|
|
7337
7419
|
function resolveArtifactSnapshot(projectRoot, taskId) {
|
|
7338
|
-
const artifactDir =
|
|
7339
|
-
return
|
|
7420
|
+
const artifactDir = resolve27(resolveHarnessPaths(projectRoot).artifactsDir, taskId);
|
|
7421
|
+
return resolve27(artifactDir, "git-state.txt");
|
|
7340
7422
|
}
|
|
7341
7423
|
function ensureFullGitHistory(projectRoot, repoRoot, remoteName = "origin") {
|
|
7342
7424
|
const shallow = runCapture2(gitCmd(projectRoot, repoRoot, "rev-parse", "--is-shallow-repository"), projectRoot);
|
|
@@ -7383,32 +7465,19 @@ function resolveGithubCliBinary(projectRoot) {
|
|
|
7383
7465
|
if (explicit) {
|
|
7384
7466
|
candidates.add(explicit);
|
|
7385
7467
|
}
|
|
7468
|
+
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
7469
|
+
candidates.add(candidate);
|
|
7470
|
+
}
|
|
7386
7471
|
const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
|
|
7387
7472
|
for (const entry of explicitPathEntries) {
|
|
7388
|
-
candidates.add(
|
|
7389
|
-
}
|
|
7390
|
-
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
7391
|
-
if (hostProjectRoot) {
|
|
7392
|
-
candidates.add(resolve26(resolveHostRigBinDir(hostProjectRoot), "gh"));
|
|
7393
|
-
}
|
|
7394
|
-
candidates.add(resolve26(resolveHostRigBinDir(projectRoot), "gh"));
|
|
7395
|
-
const runtimeContext = loadRuntimeContextFromEnv();
|
|
7396
|
-
if (runtimeContext?.binDir) {
|
|
7397
|
-
candidates.add(resolve26(runtimeContext.binDir, "gh"));
|
|
7398
|
-
}
|
|
7399
|
-
const runtimeHome = process.env.RIG_RUNTIME_HOME?.trim();
|
|
7400
|
-
if (runtimeHome) {
|
|
7401
|
-
candidates.add(resolve26(runtimeHome, "bin", "gh"));
|
|
7402
|
-
}
|
|
7403
|
-
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
|
|
7404
|
-
candidates.add(candidate);
|
|
7473
|
+
candidates.add(resolve27(entry, "gh"));
|
|
7405
7474
|
}
|
|
7406
7475
|
const bunResolved = Bun.which("gh");
|
|
7407
7476
|
if (bunResolved) {
|
|
7408
7477
|
candidates.add(bunResolved);
|
|
7409
7478
|
}
|
|
7410
7479
|
for (const candidate of candidates) {
|
|
7411
|
-
if (candidate &&
|
|
7480
|
+
if (candidate && existsSync23(candidate) && !isRuntimeGatewayGhPath(candidate)) {
|
|
7412
7481
|
return candidate;
|
|
7413
7482
|
}
|
|
7414
7483
|
}
|
|
@@ -7438,7 +7507,7 @@ function resolveRepoNameWithOwner(projectRoot, repoRoot) {
|
|
|
7438
7507
|
return resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, repoRoot, repoRoot, visited);
|
|
7439
7508
|
}
|
|
7440
7509
|
function resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, gitRoot, cwd, visited) {
|
|
7441
|
-
const normalizedGitRoot =
|
|
7510
|
+
const normalizedGitRoot = resolve27(gitRoot);
|
|
7442
7511
|
if (visited.has(normalizedGitRoot)) {
|
|
7443
7512
|
return "";
|
|
7444
7513
|
}
|
|
@@ -7510,7 +7579,7 @@ function resolveNetworkRemoteName(projectRoot, repoRoot, repoNameWithOwner) {
|
|
|
7510
7579
|
return remotes.includes("origin") ? "origin" : remotes[0];
|
|
7511
7580
|
}
|
|
7512
7581
|
function gitQuery(projectRoot, gitRoot, cwd, ...args) {
|
|
7513
|
-
const gitArgs =
|
|
7582
|
+
const gitArgs = existsSync23(resolve27(gitRoot, ".git")) ? gitCmd(projectRoot, gitRoot, ...args) : [resolveGitBinary(projectRoot), "--git-dir", gitRoot, ...args];
|
|
7514
7583
|
return runCapture2(gitArgs, cwd, projectRoot);
|
|
7515
7584
|
}
|
|
7516
7585
|
function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
|
|
@@ -7528,9 +7597,9 @@ function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
|
|
|
7528
7597
|
} else if (/^[a-z][a-z0-9+.-]*:\/\//i.test(normalized) || /^[^@]+@[^:]+:.+$/.test(normalized)) {
|
|
7529
7598
|
return "";
|
|
7530
7599
|
} else if (!isAbsolute2(normalized)) {
|
|
7531
|
-
candidate =
|
|
7600
|
+
candidate = resolve27(gitRoot, normalized);
|
|
7532
7601
|
}
|
|
7533
|
-
return
|
|
7602
|
+
return existsSync23(candidate) ? candidate : "";
|
|
7534
7603
|
}
|
|
7535
7604
|
function normalizeGithubRepoNameWithOwner(value) {
|
|
7536
7605
|
const normalized = value.trim();
|
|
@@ -7561,7 +7630,7 @@ function inferRepositoryDefaultBase(projectRoot, repoRoot, repoNameWithOwner, re
|
|
|
7561
7630
|
const remote = remoteName || "origin";
|
|
7562
7631
|
const symbolic = runCapture2(gitCmd(projectRoot, repoRoot, "symbolic-ref", "--short", `refs/remotes/${remote}/HEAD`), projectRoot);
|
|
7563
7632
|
if (symbolic.exitCode === 0) {
|
|
7564
|
-
const ref = symbolic.stdout.trim().replace(new RegExp(`^${
|
|
7633
|
+
const ref = symbolic.stdout.trim().replace(new RegExp(`^${escapeRegExp2(remote)}/`), "");
|
|
7565
7634
|
if (ref && ref !== "HEAD") {
|
|
7566
7635
|
return ref;
|
|
7567
7636
|
}
|
|
@@ -7657,7 +7726,7 @@ function inferReviewerFromChangedFiles(projectRoot, repoRoot, baseRef, branchRef
|
|
|
7657
7726
|
return best;
|
|
7658
7727
|
}
|
|
7659
7728
|
function snapshotRepo(projectRoot, label, repo) {
|
|
7660
|
-
if (!
|
|
7729
|
+
if (!existsSync23(resolve27(repo, ".git"))) {
|
|
7661
7730
|
return [`## ${label}`, `repo: ${repo}`, "status: unavailable", ""];
|
|
7662
7731
|
}
|
|
7663
7732
|
const status = runCapture2(gitCmd(projectRoot, repo, "status", "--short"), projectRoot).stdout.trim();
|
|
@@ -7680,7 +7749,7 @@ function snapshotRepo(projectRoot, label, repo) {
|
|
|
7680
7749
|
];
|
|
7681
7750
|
}
|
|
7682
7751
|
function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files, changedFilesManifest) {
|
|
7683
|
-
if (!
|
|
7752
|
+
if (!existsSync23(resolve27(repo, ".git"))) {
|
|
7684
7753
|
console.log(`Skipping ${label}: repo not available (${repo})`);
|
|
7685
7754
|
return;
|
|
7686
7755
|
}
|
|
@@ -7712,18 +7781,18 @@ function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files
|
|
|
7712
7781
|
console.log(`Committed ${label}: ${message}`);
|
|
7713
7782
|
}
|
|
7714
7783
|
function readChangedFilesManifest(projectRoot, taskId) {
|
|
7715
|
-
const manifestPath =
|
|
7716
|
-
if (!
|
|
7784
|
+
const manifestPath = resolve27(artifactDirForId(projectRoot, taskId), "changed-files.txt");
|
|
7785
|
+
if (!existsSync23(manifestPath)) {
|
|
7717
7786
|
return [];
|
|
7718
7787
|
}
|
|
7719
|
-
const files =
|
|
7788
|
+
const files = readFileSync14(manifestPath, "utf-8").split(/\r?\n/).map((line) => normalizeChangedFilePath2(line)).filter(Boolean);
|
|
7720
7789
|
return [...new Set(files)];
|
|
7721
7790
|
}
|
|
7722
7791
|
function refreshChangedFilesManifest(projectRoot, taskId) {
|
|
7723
|
-
const manifestPath =
|
|
7724
|
-
|
|
7792
|
+
const manifestPath = resolve27(artifactDirForId(projectRoot, taskId), "changed-files.txt");
|
|
7793
|
+
mkdirSync11(dirname14(manifestPath), { recursive: true });
|
|
7725
7794
|
const changedFiles = changedFilesForTask(projectRoot, taskId, true);
|
|
7726
|
-
|
|
7795
|
+
writeFileSync11(manifestPath, `${changedFiles.join(`
|
|
7727
7796
|
`)}
|
|
7728
7797
|
`, "utf-8");
|
|
7729
7798
|
return manifestPath;
|
|
@@ -7836,7 +7905,7 @@ function repoHasPathChange(projectRoot, repoRoot, relativePath) {
|
|
|
7836
7905
|
return result.exitCode === 0 && result.stdout.trim().length > 0;
|
|
7837
7906
|
}
|
|
7838
7907
|
function stageExcludePathspecs(repoRoot) {
|
|
7839
|
-
const patterns =
|
|
7908
|
+
const patterns = existsSync23(resolve27(repoRoot, ".rig", "task-config.json")) ? [...TASK_RUNTIME_STAGE_EXCLUDES, ...GENERATED_STAGE_EXCLUDES] : [".rig/**", ...GENERATED_STAGE_EXCLUDES];
|
|
7840
7909
|
return patterns.map((pattern) => `:(glob,exclude)${pattern}`);
|
|
7841
7910
|
}
|
|
7842
7911
|
function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
@@ -7846,7 +7915,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
|
7846
7915
|
}
|
|
7847
7916
|
let current = repoRoot;
|
|
7848
7917
|
for (let index = 0;index < parts.length - 1; index += 1) {
|
|
7849
|
-
current =
|
|
7918
|
+
current = resolve27(current, parts[index]);
|
|
7850
7919
|
try {
|
|
7851
7920
|
if (lstatSync(current).isSymbolicLink()) {
|
|
7852
7921
|
return true;
|
|
@@ -7858,7 +7927,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
|
7858
7927
|
return false;
|
|
7859
7928
|
}
|
|
7860
7929
|
function printRepoStatus(projectRoot, label, repo, expectedBranch) {
|
|
7861
|
-
if (!
|
|
7930
|
+
if (!existsSync23(resolve27(repo, ".git"))) {
|
|
7862
7931
|
console.log(`${label}: unavailable (${repo})`);
|
|
7863
7932
|
return;
|
|
7864
7933
|
}
|
|
@@ -7894,7 +7963,7 @@ function resolveTaskBranchId(projectRoot, taskId) {
|
|
|
7894
7963
|
}
|
|
7895
7964
|
} catch {}
|
|
7896
7965
|
const artifactDir = artifactDirForId(projectRoot, taskId);
|
|
7897
|
-
if (
|
|
7966
|
+
if (existsSync23(artifactDir)) {
|
|
7898
7967
|
return taskId;
|
|
7899
7968
|
}
|
|
7900
7969
|
throw new Error(`Unknown task id: ${taskId}`);
|
|
@@ -7930,11 +7999,11 @@ function runCapture2(command, cwd, projectRoot = cwd) {
|
|
|
7930
7999
|
}
|
|
7931
8000
|
function runtimeGitEnv(projectRoot) {
|
|
7932
8001
|
const { ctx, runtimeRoot } = resolveRuntimeMetadata(projectRoot);
|
|
7933
|
-
const runtimeHome = runtimeRoot ?
|
|
7934
|
-
const runtimeTmp = runtimeRoot ?
|
|
7935
|
-
const runtimeCache = runtimeRoot ?
|
|
7936
|
-
const runtimeKnownHosts = runtimeHome ?
|
|
7937
|
-
const runtimeKey = runtimeHome ?
|
|
8002
|
+
const runtimeHome = runtimeRoot ? resolve27(runtimeRoot, "home") : "";
|
|
8003
|
+
const runtimeTmp = runtimeRoot ? resolve27(runtimeRoot, "tmp") : "";
|
|
8004
|
+
const runtimeCache = runtimeRoot ? resolve27(runtimeRoot, "cache") : "";
|
|
8005
|
+
const runtimeKnownHosts = runtimeHome ? resolve27(runtimeHome, ".ssh", "known_hosts") : "";
|
|
8006
|
+
const runtimeKey = runtimeHome ? resolve27(runtimeHome, ".ssh", "rig-agent-key") : "";
|
|
7938
8007
|
const env = {};
|
|
7939
8008
|
if (ctx?.workspaceDir) {
|
|
7940
8009
|
env.PROJECT_RIG_ROOT = projectRoot;
|
|
@@ -7947,14 +8016,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7947
8016
|
if (runtimeRoot) {
|
|
7948
8017
|
env.RIG_RUNTIME_HOME = runtimeRoot;
|
|
7949
8018
|
}
|
|
7950
|
-
if (runtimeHome &&
|
|
8019
|
+
if (runtimeHome && existsSync23(runtimeHome)) {
|
|
7951
8020
|
env.HOME = runtimeHome;
|
|
7952
8021
|
env.OPENSSL_CONF = ensureRuntimeOpenSslConfig(runtimeHome);
|
|
7953
8022
|
}
|
|
7954
|
-
if (runtimeTmp &&
|
|
8023
|
+
if (runtimeTmp && existsSync23(runtimeTmp)) {
|
|
7955
8024
|
env.TMPDIR = runtimeTmp;
|
|
7956
8025
|
}
|
|
7957
|
-
if (runtimeCache &&
|
|
8026
|
+
if (runtimeCache && existsSync23(runtimeCache)) {
|
|
7958
8027
|
env.XDG_CACHE_HOME = runtimeCache;
|
|
7959
8028
|
}
|
|
7960
8029
|
const workspaceSecrets = loadDotEnvSecrets(ctx?.workspaceDir || projectRoot, process.env);
|
|
@@ -7998,14 +8067,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7998
8067
|
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
7999
8068
|
applyGitHubCredentialHelperEnv(env);
|
|
8000
8069
|
}
|
|
8001
|
-
if (runtimeKnownHosts &&
|
|
8070
|
+
if (runtimeKnownHosts && existsSync23(runtimeKnownHosts)) {
|
|
8002
8071
|
const sshParts = [
|
|
8003
8072
|
"ssh",
|
|
8004
8073
|
`-o UserKnownHostsFile="${runtimeKnownHosts}"`,
|
|
8005
8074
|
"-o StrictHostKeyChecking=yes",
|
|
8006
8075
|
"-F /dev/null"
|
|
8007
8076
|
];
|
|
8008
|
-
if (runtimeKey &&
|
|
8077
|
+
if (runtimeKey && existsSync23(runtimeKey)) {
|
|
8009
8078
|
sshParts.splice(1, 0, `-i "${runtimeKey}"`, "-o IdentitiesOnly=yes");
|
|
8010
8079
|
}
|
|
8011
8080
|
env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
@@ -8026,12 +8095,12 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
|
8026
8095
|
if (!runtimeRoot) {
|
|
8027
8096
|
return {};
|
|
8028
8097
|
}
|
|
8029
|
-
const path =
|
|
8030
|
-
if (!
|
|
8098
|
+
const path = resolve27(runtimeRoot, "runtime-secrets.json");
|
|
8099
|
+
if (!existsSync23(path)) {
|
|
8031
8100
|
return {};
|
|
8032
8101
|
}
|
|
8033
8102
|
try {
|
|
8034
|
-
const parsed = JSON.parse(
|
|
8103
|
+
const parsed = JSON.parse(readFileSync14(path, "utf-8"));
|
|
8035
8104
|
const entries = Object.entries(parsed).filter((entry) => typeof entry[1] === "string");
|
|
8036
8105
|
return Object.fromEntries(entries);
|
|
8037
8106
|
} catch {
|
|
@@ -8039,13 +8108,13 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
|
8039
8108
|
}
|
|
8040
8109
|
}
|
|
8041
8110
|
function ensureRuntimeOpenSslConfig(runtimeHome) {
|
|
8042
|
-
const sslDir =
|
|
8043
|
-
const sslConfig =
|
|
8044
|
-
if (!
|
|
8045
|
-
|
|
8111
|
+
const sslDir = resolve27(runtimeHome, ".ssl");
|
|
8112
|
+
const sslConfig = resolve27(sslDir, "openssl.cnf");
|
|
8113
|
+
if (!existsSync23(sslDir)) {
|
|
8114
|
+
mkdirSync11(sslDir, { recursive: true });
|
|
8046
8115
|
}
|
|
8047
|
-
if (!
|
|
8048
|
-
|
|
8116
|
+
if (!existsSync23(sslConfig)) {
|
|
8117
|
+
writeFileSync11(sslConfig, `# Rig runtime OpenSSL config placeholder
|
|
8049
8118
|
`);
|
|
8050
8119
|
}
|
|
8051
8120
|
return sslConfig;
|
|
@@ -8063,11 +8132,11 @@ function resolveRuntimeMetadata(projectRoot) {
|
|
|
8063
8132
|
if (contextFile) {
|
|
8064
8133
|
return {
|
|
8065
8134
|
ctx,
|
|
8066
|
-
runtimeRoot: dirname14(
|
|
8135
|
+
runtimeRoot: dirname14(resolve27(contextFile))
|
|
8067
8136
|
};
|
|
8068
8137
|
}
|
|
8069
8138
|
const inferredContextFile = findRuntimeContextFile2(projectRoot);
|
|
8070
|
-
if (
|
|
8139
|
+
if (existsSync23(inferredContextFile)) {
|
|
8071
8140
|
try {
|
|
8072
8141
|
ctx = loadRuntimeContext(inferredContextFile);
|
|
8073
8142
|
} catch {}
|
|
@@ -8079,10 +8148,10 @@ function resolveRuntimeMetadata(projectRoot) {
|
|
|
8079
8148
|
return { ctx, runtimeRoot: "" };
|
|
8080
8149
|
}
|
|
8081
8150
|
function findRuntimeContextFile2(startPath) {
|
|
8082
|
-
let current =
|
|
8151
|
+
let current = resolve27(startPath);
|
|
8083
8152
|
while (true) {
|
|
8084
|
-
const candidate =
|
|
8085
|
-
if (
|
|
8153
|
+
const candidate = resolve27(current, "runtime-context.json");
|
|
8154
|
+
if (existsSync23(candidate)) {
|
|
8086
8155
|
return candidate;
|
|
8087
8156
|
}
|
|
8088
8157
|
const parent = dirname14(current);
|
|
@@ -8094,7 +8163,7 @@ function findRuntimeContextFile2(startPath) {
|
|
|
8094
8163
|
}
|
|
8095
8164
|
|
|
8096
8165
|
// packages/runtime/src/control-plane/native/profile-ops.ts
|
|
8097
|
-
import { existsSync as
|
|
8166
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
8098
8167
|
var DEFAULTS = {
|
|
8099
8168
|
model: parseEnvOrDefault(process.env.DEFAULT_AGENT_MODEL, ["claude", "gpt-codex", "pi"], "pi"),
|
|
8100
8169
|
runtime: parseEnvOrDefault(process.env.DEFAULT_AGENT_RUNTIME, ["claude-code", "codex-app-server", "pi"], "pi"),
|
|
@@ -8109,7 +8178,7 @@ function parseEnvOrDefault(value, allowed, fallback) {
|
|
|
8109
8178
|
return allowed.includes(value) ? value : fallback;
|
|
8110
8179
|
}
|
|
8111
8180
|
async function readProfileFile(path) {
|
|
8112
|
-
if (!
|
|
8181
|
+
if (!existsSync24(path)) {
|
|
8113
8182
|
return null;
|
|
8114
8183
|
}
|
|
8115
8184
|
try {
|
|
@@ -8162,14 +8231,14 @@ async function setProfile(projectRoot, options) {
|
|
|
8162
8231
|
plugin = model === "gpt-codex" ? "codex" : model === "pi" ? "pi" : "claude";
|
|
8163
8232
|
}
|
|
8164
8233
|
const paths = resolveHarnessPaths(projectRoot);
|
|
8165
|
-
|
|
8234
|
+
mkdirSync12(paths.stateDir, { recursive: true });
|
|
8166
8235
|
const next = {
|
|
8167
8236
|
model,
|
|
8168
8237
|
runtime,
|
|
8169
8238
|
agent_plugin: plugin,
|
|
8170
8239
|
updated_at: new Date().toISOString()
|
|
8171
8240
|
};
|
|
8172
|
-
|
|
8241
|
+
writeFileSync12(paths.agentProfilePath, `${JSON.stringify(next, null, 2)}
|
|
8173
8242
|
`, "utf-8");
|
|
8174
8243
|
await showProfile(projectRoot, false);
|
|
8175
8244
|
}
|
|
@@ -8205,13 +8274,13 @@ async function setReviewProfile(projectRoot, mode, provider) {
|
|
|
8205
8274
|
throw new Error(`Invalid provider: ${resolvedProvider}. Supported: greptile.`);
|
|
8206
8275
|
}
|
|
8207
8276
|
const paths = resolveHarnessPaths(projectRoot);
|
|
8208
|
-
|
|
8277
|
+
mkdirSync12(paths.stateDir, { recursive: true });
|
|
8209
8278
|
const next = {
|
|
8210
8279
|
mode,
|
|
8211
8280
|
provider: resolvedProvider,
|
|
8212
8281
|
updated_at: new Date().toISOString()
|
|
8213
8282
|
};
|
|
8214
|
-
|
|
8283
|
+
writeFileSync12(paths.reviewProfilePath, `${JSON.stringify(next, null, 2)}
|
|
8215
8284
|
`, "utf-8");
|
|
8216
8285
|
await showReviewProfile(projectRoot);
|
|
8217
8286
|
}
|
|
@@ -8249,44 +8318,44 @@ async function loadReviewProfile(path) {
|
|
|
8249
8318
|
}
|
|
8250
8319
|
|
|
8251
8320
|
// packages/runtime/src/control-plane/native/repo-ops.ts
|
|
8252
|
-
import { existsSync as
|
|
8253
|
-
import { basename as basename8, dirname as dirname16, resolve as
|
|
8321
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync16, readFileSync as readFileSync16, readdirSync as readdirSync6, rmSync as rmSync8, writeFileSync as writeFileSync14 } from "fs";
|
|
8322
|
+
import { basename as basename8, dirname as dirname16, resolve as resolve31 } from "path";
|
|
8254
8323
|
// packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
|
|
8255
|
-
import { existsSync as
|
|
8256
|
-
import { resolve as
|
|
8324
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync14, realpathSync as realpathSync2 } from "fs";
|
|
8325
|
+
import { resolve as resolve29 } from "path";
|
|
8257
8326
|
|
|
8258
8327
|
// packages/runtime/src/control-plane/authority-files.ts
|
|
8259
|
-
import { existsSync as
|
|
8260
|
-
import { dirname as dirname15, join as join5, relative, resolve as
|
|
8328
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync13, readFileSync as readFileSync15, writeFileSync as writeFileSync13, appendFileSync as appendFileSync2, copyFileSync as copyFileSync3, statSync as statSync6, readdirSync as readdirSync5, chmodSync as chmodSync3 } from "fs";
|
|
8329
|
+
import { dirname as dirname15, join as join5, relative, resolve as resolve28 } from "path";
|
|
8261
8330
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
8262
8331
|
function resolveAuthorityProjectStateDir(projectRoot) {
|
|
8263
8332
|
const explicit = process.env.RIG_STATE_DIR?.trim();
|
|
8264
8333
|
if (explicit) {
|
|
8265
|
-
return
|
|
8334
|
+
return resolve28(explicit);
|
|
8266
8335
|
}
|
|
8267
|
-
return
|
|
8336
|
+
return resolve28(resolve28(projectRoot), ".rig", "state");
|
|
8268
8337
|
}
|
|
8269
8338
|
function readJsonAtPath(path, fallback) {
|
|
8270
|
-
if (!
|
|
8339
|
+
if (!existsSync25(path)) {
|
|
8271
8340
|
return fallback;
|
|
8272
8341
|
}
|
|
8273
8342
|
try {
|
|
8274
|
-
return JSON.parse(
|
|
8343
|
+
return JSON.parse(readFileSync15(path, "utf-8"));
|
|
8275
8344
|
} catch {
|
|
8276
8345
|
return fallback;
|
|
8277
8346
|
}
|
|
8278
8347
|
}
|
|
8279
8348
|
function writeJsonAtPath(path, value) {
|
|
8280
|
-
|
|
8281
|
-
|
|
8349
|
+
mkdirSync13(dirname15(path), { recursive: true });
|
|
8350
|
+
writeFileSync13(path, `${JSON.stringify(value, null, 2)}
|
|
8282
8351
|
`, "utf8");
|
|
8283
8352
|
return path;
|
|
8284
8353
|
}
|
|
8285
8354
|
function readAuthorityProjectStateJson(projectRoot, relativePath, fallback) {
|
|
8286
|
-
return readJsonAtPath(
|
|
8355
|
+
return readJsonAtPath(resolve28(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
|
|
8287
8356
|
}
|
|
8288
8357
|
function writeAuthorityProjectStateJson(projectRoot, relativePath, value) {
|
|
8289
|
-
return writeJsonAtPath(
|
|
8358
|
+
return writeJsonAtPath(resolve28(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
|
|
8290
8359
|
}
|
|
8291
8360
|
|
|
8292
8361
|
// packages/runtime/src/control-plane/repos/mirror/state.ts
|
|
@@ -8346,7 +8415,7 @@ function sameExistingPath(left, right) {
|
|
|
8346
8415
|
try {
|
|
8347
8416
|
return realpathSync2(left) === realpathSync2(right);
|
|
8348
8417
|
} catch {
|
|
8349
|
-
return
|
|
8418
|
+
return resolve29(left) === resolve29(right);
|
|
8350
8419
|
}
|
|
8351
8420
|
}
|
|
8352
8421
|
function repoLooksUsable(repoRoot, projectRoot) {
|
|
@@ -8382,7 +8451,7 @@ function resolveMirrorRemoteUrl(layout) {
|
|
|
8382
8451
|
}
|
|
8383
8452
|
}
|
|
8384
8453
|
}
|
|
8385
|
-
if (
|
|
8454
|
+
if (existsSync26(resolve29(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
|
|
8386
8455
|
const checkoutOrigin = runGit(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
8387
8456
|
if (checkoutOrigin.exitCode === 0) {
|
|
8388
8457
|
const currentOrigin = checkoutOrigin.stdout.trim();
|
|
@@ -8395,9 +8464,9 @@ function resolveMirrorRemoteUrl(layout) {
|
|
|
8395
8464
|
}
|
|
8396
8465
|
function ensureManagedRepoMirror(projectRoot, repoId) {
|
|
8397
8466
|
const layout = resolveManagedRepoLayout(projectRoot, repoId);
|
|
8398
|
-
|
|
8467
|
+
mkdirSync14(layout.metadataRoot, { recursive: true });
|
|
8399
8468
|
const remoteUrl = resolveMirrorRemoteUrl(layout);
|
|
8400
|
-
if (!
|
|
8469
|
+
if (!existsSync26(resolve29(layout.mirrorRoot, "HEAD"))) {
|
|
8401
8470
|
ensureGitSuccess(runGit(["git", "init", "--bare", layout.mirrorRoot], layout.projectRoot), ["git", "init", "--bare", layout.mirrorRoot]);
|
|
8402
8471
|
}
|
|
8403
8472
|
const getOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
@@ -8417,8 +8486,8 @@ function ensureManagedRepoMirror(projectRoot, repoId) {
|
|
|
8417
8486
|
return layout;
|
|
8418
8487
|
}
|
|
8419
8488
|
// packages/runtime/src/control-plane/repos/mirror/refresh.ts
|
|
8420
|
-
import { existsSync as
|
|
8421
|
-
import { resolve as
|
|
8489
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync15, realpathSync as realpathSync3, rmSync as rmSync7 } from "fs";
|
|
8490
|
+
import { resolve as resolve30 } from "path";
|
|
8422
8491
|
function nowIso3() {
|
|
8423
8492
|
return new Date().toISOString();
|
|
8424
8493
|
}
|
|
@@ -8445,7 +8514,7 @@ function sameExistingPath2(left, right) {
|
|
|
8445
8514
|
try {
|
|
8446
8515
|
return realpathSync3(left) === realpathSync3(right);
|
|
8447
8516
|
} catch {
|
|
8448
|
-
return
|
|
8517
|
+
return resolve30(left) === resolve30(right);
|
|
8449
8518
|
}
|
|
8450
8519
|
}
|
|
8451
8520
|
function ensureMirrorHead(layout) {
|
|
@@ -8491,12 +8560,12 @@ function checkoutLooksUsable2(layout) {
|
|
|
8491
8560
|
return probe.exitCode === 0 && sameExistingPath2(probe.stdout.trim(), layout.checkoutRoot);
|
|
8492
8561
|
}
|
|
8493
8562
|
function ensureCheckoutFromMirror(layout) {
|
|
8494
|
-
|
|
8495
|
-
const gitPath =
|
|
8496
|
-
if (
|
|
8497
|
-
|
|
8563
|
+
mkdirSync15(resolve30(layout.checkoutRoot, ".."), { recursive: true });
|
|
8564
|
+
const gitPath = resolve30(layout.checkoutRoot, ".git");
|
|
8565
|
+
if (existsSync27(layout.checkoutRoot) && (!existsSync27(gitPath) || !checkoutLooksUsable2(layout))) {
|
|
8566
|
+
rmSync7(layout.checkoutRoot, { recursive: true, force: true });
|
|
8498
8567
|
}
|
|
8499
|
-
if (!
|
|
8568
|
+
if (!existsSync27(gitPath)) {
|
|
8500
8569
|
ensureGitSuccess2(runGit2(["git", "clone", layout.mirrorRoot, layout.checkoutRoot], layout.projectRoot), ["git", "clone", layout.mirrorRoot, layout.checkoutRoot]);
|
|
8501
8570
|
}
|
|
8502
8571
|
const getOrigin = runGit2(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
@@ -8597,7 +8666,7 @@ function repoDiscover(projectRoot, taskId) {
|
|
|
8597
8666
|
}
|
|
8598
8667
|
function repoBaseline(projectRoot, refresh = false) {
|
|
8599
8668
|
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
8600
|
-
if (!refresh &&
|
|
8669
|
+
if (!refresh && existsSync28(paths.baseRepoPinsPath)) {
|
|
8601
8670
|
const baseline = readJsonFile(paths.baseRepoPinsPath, { recorded_at: nowIso(), repos: {} });
|
|
8602
8671
|
return baseline.repos || {};
|
|
8603
8672
|
}
|
|
@@ -8621,8 +8690,8 @@ function ensureMonorepoReady(projectRoot) {
|
|
|
8621
8690
|
}
|
|
8622
8691
|
function persistBaselinePins(projectRoot, repos) {
|
|
8623
8692
|
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
8624
|
-
|
|
8625
|
-
|
|
8693
|
+
mkdirSync16(resolve31(paths.baseRepoPinsPath, ".."), { recursive: true });
|
|
8694
|
+
writeFileSync14(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
|
|
8626
8695
|
`, "utf-8");
|
|
8627
8696
|
return repos;
|
|
8628
8697
|
}
|
|
@@ -8701,28 +8770,28 @@ function readRepoDiscoveryTaskConfig(projectRoot) {
|
|
|
8701
8770
|
function resolveRepoDiscoveryPaths(projectRoot) {
|
|
8702
8771
|
const monorepoRoot = resolveMonorepoRepoLayout(projectRoot).checkoutRoot;
|
|
8703
8772
|
const explicitHostProjectRoot = (process.env.RIG_HOST_PROJECT_ROOT || "").trim();
|
|
8704
|
-
const normalizedProjectRoot =
|
|
8773
|
+
const normalizedProjectRoot = resolve31(projectRoot);
|
|
8705
8774
|
const hostProjectRoot = explicitHostProjectRoot && shouldUseHostProjectStateRoot(normalizedProjectRoot) ? explicitHostProjectRoot : normalizedProjectRoot;
|
|
8706
|
-
const stateDir =
|
|
8775
|
+
const stateDir = resolve31(hostProjectRoot, ".rig", "state");
|
|
8707
8776
|
return {
|
|
8708
8777
|
monorepoRoot,
|
|
8709
|
-
taskRepoCommitsPath:
|
|
8710
|
-
baseRepoPinsPath:
|
|
8778
|
+
taskRepoCommitsPath: resolve31(stateDir, "task-repo-commits.json"),
|
|
8779
|
+
baseRepoPinsPath: resolve31(stateDir, "base-repo-pins.json")
|
|
8711
8780
|
};
|
|
8712
8781
|
}
|
|
8713
8782
|
function shouldUseHostProjectStateRoot(projectRoot) {
|
|
8714
8783
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
8715
|
-
if (runtimeWorkspace &&
|
|
8784
|
+
if (runtimeWorkspace && resolve31(runtimeWorkspace) === projectRoot) {
|
|
8716
8785
|
return true;
|
|
8717
8786
|
}
|
|
8718
8787
|
return basename8(dirname16(projectRoot)) === ".worktrees";
|
|
8719
8788
|
}
|
|
8720
8789
|
function readPinFromArtifact(projectRoot, depTask, repoKey) {
|
|
8721
|
-
const snapshot =
|
|
8722
|
-
if (!
|
|
8790
|
+
const snapshot = resolve31(artifactDirForId(projectRoot, depTask), "git-state.txt");
|
|
8791
|
+
if (!existsSync28(snapshot)) {
|
|
8723
8792
|
return "";
|
|
8724
8793
|
}
|
|
8725
|
-
const content =
|
|
8794
|
+
const content = readFileSync16(snapshot, "utf-8");
|
|
8726
8795
|
const chunk = content.split(/\r?\n/);
|
|
8727
8796
|
let inSection = false;
|
|
8728
8797
|
for (const line of chunk) {
|
|
@@ -8744,12 +8813,12 @@ function repoPath(projectRoot, key) {
|
|
|
8744
8813
|
if (managed) {
|
|
8745
8814
|
return managed.checkoutRoot;
|
|
8746
8815
|
}
|
|
8747
|
-
return key.startsWith("/") ? key :
|
|
8816
|
+
return key.startsWith("/") ? key : resolve31(projectRoot, key);
|
|
8748
8817
|
}
|
|
8749
8818
|
function applyPins(projectRoot, pins) {
|
|
8750
8819
|
for (const [key, commit] of Object.entries(pins)) {
|
|
8751
8820
|
const path = repoPath(projectRoot, key);
|
|
8752
|
-
if (!
|
|
8821
|
+
if (!existsSync28(resolve31(path, ".git"))) {
|
|
8753
8822
|
throw new Error(`Repo for pin not available: ${key} (${path})`);
|
|
8754
8823
|
}
|
|
8755
8824
|
let hasCommit = runGitCapture(["git", "-C", path, "cat-file", "-e", `${commit}^{commit}`], projectRoot).exitCode === 0;
|
|
@@ -8778,7 +8847,7 @@ function verifyPins(projectRoot, pins) {
|
|
|
8778
8847
|
let ok = true;
|
|
8779
8848
|
for (const [key, expected] of Object.entries(pins)) {
|
|
8780
8849
|
const path = repoPath(projectRoot, key);
|
|
8781
|
-
if (!
|
|
8850
|
+
if (!existsSync28(resolve31(path, ".git"))) {
|
|
8782
8851
|
console.error(`ERROR: repo missing during pin verification: ${key}`);
|
|
8783
8852
|
ok = false;
|
|
8784
8853
|
continue;
|
|
@@ -8803,23 +8872,23 @@ function resolveRuntimeGitEnv() {
|
|
|
8803
8872
|
GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND
|
|
8804
8873
|
};
|
|
8805
8874
|
}
|
|
8806
|
-
const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ?
|
|
8807
|
-
const runtimeHome = runtimeRoot ?
|
|
8875
|
+
const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ? resolve31(process.env.RIG_RUNTIME_CONTEXT_FILE, "..") : inferRuntimeRootFromWorkspace(process.cwd()));
|
|
8876
|
+
const runtimeHome = runtimeRoot ? resolve31(runtimeRoot, "home") : process.env.HOME?.trim() || "";
|
|
8808
8877
|
if (!runtimeHome) {
|
|
8809
8878
|
return;
|
|
8810
8879
|
}
|
|
8811
|
-
const knownHostsPath =
|
|
8812
|
-
if (!
|
|
8880
|
+
const knownHostsPath = resolve31(runtimeHome, ".ssh", "known_hosts");
|
|
8881
|
+
if (!existsSync28(knownHostsPath)) {
|
|
8813
8882
|
return { HOME: runtimeHome };
|
|
8814
8883
|
}
|
|
8815
|
-
const agentSshKey =
|
|
8884
|
+
const agentSshKey = resolve31(runtimeHome, ".ssh", "rig-agent-key");
|
|
8816
8885
|
const sshParts = [
|
|
8817
8886
|
"ssh",
|
|
8818
8887
|
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
8819
8888
|
"-o StrictHostKeyChecking=yes",
|
|
8820
8889
|
"-F /dev/null"
|
|
8821
8890
|
];
|
|
8822
|
-
if (
|
|
8891
|
+
if (existsSync28(agentSshKey)) {
|
|
8823
8892
|
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
8824
8893
|
}
|
|
8825
8894
|
return {
|
|
@@ -8829,24 +8898,24 @@ function resolveRuntimeGitEnv() {
|
|
|
8829
8898
|
}
|
|
8830
8899
|
function inferRuntimeRootFromWorkspace(cwd) {
|
|
8831
8900
|
const contextPath = findRuntimeContextFile3(cwd);
|
|
8832
|
-
if (!contextPath || !
|
|
8901
|
+
if (!contextPath || !existsSync28(contextPath)) {
|
|
8833
8902
|
return "";
|
|
8834
8903
|
}
|
|
8835
8904
|
try {
|
|
8836
8905
|
loadRuntimeContext(contextPath);
|
|
8837
|
-
return
|
|
8906
|
+
return resolve31(contextPath, "..");
|
|
8838
8907
|
} catch {
|
|
8839
8908
|
return "";
|
|
8840
8909
|
}
|
|
8841
8910
|
}
|
|
8842
8911
|
function findRuntimeContextFile3(startPath) {
|
|
8843
|
-
let current =
|
|
8912
|
+
let current = resolve31(startPath);
|
|
8844
8913
|
while (true) {
|
|
8845
|
-
const candidate =
|
|
8846
|
-
if (
|
|
8914
|
+
const candidate = resolve31(current, "runtime-context.json");
|
|
8915
|
+
if (existsSync28(candidate)) {
|
|
8847
8916
|
return candidate;
|
|
8848
8917
|
}
|
|
8849
|
-
const parent =
|
|
8918
|
+
const parent = resolve31(current, "..");
|
|
8850
8919
|
if (parent === current) {
|
|
8851
8920
|
return "";
|
|
8852
8921
|
}
|
|
@@ -8900,7 +8969,7 @@ function getEventBus() {
|
|
|
8900
8969
|
}
|
|
8901
8970
|
function inferRuntimeContext() {
|
|
8902
8971
|
for (const candidate of runtimeContextCandidates()) {
|
|
8903
|
-
if (!candidate || !
|
|
8972
|
+
if (!candidate || !existsSync29(candidate)) {
|
|
8904
8973
|
continue;
|
|
8905
8974
|
}
|
|
8906
8975
|
try {
|
|
@@ -8913,15 +8982,15 @@ function inferRuntimeContext() {
|
|
|
8913
8982
|
function runtimeContextCandidates() {
|
|
8914
8983
|
const cwd = process.cwd();
|
|
8915
8984
|
const candidates = [
|
|
8916
|
-
|
|
8917
|
-
|
|
8985
|
+
resolve32(cwd, "..", "runtime-context.json"),
|
|
8986
|
+
resolve32(cwd, ".rig", "runtime-context.json")
|
|
8918
8987
|
];
|
|
8919
8988
|
const argv1 = process.argv[1]?.trim();
|
|
8920
8989
|
if (argv1) {
|
|
8921
|
-
candidates.push(
|
|
8990
|
+
candidates.push(resolve32(argv1, "..", "..", "runtime-context.json"));
|
|
8922
8991
|
}
|
|
8923
8992
|
if (BAKED_BINARY_PATH) {
|
|
8924
|
-
candidates.push(
|
|
8993
|
+
candidates.push(resolve32(BAKED_BINARY_PATH, "..", "..", "runtime-context.json"));
|
|
8925
8994
|
}
|
|
8926
8995
|
return Array.from(new Set(candidates));
|
|
8927
8996
|
}
|
|
@@ -8936,12 +9005,12 @@ var GITHUB_KNOWN_HOSTS = [
|
|
|
8936
9005
|
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
|
|
8937
9006
|
];
|
|
8938
9007
|
function ensureRuntimeKnownHosts(runtimeHome) {
|
|
8939
|
-
const sshDir =
|
|
8940
|
-
const knownHostsPath =
|
|
8941
|
-
if (!
|
|
8942
|
-
|
|
9008
|
+
const sshDir = resolve32(runtimeHome, ".ssh");
|
|
9009
|
+
const knownHostsPath = resolve32(sshDir, "known_hosts");
|
|
9010
|
+
if (!existsSync29(sshDir)) {
|
|
9011
|
+
mkdirSync17(sshDir, { recursive: true });
|
|
8943
9012
|
}
|
|
8944
|
-
const existing =
|
|
9013
|
+
const existing = existsSync29(knownHostsPath) ? readFileSync17(knownHostsPath, "utf-8") : "";
|
|
8945
9014
|
const existingLines = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
8946
9015
|
const missing = GITHUB_KNOWN_HOSTS.filter((line) => !existingLines.has(line));
|
|
8947
9016
|
if (missing.length === 0) {
|
|
@@ -8951,11 +9020,11 @@ function ensureRuntimeKnownHosts(runtimeHome) {
|
|
|
8951
9020
|
for (const line of missing) {
|
|
8952
9021
|
existingLines.add(line);
|
|
8953
9022
|
}
|
|
8954
|
-
|
|
9023
|
+
writeFileSync15(knownHostsPath, `${Array.from(existingLines).join(`
|
|
8955
9024
|
`)}
|
|
8956
9025
|
`, { mode: 420 });
|
|
8957
9026
|
} catch (err) {
|
|
8958
|
-
const hint =
|
|
9027
|
+
const hint = existsSync29(knownHostsPath) ? "" : " \u2014 known_hosts is missing; git SSH operations may fail";
|
|
8959
9028
|
console.warn(`[rig-agent] Could not update ${knownHostsPath}: ${err instanceof Error ? err.message : String(err)}${hint}`);
|
|
8960
9029
|
}
|
|
8961
9030
|
return knownHostsPath;
|
|
@@ -8969,13 +9038,13 @@ function hydrateRuntimeProcessEnv(ctx) {
|
|
|
8969
9038
|
return;
|
|
8970
9039
|
}
|
|
8971
9040
|
process.env.RIG_RUNTIME_CONTEXT_FILE = contextFile;
|
|
8972
|
-
const runtimeRoot = dirname17(
|
|
8973
|
-
const runtimeHome =
|
|
8974
|
-
const runtimeTmp =
|
|
8975
|
-
const runtimeCache =
|
|
8976
|
-
const runtimeBin =
|
|
8977
|
-
const runtimeWorkspaceBin =
|
|
8978
|
-
const runtimeTools =
|
|
9041
|
+
const runtimeRoot = dirname17(resolve32(contextFile));
|
|
9042
|
+
const runtimeHome = resolve32(runtimeRoot, "home");
|
|
9043
|
+
const runtimeTmp = resolve32(runtimeRoot, "tmp");
|
|
9044
|
+
const runtimeCache = resolve32(runtimeRoot, "cache");
|
|
9045
|
+
const runtimeBin = resolve32(runtimeRoot, "bin");
|
|
9046
|
+
const runtimeWorkspaceBin = resolve32(ctx.workspaceDir, ".rig", "bin");
|
|
9047
|
+
const runtimeTools = resolve32(ctx.workspaceDir, "rig", "tools");
|
|
8979
9048
|
if (ctx.hostProjectRoot) {
|
|
8980
9049
|
process.env.PROJECT_RIG_ROOT = ctx.hostProjectRoot;
|
|
8981
9050
|
}
|
|
@@ -8991,13 +9060,13 @@ function hydrateRuntimeProcessEnv(ctx) {
|
|
|
8991
9060
|
for (const [key, value] of Object.entries(browserEnvFromContext(ctx.browser))) {
|
|
8992
9061
|
process.env[key] = value;
|
|
8993
9062
|
}
|
|
8994
|
-
if (
|
|
9063
|
+
if (existsSync29(runtimeHome)) {
|
|
8995
9064
|
process.env.HOME = runtimeHome;
|
|
8996
9065
|
}
|
|
8997
|
-
if (
|
|
9066
|
+
if (existsSync29(runtimeTmp)) {
|
|
8998
9067
|
process.env.TMPDIR = runtimeTmp;
|
|
8999
9068
|
}
|
|
9000
|
-
if (
|
|
9069
|
+
if (existsSync29(runtimeCache)) {
|
|
9001
9070
|
process.env.XDG_CACHE_HOME = runtimeCache;
|
|
9002
9071
|
}
|
|
9003
9072
|
const workspaceSecrets = loadDotEnvSecrets(ctx.workspaceDir, process.env);
|
|
@@ -9023,31 +9092,31 @@ function hydrateRuntimeProcessEnv(ctx) {
|
|
|
9023
9092
|
const currentPath = process.env.PATH || "";
|
|
9024
9093
|
const pathEntries = currentPath.split(":").filter(Boolean);
|
|
9025
9094
|
for (const entry of [runtimeBin, runtimeWorkspaceBin, runtimeTools, "/usr/bin", "/bin", "/usr/sbin", "/sbin"]) {
|
|
9026
|
-
if (
|
|
9095
|
+
if (existsSync29(entry) && !pathEntries.includes(entry)) {
|
|
9027
9096
|
pathEntries.unshift(entry);
|
|
9028
9097
|
}
|
|
9029
9098
|
}
|
|
9030
9099
|
process.env.PATH = pathEntries.join(":");
|
|
9031
9100
|
if (!process.env.RIG_GIT_BIN) {
|
|
9032
|
-
const runtimeGit =
|
|
9033
|
-
process.env.RIG_GIT_BIN =
|
|
9101
|
+
const runtimeGit = resolve32(runtimeBin, "git");
|
|
9102
|
+
process.env.RIG_GIT_BIN = existsSync29(runtimeGit) ? runtimeGit : Bun.which("git") || "/usr/bin/git";
|
|
9034
9103
|
}
|
|
9035
9104
|
const knownHosts = ensureRuntimeKnownHosts(runtimeHome);
|
|
9036
|
-
const agentKey =
|
|
9105
|
+
const agentKey = resolve32(runtimeHome, ".ssh", "rig-agent-key");
|
|
9037
9106
|
const sshParts = [
|
|
9038
9107
|
"ssh",
|
|
9039
9108
|
`-o UserKnownHostsFile="${knownHosts}"`,
|
|
9040
9109
|
"-o StrictHostKeyChecking=yes",
|
|
9041
9110
|
"-F /dev/null"
|
|
9042
9111
|
];
|
|
9043
|
-
if (
|
|
9112
|
+
if (existsSync29(agentKey)) {
|
|
9044
9113
|
sshParts.splice(1, 0, `-i "${agentKey}"`, "-o IdentitiesOnly=yes");
|
|
9045
9114
|
}
|
|
9046
9115
|
process.env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
9047
9116
|
}
|
|
9048
9117
|
function inferRuntimeContextFileFromWorkspace(workspaceDir) {
|
|
9049
|
-
const candidate =
|
|
9050
|
-
return
|
|
9118
|
+
const candidate = resolve32(workspaceDir, "..", "runtime-context.json");
|
|
9119
|
+
return existsSync29(candidate) ? candidate : "";
|
|
9051
9120
|
}
|
|
9052
9121
|
async function main() {
|
|
9053
9122
|
const args = process.argv.slice(2);
|
|
@@ -9172,7 +9241,7 @@ async function runAgentCommand(args) {
|
|
|
9172
9241
|
const fileIdx = rest.indexOf("--file");
|
|
9173
9242
|
const inputFile = fileIdx !== -1 ? rest[fileIdx + 1] : undefined;
|
|
9174
9243
|
if (inputFile) {
|
|
9175
|
-
content =
|
|
9244
|
+
content = readFileSync17(resolve32(projectRoot, inputFile), "utf-8");
|
|
9176
9245
|
} else {
|
|
9177
9246
|
const chunks = [];
|
|
9178
9247
|
for await (const chunk of process.stdin) {
|
|
@@ -9475,8 +9544,8 @@ WORKFLOW:
|
|
|
9475
9544
|
`);
|
|
9476
9545
|
}
|
|
9477
9546
|
async function runCompletionVerification(projectRoot) {
|
|
9478
|
-
const hookPath =
|
|
9479
|
-
if (!
|
|
9547
|
+
const hookPath = resolve32(projectRoot, ".rig/bin/hooks/completion-verification");
|
|
9548
|
+
if (!existsSync29(hookPath)) {
|
|
9480
9549
|
console.error(`[rig-agent] completion-verification hook binary not found: ${hookPath}`);
|
|
9481
9550
|
return 1;
|
|
9482
9551
|
}
|
|
@@ -9510,7 +9579,7 @@ async function verifyRuntimeManifest() {
|
|
|
9510
9579
|
if (!manifestPath) {
|
|
9511
9580
|
return;
|
|
9512
9581
|
}
|
|
9513
|
-
if (!
|
|
9582
|
+
if (!existsSync29(manifestPath)) {
|
|
9514
9583
|
throw new Error(`[rig-agent] Runtime manifest missing: ${manifestPath}`);
|
|
9515
9584
|
}
|
|
9516
9585
|
let manifest;
|
|
@@ -9527,10 +9596,10 @@ async function verifyRuntimeManifest() {
|
|
|
9527
9596
|
if (!manifestBinaryPath || !expectedHash) {
|
|
9528
9597
|
throw new Error(`[rig-agent] Runtime manifest is missing binary hash data (${manifestPath}).`);
|
|
9529
9598
|
}
|
|
9530
|
-
if (!
|
|
9599
|
+
if (!existsSync29(manifestBinaryPath)) {
|
|
9531
9600
|
throw new Error(`[rig-agent] Runtime binary not found at ${manifestBinaryPath}.`);
|
|
9532
9601
|
}
|
|
9533
|
-
const actualHash = sha256Hex(
|
|
9602
|
+
const actualHash = sha256Hex(readFileSync17(resolve32(manifestBinaryPath)));
|
|
9534
9603
|
if (actualHash !== expectedHash) {
|
|
9535
9604
|
throw new Error(`[rig-agent] Runtime manifest mismatch for binary hash.
|
|
9536
9605
|
` + `expected=${expectedHash}
|