@h-rig/runtime 0.0.6-alpha.2 → 0.0.6-alpha.21

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.
Files changed (46) hide show
  1. package/dist/bin/rig-agent-dispatch.js +84 -313
  2. package/dist/bin/rig-agent.js +85 -27
  3. package/dist/src/control-plane/agent-wrapper.js +101 -27
  4. package/dist/src/control-plane/authority-files.js +12 -6
  5. package/dist/src/control-plane/harness-main.js +1357 -180
  6. package/dist/src/control-plane/hooks/completion-verification.js +1669 -329
  7. package/dist/src/control-plane/hooks/inject-context.js +2 -2
  8. package/dist/src/control-plane/hooks/submodule-branch.js +26 -3
  9. package/dist/src/control-plane/hooks/task-runtime-start.js +26 -3
  10. package/dist/src/control-plane/native/git-ops.js +134 -68
  11. package/dist/src/control-plane/native/harness-cli.js +1357 -180
  12. package/dist/src/control-plane/native/pr-automation.js +1532 -54
  13. package/dist/src/control-plane/native/pr-review-gate.js +1330 -0
  14. package/dist/src/control-plane/native/run-ops.js +35 -12
  15. package/dist/src/control-plane/native/task-ops.js +1274 -155
  16. package/dist/src/control-plane/native/validator.js +2 -2
  17. package/dist/src/control-plane/native/verifier.js +1274 -154
  18. package/dist/src/control-plane/native/workspace-ops.js +12 -6
  19. package/dist/src/control-plane/runtime/index.js +38 -9
  20. package/dist/src/control-plane/runtime/isolation/home.js +31 -6
  21. package/dist/src/control-plane/runtime/isolation/index.js +38 -9
  22. package/dist/src/control-plane/runtime/isolation/runner.js +31 -6
  23. package/dist/src/control-plane/runtime/isolation/shared.js +9 -6
  24. package/dist/src/control-plane/runtime/isolation.js +38 -9
  25. package/dist/src/control-plane/runtime/queue.js +38 -9
  26. package/dist/src/control-plane/tasks/source-aware-task-config-source.js +14 -2
  27. package/dist/src/control-plane/tasks/source-lifecycle.js +2 -2
  28. package/dist/src/index.js +27 -20
  29. package/dist/src/layout.js +12 -7
  30. package/dist/src/local-server.js +20 -14
  31. package/native/darwin-arm64/{bin/rig-git → rig-git} +0 -0
  32. package/native/darwin-arm64/rig-git.build-manifest.json +4 -0
  33. package/native/darwin-arm64/{bin/rig-shell → rig-shell} +0 -0
  34. package/native/darwin-arm64/rig-shell.build-manifest.json +4 -0
  35. package/native/darwin-arm64/{bin/rig-tools → rig-tools} +0 -0
  36. package/native/darwin-arm64/rig-tools.build-manifest.json +4 -0
  37. package/native/darwin-arm64/{lib/runtime-native.dylib → runtime-native.dylib} +0 -0
  38. package/package.json +6 -6
  39. package/native/darwin-arm64/lib/runtime-native-darwin-arm64.dylib +0 -0
  40. package/native/darwin-arm64/manifest.json +0 -1
  41. package/native/linux-x64/bin/rig-git +0 -0
  42. package/native/linux-x64/bin/rig-shell +0 -0
  43. package/native/linux-x64/bin/rig-tools +0 -0
  44. package/native/linux-x64/lib/runtime-native-linux-x64.so +0 -0
  45. package/native/linux-x64/lib/runtime-native.so +0 -0
  46. package/native/linux-x64/manifest.json +0 -1
@@ -2951,34 +2951,6 @@ async function readSourceAwareTaskStatus(projectRoot, taskId, options = {}) {
2951
2951
  return null;
2952
2952
  }
2953
2953
  }
2954
- function updateSourceAwareTaskConfigTask(projectRoot, taskId, update, options = {}) {
2955
- const configPath = options.configPath ?? resolve13(projectRoot, ".rig", "task-config.json");
2956
- const rawEntry = readRawTaskEntry(configPath, taskId);
2957
- if (!rawEntry) {
2958
- const configuredFilesPath = readConfiguredFilesTaskSourcePath(projectRoot);
2959
- return configuredFilesPath ? updateFileBackedTask(projectRoot, configuredFilesPath, taskId, update) : false;
2960
- }
2961
- const metadata = readMaterializedTaskMetadata(rawEntry);
2962
- const source = metadata.taskSource;
2963
- if (source?.kind === "github-issues") {
2964
- applyGithubIssueUpdate(options.ghBinary ?? "gh", options.spawn ?? spawnSync, taskId, metadata, update);
2965
- return true;
2966
- }
2967
- if (source?.kind === "files" && source.path) {
2968
- return updateFileBackedTask(projectRoot, source.path, taskId, update);
2969
- }
2970
- if (source?.kind && source.kind !== "files" && source.kind !== "legacy-task-config") {
2971
- return false;
2972
- }
2973
- if (!source && options.allowLocalTaskConfigStatusFallback === false) {
2974
- return false;
2975
- }
2976
- if (typeof update.status !== "string" || update.status.trim().length === 0) {
2977
- return false;
2978
- }
2979
- writeLegacyTaskStatus(configPath, taskId, update.status);
2980
- return true;
2981
- }
2982
2954
  function readMaterializedTaskMetadata(entry) {
2983
2955
  const rawRig = entry._rig;
2984
2956
  if (!isPlainRecord2(rawRig)) {
@@ -3052,46 +3024,6 @@ function stripLegacyTaskConfigMetadata2(raw) {
3052
3024
  const { validation_descriptions: _legacyDescriptions, _meta, ...tasks } = raw;
3053
3025
  return tasks;
3054
3026
  }
3055
- function writeLegacyTaskStatus(configPath, taskId, status) {
3056
- const rawConfig = readRawTaskConfig(configPath);
3057
- if (!rawConfig) {
3058
- return;
3059
- }
3060
- const entry = rawConfig[taskId];
3061
- if (!isPlainRecord2(entry)) {
3062
- return;
3063
- }
3064
- entry.status = status;
3065
- writeFileSync5(configPath, `${JSON.stringify(rawConfig, null, 2)}
3066
- `, "utf8");
3067
- }
3068
- function updateFileBackedTask(projectRoot, sourcePath, taskId, update) {
3069
- const directory = resolve13(projectRoot, sourcePath);
3070
- const file = findFileBackedTaskFile(directory, taskId);
3071
- if (!file) {
3072
- return false;
3073
- }
3074
- const raw = JSON.parse(readFileSync6(file, "utf8"));
3075
- if (!isPlainRecord2(raw)) {
3076
- return false;
3077
- }
3078
- if (update.status)
3079
- raw.status = update.status;
3080
- if (update.title !== undefined)
3081
- raw.title = update.title;
3082
- if (update.body !== undefined)
3083
- raw.body = update.body;
3084
- if (update.comment?.trim()) {
3085
- const existing = Array.isArray(raw.comments) ? raw.comments : [];
3086
- raw.comments = [
3087
- ...existing,
3088
- { body: update.comment, createdAt: new Date().toISOString(), source: "rig" }
3089
- ];
3090
- }
3091
- writeFileSync5(file, `${JSON.stringify(raw, null, 2)}
3092
- `, "utf8");
3093
- return true;
3094
- }
3095
3027
  function listFileBackedTasks(projectRoot, sourcePath) {
3096
3028
  const directory = resolve13(projectRoot, sourcePath);
3097
3029
  if (!existsSync13(directory)) {
@@ -3159,26 +3091,6 @@ function readGithubIssueTask(bin, spawnFn, id, metadata, rawEntry) {
3159
3091
  ], spawnFn);
3160
3092
  return githubIssueToTask(issue, source, rawEntry);
3161
3093
  }
3162
- function applyGithubIssueUpdate(bin, spawnFn, id, metadata, update) {
3163
- const source = requireGithubIssueSource(metadata, id);
3164
- const repo = `${source.owner}/${source.repo}`;
3165
- if (update.status) {
3166
- applyGithubIssueStatus(bin, repo, spawnFn, id, update.status);
3167
- }
3168
- if (typeof update.comment === "string" && update.comment.trim().length > 0) {
3169
- runGhVoid(bin, ["issue", "comment", String(id), "--repo", repo, "--body", update.comment], spawnFn);
3170
- }
3171
- const editArgs = ["issue", "edit", String(id), "--repo", repo];
3172
- if (typeof update.title === "string" && update.title.trim().length > 0) {
3173
- editArgs.push("--title", update.title.trim());
3174
- }
3175
- if (typeof update.body === "string") {
3176
- editArgs.push("--body", update.body);
3177
- }
3178
- if (editArgs.length > 5) {
3179
- runGhVoid(bin, editArgs, spawnFn);
3180
- }
3181
- }
3182
3094
  function requireGithubIssueSource(metadata, id) {
3183
3095
  const source = metadata.taskSource;
3184
3096
  if (source?.kind === "github-issues" && source.owner && source.repo) {
@@ -3238,76 +3150,9 @@ function githubStatusFor(issue) {
3238
3150
  return "cancelled";
3239
3151
  return "open";
3240
3152
  }
3241
- function applyGithubIssueStatus(bin, repo, spawnFn, id, status) {
3242
- if (status === "closed") {
3243
- runGhVoid(bin, ["issue", "close", String(id), "--repo", repo], spawnFn);
3244
- return;
3245
- }
3246
- const targetLabel = statusLabelFor(status);
3247
- for (const label of STATUS_LABELS) {
3248
- if (targetLabel !== null && label === targetLabel) {
3249
- continue;
3250
- }
3251
- try {
3252
- runGhVoid(bin, ["issue", "edit", String(id), "--repo", repo, "--remove-label", label], spawnFn);
3253
- } catch {}
3254
- }
3255
- if (targetLabel !== null) {
3256
- try {
3257
- runGhVoid(bin, ["issue", "edit", String(id), "--repo", repo, "--add-label", targetLabel], spawnFn);
3258
- } catch (error) {
3259
- const message = error instanceof Error ? error.message : String(error);
3260
- if (!/not found/i.test(message)) {
3261
- throw error;
3262
- }
3263
- ensureStatusLabel(bin, repo, spawnFn, targetLabel);
3264
- runGhVoid(bin, ["issue", "edit", String(id), "--repo", repo, "--add-label", targetLabel], spawnFn);
3265
- }
3266
- }
3267
- }
3268
- function statusLabelFor(status) {
3269
- switch (status) {
3270
- case "in_progress":
3271
- return "in-progress";
3272
- case "blocked":
3273
- return "blocked";
3274
- case "ready":
3275
- return "ready";
3276
- case "under_review":
3277
- return "under-review";
3278
- case "failed":
3279
- return "failed";
3280
- case "cancelled":
3281
- return "cancelled";
3282
- case "open":
3283
- return null;
3284
- default:
3285
- throw new Error(`unsupported status: ${status}`);
3286
- }
3287
- }
3288
- function ensureStatusLabel(bin, repo, spawnFn, label) {
3289
- try {
3290
- runGhVoid(bin, [
3291
- "label",
3292
- "create",
3293
- label,
3294
- "--repo",
3295
- repo,
3296
- "--color",
3297
- "6f42c1",
3298
- "--description",
3299
- "Task status managed by Rig"
3300
- ], spawnFn);
3301
- } catch (error) {
3302
- const message = error instanceof Error ? error.message : String(error);
3303
- if (!/already exists/i.test(message)) {
3304
- throw error;
3305
- }
3306
- }
3307
- }
3308
3153
  function selectedGitHubEnv() {
3309
- const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() ?? "";
3310
- return { GH_TOKEN: token, GITHUB_TOKEN: token };
3154
+ const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
3155
+ return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
3311
3156
  }
3312
3157
  function ghSpawnOptions() {
3313
3158
  return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
@@ -3320,10 +3165,6 @@ function runGh(bin, args, spawnFn) {
3320
3165
  }
3321
3166
  return JSON.parse(res.stdout);
3322
3167
  }
3323
- function runGhVoid(bin, args, spawnFn) {
3324
- const res = spawnFn(bin, [...args], ghSpawnOptions());
3325
- assertGhSuccess(args, res);
3326
- }
3327
3168
  function assertGhSuccess(args, res) {
3328
3169
  if (res.error) {
3329
3170
  const msg = res.error.message ?? String(res.error);
@@ -3361,19 +3202,6 @@ function isPlainRecord2(candidate) {
3361
3202
  function hasRunnableTaskSource(source) {
3362
3203
  return Boolean(source && typeof source === "object" && !Array.isArray(source));
3363
3204
  }
3364
- function cleanString(value) {
3365
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
3366
- }
3367
- function taskIdFromSourceIssueId(value) {
3368
- const raw = cleanString(value);
3369
- if (!raw)
3370
- return null;
3371
- const issueNumber = raw.match(/#([^#\s]+)$/)?.[1];
3372
- return issueNumber ?? raw;
3373
- }
3374
- function resolveSourceTaskId(taskId, sourceTask) {
3375
- return cleanString(sourceTask?.id) ?? taskIdFromSourceIssueId(sourceTask?.sourceIssueId) ?? taskIdFromSourceIssueId(sourceTask?.source_issue_id) ?? taskId;
3376
- }
3377
3205
  async function getPluginTask(projectRoot, taskId) {
3378
3206
  const ctx = await buildPluginHostContext(projectRoot);
3379
3207
  const [source] = ctx?.taskSourceRegistry.list() ?? [];
@@ -3398,91 +3226,6 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
3398
3226
  task
3399
3227
  };
3400
3228
  }
3401
- async function updatePluginTaskSourceTask(projectRoot, taskId, update) {
3402
- const ctx = await buildPluginHostContext(projectRoot);
3403
- const [source] = ctx?.taskSourceRegistry.list() ?? [];
3404
- if (!hasRunnableTaskSource(source)) {
3405
- return ctx ? { taskId, updated: false, source: "none", sourceKind: null, status: null } : null;
3406
- }
3407
- if (source.updateTask) {
3408
- await source.updateTask(taskId, update);
3409
- } else if (update.status && source.updateStatus) {
3410
- await source.updateStatus(taskId, update.status);
3411
- } else {
3412
- return {
3413
- taskId,
3414
- updated: false,
3415
- source: "plugin",
3416
- sourceKind: source.kind,
3417
- status: null
3418
- };
3419
- }
3420
- const status = source.get ? (await source.get(taskId))?.status ?? update.status ?? null : update.status ?? null;
3421
- return {
3422
- taskId,
3423
- updated: true,
3424
- source: "plugin",
3425
- sourceKind: source.kind,
3426
- status
3427
- };
3428
- }
3429
- async function updateConfiguredTaskSourceTask(projectRoot, input) {
3430
- const taskId = resolveSourceTaskId(input.taskId, input.sourceTask);
3431
- let pluginResult = null;
3432
- try {
3433
- pluginResult = await updatePluginTaskSourceTask(projectRoot, taskId, input.update);
3434
- } catch (error) {
3435
- const fallbackUpdated = updateSourceAwareTaskConfigTask(projectRoot, taskId, input.update, {
3436
- allowLocalTaskConfigStatusFallback: false
3437
- });
3438
- if (!fallbackUpdated) {
3439
- throw error;
3440
- }
3441
- return {
3442
- taskId,
3443
- updated: true,
3444
- source: "compat",
3445
- sourceKind: null,
3446
- status: await readSourceAwareTaskStatus(projectRoot, taskId)
3447
- };
3448
- }
3449
- if (pluginResult) {
3450
- return pluginResult;
3451
- }
3452
- const updated = updateSourceAwareTaskConfigTask(projectRoot, taskId, input.update);
3453
- return {
3454
- taskId,
3455
- updated,
3456
- source: updated ? "compat" : "none",
3457
- sourceKind: null,
3458
- status: await readSourceAwareTaskStatus(projectRoot, taskId)
3459
- };
3460
- }
3461
- function buildTaskRunLifecycleComment(input) {
3462
- const lines = [
3463
- "<!-- rig:status-comment -->",
3464
- `### Rig status: ${input.status}`,
3465
- "",
3466
- input.summary,
3467
- "",
3468
- `- Run: ${input.runId}`,
3469
- `- Status: ${input.status}`
3470
- ];
3471
- if (input.errorText?.trim()) {
3472
- lines.push(`- Error: ${input.errorText.trim()}`);
3473
- }
3474
- if (input.runtimeWorkspace?.trim()) {
3475
- lines.push(`- Runtime workspace: ${input.runtimeWorkspace.trim()}`);
3476
- }
3477
- if (input.logsDir?.trim()) {
3478
- lines.push(`- Logs: ${input.logsDir.trim()}`);
3479
- }
3480
- if (input.sessionDir?.trim()) {
3481
- lines.push(`- Session: ${input.sessionDir.trim()}`);
3482
- }
3483
- return lines.join(`
3484
- `);
3485
- }
3486
3229
 
3487
3230
  // packages/runtime/src/control-plane/native/task-state.ts
3488
3231
  import { existsSync as existsSync17, readFileSync as readFileSync8, readdirSync as readdirSync2, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
@@ -5710,20 +5453,23 @@ function hashProjectPath(workspaceDir) {
5710
5453
  }
5711
5454
  function resolveGithubCliBinaryPath() {
5712
5455
  const explicit = process.env.RIG_GH_BIN?.trim();
5713
- if (explicit && existsSync23(explicit)) {
5456
+ if (explicit && existsSync23(explicit) && !isRuntimeGatewayGhPath(explicit)) {
5714
5457
  return explicit;
5715
5458
  }
5716
- const bunResolved = Bun.which("gh");
5717
- if (bunResolved && existsSync23(bunResolved)) {
5718
- return bunResolved;
5719
- }
5720
- for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
5459
+ for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
5721
5460
  if (existsSync23(candidate)) {
5722
5461
  return candidate;
5723
5462
  }
5724
5463
  }
5464
+ const bunResolved = Bun.which("gh");
5465
+ if (bunResolved && existsSync23(bunResolved) && !isRuntimeGatewayGhPath(bunResolved)) {
5466
+ return bunResolved;
5467
+ }
5725
5468
  return "";
5726
5469
  }
5470
+ function isRuntimeGatewayGhPath(candidate) {
5471
+ return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
5472
+ }
5727
5473
  async function resolveGithubCliAuthToken(ghBinary = "") {
5728
5474
  const gh = ghBinary || resolveGithubCliBinaryPath();
5729
5475
  if (!gh) {
@@ -5824,6 +5570,8 @@ async function runtimeEnv(projectRoot, runtime) {
5824
5570
  XDG_CACHE_HOME: runtime.cacheDir,
5825
5571
  XDG_STATE_HOME: runtime.stateDir,
5826
5572
  RIG_AGENT_ID: runtime.id,
5573
+ ...process.env.RIG_RUN_ID?.trim() ? { RIG_RUN_ID: process.env.RIG_RUN_ID.trim() } : {},
5574
+ ...process.env.RIG_SERVER_RUN_ID?.trim() ? { RIG_SERVER_RUN_ID: process.env.RIG_SERVER_RUN_ID.trim() } : {},
5827
5575
  RIG_TASK_ID: runtime.taskId,
5828
5576
  RIG_TASK_RUNTIME_ID: runtime.id,
5829
5577
  RIG_TASK_WORKSPACE: runtime.workspaceDir,
@@ -5887,6 +5635,10 @@ async function runtimeEnv(projectRoot, runtime) {
5887
5635
  env[key] = value;
5888
5636
  }
5889
5637
  }
5638
+ const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
5639
+ if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
5640
+ env.GITHUB_TOKEN = rigGithubToken;
5641
+ }
5890
5642
  const fallbackGithubToken = !env.GITHUB_TOKEN && !env.GH_TOKEN ? await resolveGithubCliAuthToken(hostGhBinary) : "";
5891
5643
  if (fallbackGithubToken) {
5892
5644
  env.GITHUB_TOKEN = fallbackGithubToken;
@@ -5897,6 +5649,13 @@ async function runtimeEnv(projectRoot, runtime) {
5897
5649
  if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
5898
5650
  env.GH_TOKEN = env.GITHUB_TOKEN;
5899
5651
  }
5652
+ const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || rigGithubToken;
5653
+ if (gitHubToken) {
5654
+ env.RIG_GITHUB_TOKEN = gitHubToken;
5655
+ env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
5656
+ env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
5657
+ applyGitHubCredentialHelperEnv(env);
5658
+ }
5900
5659
  if (!env.GREPTILE_GITHUB_TOKEN && env.GITHUB_TOKEN) {
5901
5660
  env.GREPTILE_GITHUB_TOKEN = env.GITHUB_TOKEN;
5902
5661
  }
@@ -5977,12 +5736,21 @@ async function materializeRuntimeCertBundle(runtime) {
5977
5736
  }
5978
5737
  return targetPath;
5979
5738
  }
5739
+ function applyGitHubCredentialHelperEnv(env) {
5740
+ env.GIT_TERMINAL_PROMPT = "0";
5741
+ env.GIT_CONFIG_COUNT = "2";
5742
+ env.GIT_CONFIG_KEY_0 = "credential.helper";
5743
+ env.GIT_CONFIG_VALUE_0 = "";
5744
+ env.GIT_CONFIG_KEY_1 = "credential.helper";
5745
+ env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
5746
+ }
5980
5747
  function persistRuntimeSecrets(runtimeRoot, env) {
5981
5748
  const secretsPath = resolve25(runtimeRoot, "runtime-secrets.json");
5982
5749
  const persisted = {};
5983
5750
  for (const key of [
5984
5751
  "GITHUB_TOKEN",
5985
5752
  "GH_TOKEN",
5753
+ "RIG_GITHUB_TOKEN",
5986
5754
  "GREPTILE_GITHUB_TOKEN",
5987
5755
  "GREPTILE_API_KEY",
5988
5756
  "AI_REVIEW_MODE",
@@ -8461,7 +8229,11 @@ async function ensureAgentRuntime(options) {
8461
8229
  mkdirSync18(runtime.binDir, { recursive: true });
8462
8230
  mkdirSync18(workspaceLayout.distDir, { recursive: true });
8463
8231
  prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
8464
- await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
8232
+ if (options.preserveTaskArtifacts) {
8233
+ console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
8234
+ } else {
8235
+ await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
8236
+ }
8465
8237
  const ctx = {
8466
8238
  runtimeId: options.id,
8467
8239
  taskId: options.taskId,
@@ -9173,7 +8945,8 @@ async function runAgentWrapper(options = {}) {
9173
8945
  taskId,
9174
8946
  mode: "worktree",
9175
8947
  provider,
9176
- taskRecordReader: taskRecordReaderFromEnv(taskId)
8948
+ taskRecordReader: taskRecordReaderFromEnv(taskId),
8949
+ preserveTaskArtifacts: process.env.RIG_RUN_RESUME === "1" || process.env.RIG_RUNTIME_ARTIFACT_CLEANUP === "preserve"
9177
8950
  });
9178
8951
  emitWrapperEvent("runtime.provision.completed", {
9179
8952
  runtimeId: runtime.id,
@@ -9278,15 +9051,13 @@ async function runAgentWrapper(options = {}) {
9278
9051
  throw error;
9279
9052
  }
9280
9053
  const serverManagedRun = Boolean(process.env.RIG_SERVER_RUN_ID?.trim());
9281
- if (exitCode === 0 && serverManagedRun) {
9282
- await updateTaskSourceAfterRun(monorepoRoot, taskId, runtime);
9283
- }
9284
9054
  const taskClosed = await isTaskClosed(monorepoRoot, taskId);
9285
9055
  const finalExitCode = resolveFinalProviderExitCode({
9286
9056
  providerExitCode: exitCode,
9287
9057
  taskClosed,
9288
9058
  serverManagedRun
9289
9059
  });
9060
+ const handoffRequired = exitCode !== 0 || !taskClosed && !serverManagedRun;
9290
9061
  emitWrapperEvent("provider.completed", {
9291
9062
  provider,
9292
9063
  runtimeId: runtime.id,
@@ -9295,24 +9066,21 @@ async function runAgentWrapper(options = {}) {
9295
9066
  providerExitCode: exitCode,
9296
9067
  taskClosed,
9297
9068
  serverManagedRun,
9298
- handoffRequired: exitCode !== 0 || !taskClosed
9069
+ handoffRequired
9299
9070
  });
9300
- if (exitCode !== 0 || !taskClosed) {
9071
+ if (handoffRequired) {
9301
9072
  recordRuntimeHandoff(projectRoot, runtime, taskId, exitCode);
9302
9073
  }
9303
- if (exitCode === 0 && !taskClosed && serverManagedRun) {
9304
- console.error(`[rig-agent] Server-managed task run cannot finish successfully while ${taskId} is still open.`);
9305
- }
9306
9074
  return finalExitCode;
9307
9075
  }
9308
9076
  function resolveFinalProviderExitCode(input) {
9309
9077
  if (input.providerExitCode !== 0) {
9310
9078
  return input.providerExitCode;
9311
9079
  }
9312
- if (input.taskClosed) {
9080
+ if (input.taskClosed || input.serverManagedRun) {
9313
9081
  return 0;
9314
9082
  }
9315
- return input.serverManagedRun ? 2 : 0;
9083
+ return 0;
9316
9084
  }
9317
9085
  function shouldBypassProviderSandboxOnPlatform(provider, platform) {
9318
9086
  if (platform !== "darwin") {
@@ -9336,12 +9104,16 @@ function buildProviderArgs(provider, runtime, argv) {
9336
9104
  }
9337
9105
  if (provider === "pi") {
9338
9106
  const piArgs = [...argv];
9107
+ const piProvider = cliOptionValue(piArgs, "--provider") || process.env.RIG_PI_PROVIDER?.trim() || "openai-codex";
9339
9108
  if (!hasCliOption(piArgs, "--provider")) {
9340
- piArgs.unshift(process.env.RIG_PI_PROVIDER?.trim() || "openai-codex");
9109
+ piArgs.unshift(piProvider);
9341
9110
  piArgs.unshift("--provider");
9342
9111
  }
9343
- if (!hasCliOption(piArgs, "--model")) {
9344
- piArgs.unshift(process.env.RIG_PI_MODEL?.trim() || "gpt-5.5");
9112
+ const model = cliOptionValue(piArgs, "--model") || process.env.RIG_PI_MODEL?.trim() || "gpt-5.5";
9113
+ if (hasCliOption(piArgs, "--model")) {
9114
+ rewriteCliOptionValue(piArgs, "--model", normalizePiModelForProvider(model, piProvider));
9115
+ } else {
9116
+ piArgs.unshift(normalizePiModelForProvider(model, piProvider));
9345
9117
  piArgs.unshift("--model");
9346
9118
  }
9347
9119
  return piArgs;
@@ -9409,6 +9181,38 @@ function resolveProvider() {
9409
9181
  function hasCliOption(argv, option) {
9410
9182
  return argv.some((arg) => arg === option || arg.startsWith(`${option}=`));
9411
9183
  }
9184
+ function cliOptionValue(argv, option) {
9185
+ for (let index = 0;index < argv.length; index += 1) {
9186
+ const arg = argv[index];
9187
+ if (arg === option) {
9188
+ const next = argv[index + 1];
9189
+ return next && !next.startsWith("--") ? next : undefined;
9190
+ }
9191
+ if (arg?.startsWith(`${option}=`)) {
9192
+ return arg.slice(option.length + 1);
9193
+ }
9194
+ }
9195
+ return;
9196
+ }
9197
+ function rewriteCliOptionValue(argv, option, value) {
9198
+ for (let index = 0;index < argv.length; index += 1) {
9199
+ const arg = argv[index];
9200
+ if (arg === option && argv[index + 1] && !argv[index + 1].startsWith("--")) {
9201
+ argv[index + 1] = value;
9202
+ return;
9203
+ }
9204
+ if (arg?.startsWith(`${option}=`)) {
9205
+ argv[index] = `${option}=${value}`;
9206
+ return;
9207
+ }
9208
+ }
9209
+ }
9210
+ function normalizePiModelForProvider(model, provider) {
9211
+ if (provider === "openrouter" && model === "openai-codex/gpt-5.5") {
9212
+ return "openai/gpt-5.5";
9213
+ }
9214
+ return model;
9215
+ }
9412
9216
  function providerBinary(provider) {
9413
9217
  if (provider === "codex") {
9414
9218
  return Bun.which("codex") || "codex";
@@ -9507,39 +9311,6 @@ async function readPluginTaskStatus(projectRoot, taskId) {
9507
9311
  return readSourceAwareTaskStatus(projectRoot, taskId);
9508
9312
  }
9509
9313
  }
9510
- async function updateTaskSourceAfterRun(projectRoot, taskId, runtime) {
9511
- const comment = buildTaskRunLifecycleComment({
9512
- runId: process.env.RIG_SERVER_RUN_ID || "(unknown)",
9513
- status: "closed",
9514
- summary: "Rig task run completed and closed this task.",
9515
- runtimeWorkspace: runtime.workspaceDir,
9516
- logsDir: runtime.logsDir,
9517
- sessionDir: runtime.sessionDir
9518
- });
9519
- try {
9520
- const result = await updateConfiguredTaskSourceTask(projectRoot, {
9521
- taskId,
9522
- update: { status: "closed", comment }
9523
- });
9524
- if (result.updated) {
9525
- return;
9526
- }
9527
- throw new Error(result.source === "plugin" || result.sourceKind ? `configured task source${result.sourceKind ? ` (${result.sourceKind})` : ""} does not support lifecycle updates` : "no source-aware task source is configured");
9528
- } catch (error) {
9529
- let fallbackUpdated = false;
9530
- try {
9531
- fallbackUpdated = updateSourceAwareTaskConfigTask(projectRoot, taskId, { status: "closed", comment });
9532
- } catch (fallbackError) {
9533
- console.error(`[rig-agent] Source-aware compatibility update also failed for ${taskId}: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`);
9534
- }
9535
- const message = `[rig-agent] Failed to update task source for ${taskId}${fallbackUpdated ? "; applied source-aware compatibility update" : ""}: ${error instanceof Error ? error.message : String(error)}`;
9536
- if (fallbackUpdated) {
9537
- console.log(message);
9538
- } else {
9539
- console.error(message);
9540
- }
9541
- }
9542
- }
9543
9314
  function recordRuntimeHandoff(hostProjectRoot, runtime, taskId, exitCode) {
9544
9315
  const handoffDir = resolve35(hostProjectRoot, ".rig/runtime/handoffs");
9545
9316
  mkdirSync19(handoffDir, { recursive: true });