@h-rig/cli 0.0.6-alpha.34 → 0.0.6-alpha.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -337,9 +337,9 @@ var init_plugin = __esm(() => {
337
337
  // packages/cli/src/commands.ts
338
338
  init_runner();
339
339
  import {
340
- existsSync as existsSync14
340
+ existsSync as existsSync15
341
341
  } from "fs";
342
- import { resolve as resolve23 } from "path";
342
+ import { resolve as resolve24 } from "path";
343
343
  import { readBuildConfig } from "@rig/runtime/build-time-config";
344
344
 
345
345
  // packages/cli/src/commands/browser.ts
@@ -2450,6 +2450,157 @@ async function executeHarness(context, args) {
2450
2450
  // packages/cli/src/commands.ts
2451
2451
  init_plugin();
2452
2452
 
2453
+ // packages/cli/src/commands/pi.ts
2454
+ init_runner();
2455
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
2456
+ import { homedir as homedir2 } from "os";
2457
+ import { dirname, resolve as resolve8 } from "path";
2458
+ function settingsPath(root) {
2459
+ return resolve8(root, ".pi", "settings.json");
2460
+ }
2461
+ function userSettingsPath() {
2462
+ return resolve8(homedir2(), ".pi", "agent", "settings.json");
2463
+ }
2464
+ function readJson(path, fallback) {
2465
+ if (!existsSync4(path))
2466
+ return fallback;
2467
+ try {
2468
+ return JSON.parse(readFileSync2(path, "utf-8"));
2469
+ } catch {
2470
+ return fallback;
2471
+ }
2472
+ }
2473
+ function packageKey(entry) {
2474
+ if (typeof entry === "string")
2475
+ return entry;
2476
+ if (entry && typeof entry === "object" && typeof entry.source === "string") {
2477
+ return entry.source;
2478
+ }
2479
+ return JSON.stringify(entry);
2480
+ }
2481
+ function writeSettings(path, settings) {
2482
+ mkdirSync4(dirname(path), { recursive: true });
2483
+ writeFileSync3(path, `${JSON.stringify(settings, null, 2)}
2484
+ `, "utf-8");
2485
+ }
2486
+ async function searchNpmForPiExtensions(term) {
2487
+ const query = encodeURIComponent(term ? `${term} pi extension` : "pi extension");
2488
+ const url = `https://registry.npmjs.org/-/v1/search?text=${query}&size=20`;
2489
+ const response = await fetch(url);
2490
+ if (!response.ok) {
2491
+ throw new CliError2(`npm registry search failed (${response.status}).`, 2);
2492
+ }
2493
+ const payload = await response.json();
2494
+ const results = [];
2495
+ for (const entry of payload.objects ?? []) {
2496
+ const pkg = entry.package;
2497
+ if (!pkg?.name)
2498
+ continue;
2499
+ const keywords = (pkg.keywords ?? []).map((k) => k.toLowerCase());
2500
+ const piLike = pkg.name.startsWith("pi-") || pkg.name.includes("-pi") || keywords.includes("pi") || keywords.includes("pi-extension") || (pkg.description ?? "").toLowerCase().includes("pi extension") || (pkg.description ?? "").toLowerCase().includes("pi coding agent");
2501
+ if (!piLike)
2502
+ continue;
2503
+ results.push({ name: pkg.name, version: pkg.version ?? "", description: pkg.description ?? "" });
2504
+ }
2505
+ return results;
2506
+ }
2507
+ async function executePi(context, args) {
2508
+ const [command = "list", ...rest] = args;
2509
+ const projectSettingsPath = settingsPath(context.projectRoot);
2510
+ const managedRecordPath = resolve8(context.projectRoot, ".rig", "state", "pi-managed-packages.json");
2511
+ switch (command) {
2512
+ case "list": {
2513
+ requireNoExtraArgs(rest, "rig pi list");
2514
+ const project = readJson(projectSettingsPath, {});
2515
+ const managed = new Set(readJson(managedRecordPath, []));
2516
+ const user = readJson(userSettingsPath(), {});
2517
+ const projectPackages = (Array.isArray(project.packages) ? project.packages : []).map((entry) => ({
2518
+ source: packageKey(entry),
2519
+ managedByRigConfig: managed.has(packageKey(entry))
2520
+ }));
2521
+ const userPackages = (Array.isArray(user.packages) ? user.packages : []).map(packageKey);
2522
+ if (context.outputMode === "text") {
2523
+ console.log("Project Pi packages (.pi/settings.json):");
2524
+ if (projectPackages.length === 0)
2525
+ console.log(" (none)");
2526
+ for (const pkg of projectPackages) {
2527
+ console.log(` ${pkg.source}${pkg.managedByRigConfig ? " [from rig.config runtime.pi.packages]" : ""}`);
2528
+ }
2529
+ console.log("User Pi packages (~/.pi/agent/settings.json):");
2530
+ if (userPackages.length === 0)
2531
+ console.log(" (none)");
2532
+ for (const pkg of userPackages)
2533
+ console.log(` ${pkg}`);
2534
+ console.log("Add more: `rig pi add <npm-package>` \xB7 discover: `rig pi search <term>`");
2535
+ }
2536
+ return { ok: true, group: "pi", command, details: { projectPackages, userPackages } };
2537
+ }
2538
+ case "add": {
2539
+ const [source, ...extra] = rest;
2540
+ requireNoExtraArgs(extra, "rig pi add <package-source>");
2541
+ if (!source) {
2542
+ throw new CliError2("Usage: rig pi add <package-source> (npm name, name@version, or git URL)", 2);
2543
+ }
2544
+ const settings = readJson(projectSettingsPath, {});
2545
+ const packages = Array.isArray(settings.packages) ? settings.packages : [];
2546
+ if (packages.some((entry) => packageKey(entry) === source)) {
2547
+ throw new CliError2(`"${source}" is already in ${projectSettingsPath}.`, 2);
2548
+ }
2549
+ writeSettings(projectSettingsPath, { ...settings, packages: [...packages, source] });
2550
+ if (context.outputMode === "text") {
2551
+ console.log(`Added ${source} to ${projectSettingsPath}.`);
2552
+ console.log("Pi installs missing packages automatically at the next session start (local and worker).");
2553
+ }
2554
+ return { ok: true, group: "pi", command, details: { source, settingsPath: projectSettingsPath } };
2555
+ }
2556
+ case "remove": {
2557
+ const [source, ...extra] = rest;
2558
+ requireNoExtraArgs(extra, "rig pi remove <package-source>");
2559
+ if (!source) {
2560
+ throw new CliError2("Usage: rig pi remove <package-source>", 2);
2561
+ }
2562
+ const managed = new Set(readJson(managedRecordPath, []));
2563
+ if (managed.has(source)) {
2564
+ throw new CliError2(`"${source}" is managed by rig.config.ts (runtime.pi.packages); remove it there instead.`, 2);
2565
+ }
2566
+ const settings = readJson(projectSettingsPath, {});
2567
+ const packages = Array.isArray(settings.packages) ? settings.packages : [];
2568
+ const next = packages.filter((entry) => packageKey(entry) !== source);
2569
+ if (next.length === packages.length) {
2570
+ throw new CliError2(`"${source}" is not in ${projectSettingsPath}.`, 2);
2571
+ }
2572
+ const nextSettings = { ...settings };
2573
+ if (next.length > 0)
2574
+ nextSettings.packages = next;
2575
+ else
2576
+ delete nextSettings.packages;
2577
+ writeSettings(projectSettingsPath, nextSettings);
2578
+ if (context.outputMode === "text") {
2579
+ console.log(`Removed ${source} from ${projectSettingsPath}.`);
2580
+ }
2581
+ return { ok: true, group: "pi", command, details: { source } };
2582
+ }
2583
+ case "search": {
2584
+ const term = rest.join(" ").trim();
2585
+ const results = await searchNpmForPiExtensions(term);
2586
+ if (context.outputMode === "text") {
2587
+ if (results.length === 0) {
2588
+ console.log(`No Pi extension packages found on npm${term ? ` for "${term}"` : ""}.`);
2589
+ } else {
2590
+ console.log(`Pi extension packages on npm${term ? ` matching "${term}"` : ""}:`);
2591
+ for (const pkg of results) {
2592
+ console.log(` ${pkg.name}@${pkg.version} ${pkg.description.slice(0, 80)}`);
2593
+ }
2594
+ console.log("Install one: `rig pi add <name>`");
2595
+ }
2596
+ }
2597
+ return { ok: true, group: "pi", command, details: { term, results } };
2598
+ }
2599
+ default:
2600
+ throw new CliError2(`Unknown pi command: ${command}. Use list|add|remove|search.`);
2601
+ }
2602
+ }
2603
+
2453
2604
  // packages/cli/src/commands/queue.ts
2454
2605
  init_runner();
2455
2606
  init__parsers();
@@ -2461,33 +2612,33 @@ import { ensureProjectMainFreshBeforeRun } from "@rig/runtime/control-plane/proj
2461
2612
 
2462
2613
  // packages/cli/src/commands/_connection-state.ts
2463
2614
  init_runner();
2464
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
2465
- import { homedir as homedir2 } from "os";
2466
- import { dirname, resolve as resolve8 } from "path";
2615
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
2616
+ import { homedir as homedir3 } from "os";
2617
+ import { dirname as dirname2, resolve as resolve9 } from "path";
2467
2618
  function resolveGlobalConnectionsPath(env = process.env) {
2468
2619
  const explicit = env.RIG_CONNECTIONS_FILE?.trim();
2469
2620
  if (explicit)
2470
- return resolve8(explicit);
2621
+ return resolve9(explicit);
2471
2622
  const stateDir = env.RIG_GLOBAL_STATE_DIR?.trim();
2472
2623
  if (stateDir)
2473
- return resolve8(stateDir, "connections.json");
2474
- return resolve8(homedir2(), ".rig", "connections.json");
2624
+ return resolve9(stateDir, "connections.json");
2625
+ return resolve9(homedir3(), ".rig", "connections.json");
2475
2626
  }
2476
2627
  function resolveRepoConnectionPath(projectRoot) {
2477
- return resolve8(projectRoot, ".rig", "state", "connection.json");
2628
+ return resolve9(projectRoot, ".rig", "state", "connection.json");
2478
2629
  }
2479
2630
  function readJsonFile2(path) {
2480
- if (!existsSync4(path))
2631
+ if (!existsSync5(path))
2481
2632
  return null;
2482
2633
  try {
2483
- return JSON.parse(readFileSync2(path, "utf8"));
2634
+ return JSON.parse(readFileSync3(path, "utf8"));
2484
2635
  } catch (error) {
2485
2636
  throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
2486
2637
  }
2487
2638
  }
2488
2639
  function writeJsonFile2(path, value) {
2489
- mkdirSync4(dirname(path), { recursive: true });
2490
- writeFileSync3(path, `${JSON.stringify(value, null, 2)}
2640
+ mkdirSync5(dirname2(path), { recursive: true });
2641
+ writeFileSync4(path, `${JSON.stringify(value, null, 2)}
2491
2642
  `, "utf8");
2492
2643
  }
2493
2644
  function normalizeConnection(value) {
@@ -2564,8 +2715,8 @@ function resolveSelectedConnection(projectRoot, options = {}) {
2564
2715
 
2565
2716
  // packages/cli/src/commands/_server-client.ts
2566
2717
  init_runner();
2567
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
2568
- import { resolve as resolve9 } from "path";
2718
+ import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
2719
+ import { resolve as resolve10 } from "path";
2569
2720
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
2570
2721
  var scopedGitHubBearerTokens = new Map;
2571
2722
  function cleanToken(value) {
@@ -2573,22 +2724,22 @@ function cleanToken(value) {
2573
2724
  return trimmed ? trimmed : null;
2574
2725
  }
2575
2726
  function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
2576
- const scopedKey = resolve9(projectRoot ?? process.cwd());
2727
+ const scopedKey = resolve10(projectRoot ?? process.cwd());
2577
2728
  scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
2578
2729
  }
2579
2730
  function readPrivateRemoteSessionToken(projectRoot) {
2580
- const path = resolve9(projectRoot, ".rig", "state", "github-auth.json");
2581
- if (!existsSync5(path))
2731
+ const path = resolve10(projectRoot, ".rig", "state", "github-auth.json");
2732
+ if (!existsSync6(path))
2582
2733
  return null;
2583
2734
  try {
2584
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
2735
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
2585
2736
  return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
2586
2737
  } catch {
2587
2738
  return null;
2588
2739
  }
2589
2740
  }
2590
2741
  function readGitHubBearerTokenForRemote(projectRoot) {
2591
- const scopedKey = resolve9(projectRoot);
2742
+ const scopedKey = resolve10(projectRoot);
2592
2743
  if (scopedGitHubBearerTokens.has(scopedKey))
2593
2744
  return scopedGitHubBearerTokens.get(scopedKey) ?? null;
2594
2745
  const privateSession = readPrivateRemoteSessionToken(projectRoot);
@@ -2730,7 +2881,7 @@ async function registerProjectViaServer(context, input) {
2730
2881
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
2731
2882
  }
2732
2883
  function sleep(ms) {
2733
- return new Promise((resolve10) => setTimeout(resolve10, ms));
2884
+ return new Promise((resolve11) => setTimeout(resolve11, ms));
2734
2885
  }
2735
2886
  function isRetryableProjectRootSwitchError(error) {
2736
2887
  if (!(error instanceof Error))
@@ -3213,7 +3364,7 @@ async function executeQueue(context, args) {
3213
3364
 
3214
3365
  // packages/cli/src/commands/agent.ts
3215
3366
  init_runner();
3216
- import { resolve as resolve11 } from "path";
3367
+ import { resolve as resolve12 } from "path";
3217
3368
  import {
3218
3369
  agentId,
3219
3370
  cleanupAgentRuntime,
@@ -3223,8 +3374,8 @@ import {
3223
3374
  } from "@rig/runtime/control-plane/runtime/isolation";
3224
3375
 
3225
3376
  // packages/cli/src/commands/_authority-runs.ts
3226
- import { existsSync as existsSync6 } from "fs";
3227
- import { resolve as resolve10 } from "path";
3377
+ import { existsSync as existsSync7 } from "fs";
3378
+ import { resolve as resolve11 } from "path";
3228
3379
  import {
3229
3380
  readAuthorityRun,
3230
3381
  readJsonlFile as readJsonlFile2,
@@ -3246,8 +3397,8 @@ function normalizeRuntimeAdapter(value) {
3246
3397
  return "claude-code";
3247
3398
  }
3248
3399
  function readLatestBeadRecord(projectRoot, taskId) {
3249
- const issuesPath = resolve10(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
3250
- if (!existsSync6(issuesPath)) {
3400
+ const issuesPath = resolve11(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
3401
+ if (!existsSync7(issuesPath)) {
3251
3402
  return null;
3252
3403
  }
3253
3404
  let latest = null;
@@ -3315,7 +3466,7 @@ function upsertAgentAuthorityRun(projectRoot, input) {
3315
3466
  } else if ("errorText" in next) {
3316
3467
  delete next.errorText;
3317
3468
  }
3318
- writeJsonFile3(resolve10(resolveAuthorityRunDir(projectRoot, input.runId), "run.json"), next);
3469
+ writeJsonFile3(resolve11(resolveAuthorityRunDir(projectRoot, input.runId), "run.json"), next);
3319
3470
  return next;
3320
3471
  }
3321
3472
 
@@ -3437,10 +3588,10 @@ async function executeAgent(context, args) {
3437
3588
  status: "running",
3438
3589
  startedAt: createdAt,
3439
3590
  worktreePath: runtime.workspaceDir,
3440
- artifactRoot: resolve11(runtime.workspaceDir, "artifacts", taskId),
3591
+ artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
3441
3592
  logRoot: runtime.logsDir,
3442
- sessionPath: resolve11(runtime.sessionDir, "session.json"),
3443
- sessionLogPath: resolve11(runtime.logsDir, "agent-stdout.log"),
3593
+ sessionPath: resolve12(runtime.sessionDir, "session.json"),
3594
+ sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
3444
3595
  pid: process.pid
3445
3596
  });
3446
3597
  const result = await runInAgentRuntime({
@@ -3460,10 +3611,10 @@ async function executeAgent(context, args) {
3460
3611
  startedAt: createdAt,
3461
3612
  completedAt: failedAt,
3462
3613
  worktreePath: runtime.workspaceDir,
3463
- artifactRoot: resolve11(runtime.workspaceDir, "artifacts", taskId),
3614
+ artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
3464
3615
  logRoot: runtime.logsDir,
3465
- sessionPath: resolve11(runtime.sessionDir, "session.json"),
3466
- sessionLogPath: resolve11(runtime.logsDir, "agent-stdout.log"),
3616
+ sessionPath: resolve12(runtime.sessionDir, "session.json"),
3617
+ sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
3467
3618
  pid: process.pid,
3468
3619
  errorText: result.stderr ? result.stderr.trim() : `Agent runtime command failed (${result.exitCode})`
3469
3620
  });
@@ -3480,10 +3631,10 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
3480
3631
  startedAt: createdAt,
3481
3632
  completedAt,
3482
3633
  worktreePath: runtime.workspaceDir,
3483
- artifactRoot: resolve11(runtime.workspaceDir, "artifacts", taskId),
3634
+ artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
3484
3635
  logRoot: runtime.logsDir,
3485
- sessionPath: resolve11(runtime.sessionDir, "session.json"),
3486
- sessionLogPath: resolve11(runtime.logsDir, "agent-stdout.log"),
3636
+ sessionPath: resolve12(runtime.sessionDir, "session.json"),
3637
+ sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
3487
3638
  pid: process.pid
3488
3639
  });
3489
3640
  return {
@@ -3559,8 +3710,8 @@ init__parsers();
3559
3710
  import {
3560
3711
  chmodSync,
3561
3712
  copyFileSync as copyFileSync2,
3562
- existsSync as existsSync7,
3563
- mkdirSync as mkdirSync5,
3713
+ existsSync as existsSync8,
3714
+ mkdirSync as mkdirSync6,
3564
3715
  readdirSync,
3565
3716
  readlinkSync,
3566
3717
  rmSync as rmSync3,
@@ -3568,8 +3719,8 @@ import {
3568
3719
  symlinkSync,
3569
3720
  unlinkSync
3570
3721
  } from "fs";
3571
- import { homedir as homedir3 } from "os";
3572
- import { resolve as resolve12 } from "path";
3722
+ import { homedir as homedir4 } from "os";
3723
+ import { resolve as resolve13 } from "path";
3573
3724
  import { buildBinary as buildBinary2 } from "@rig/runtime/control-plane/runtime/isolation";
3574
3725
  import {
3575
3726
  computeRuntimeImageFingerprint,
@@ -3588,13 +3739,13 @@ async function runQuietBinaryProbe(binaryPath, args, cwd) {
3588
3739
 
3589
3740
  // packages/cli/src/commands/dist.ts
3590
3741
  function collectRigValidatorBuildTargets(input) {
3591
- const validatorsRoot = resolve12(input.hostProjectRoot, "packages/runtime/src/control-plane/validators");
3592
- if (!existsSync7(validatorsRoot))
3742
+ const validatorsRoot = resolve13(input.hostProjectRoot, "packages/runtime/src/control-plane/validators");
3743
+ if (!existsSync8(validatorsRoot))
3593
3744
  return [];
3594
3745
  const targets = [];
3595
3746
  const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
3596
3747
  for (const category of categories) {
3597
- const categoryDir = resolve12(validatorsRoot, category.name);
3748
+ const categoryDir = resolve13(validatorsRoot, category.name);
3598
3749
  for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
3599
3750
  if (!entry.isFile() || !entry.name.endsWith(".ts"))
3600
3751
  continue;
@@ -3603,7 +3754,7 @@ function collectRigValidatorBuildTargets(input) {
3603
3754
  continue;
3604
3755
  targets.push({
3605
3756
  source: `packages/runtime/src/control-plane/validators/${category.name}/${entry.name}`,
3606
- dest: resolve12(input.imageDir, `bin/validators/${category.name}-${check}`),
3757
+ dest: resolve13(input.imageDir, `bin/validators/${category.name}-${check}`),
3607
3758
  cwd: input.hostProjectRoot
3608
3759
  });
3609
3760
  }
@@ -3612,16 +3763,16 @@ function collectRigValidatorBuildTargets(input) {
3612
3763
  }
3613
3764
  async function findLatestDistBinary(projectRoot) {
3614
3765
  const distRoot = resolveControlPlaneHostDistDir(projectRoot);
3615
- if (!existsSync7(distRoot)) {
3766
+ if (!existsSync8(distRoot)) {
3616
3767
  return null;
3617
3768
  }
3618
3769
  const entries = readdirSync(distRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("rig-")).map((entry) => ({
3619
3770
  name: entry.name,
3620
- mtimeMs: statSync(resolve12(distRoot, entry.name)).mtimeMs
3771
+ mtimeMs: statSync(resolve13(distRoot, entry.name)).mtimeMs
3621
3772
  })).sort((a, b) => b.mtimeMs - a.mtimeMs || b.name.localeCompare(a.name));
3622
3773
  for (const { name } of entries) {
3623
- const candidate = resolve12(distRoot, name, "bin", "rig");
3624
- if (existsSync7(candidate) && await isRunnableRigBinary(candidate, projectRoot)) {
3774
+ const candidate = resolve13(distRoot, name, "bin", "rig");
3775
+ if (existsSync8(candidate) && await isRunnableRigBinary(candidate, projectRoot)) {
3625
3776
  return candidate;
3626
3777
  }
3627
3778
  }
@@ -3633,7 +3784,7 @@ async function isRunnableRigBinary(binaryPath, projectRoot) {
3633
3784
  async function runDistDoctor(projectRoot) {
3634
3785
  const bunPath = Bun.which("bun");
3635
3786
  const rigPath = Bun.which("rig");
3636
- const userBinDir = resolve12(homedir3(), ".local/bin");
3787
+ const userBinDir = resolve13(homedir4(), ".local/bin");
3637
3788
  const userBinInPath = (process.env.PATH || "").split(":").filter(Boolean).includes(userBinDir);
3638
3789
  let rigRunnable = false;
3639
3790
  if (rigPath) {
@@ -3677,19 +3828,19 @@ async function executeDist(context, args) {
3677
3828
  requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
3678
3829
  const scope = parseInstallScope(scopeResult.value);
3679
3830
  const installDir = resolveInstallDir(scope, pathResult.value);
3680
- mkdirSync5(installDir, { recursive: true });
3831
+ mkdirSync6(installDir, { recursive: true });
3681
3832
  let source = await findLatestDistBinary(context.projectRoot);
3682
3833
  let buildDir = null;
3683
3834
  if (!source) {
3684
- buildDir = resolve12(resolveControlPlaneHostDistDir(context.projectRoot), `rig-install-${Date.now()}`);
3835
+ buildDir = resolve13(resolveControlPlaneHostDistDir(context.projectRoot), `rig-install-${Date.now()}`);
3685
3836
  await context.runCommand(["bun", "run", "packages/cli/bin/build-rig-binaries.ts", "--output-dir", buildDir]);
3686
- source = resolve12(buildDir, "bin", "rig");
3837
+ source = resolve13(buildDir, "bin", "rig");
3687
3838
  }
3688
- if (!existsSync7(source)) {
3839
+ if (!existsSync8(source)) {
3689
3840
  throw new CliError2(`Unable to locate rig binary at ${source}.`, 2);
3690
3841
  }
3691
- const installedPath = resolve12(installDir, "rig");
3692
- if (existsSync7(installedPath)) {
3842
+ const installedPath = resolve13(installDir, "rig");
3843
+ if (existsSync8(installedPath)) {
3693
3844
  unlinkSync(installedPath);
3694
3845
  }
3695
3846
  copyFileSync2(source, installedPath);
@@ -3731,22 +3882,22 @@ async function executeDist(context, args) {
3731
3882
  requireNoExtraArgs(rest, "rig dist rebuild-agent");
3732
3883
  const fp = await computeRuntimeImageFingerprint(context.projectRoot);
3733
3884
  const currentId = computeRuntimeImageId(fp);
3734
- const imagesDir = resolve12(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
3735
- mkdirSync5(imagesDir, { recursive: true });
3885
+ const imagesDir = resolve13(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
3886
+ mkdirSync6(imagesDir, { recursive: true });
3736
3887
  let pruned = 0;
3737
3888
  for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
3738
3889
  if (entry.isDirectory() && entry.name !== currentId) {
3739
- rmSync3(resolve12(imagesDir, entry.name), { recursive: true, force: true });
3890
+ rmSync3(resolve13(imagesDir, entry.name), { recursive: true, force: true });
3740
3891
  pruned++;
3741
3892
  }
3742
3893
  }
3743
3894
  if (pruned > 0 && context.outputMode === "text") {
3744
3895
  console.log(`Pruned ${pruned} stale image(s).`);
3745
3896
  }
3746
- const imageDir = resolve12(imagesDir, currentId);
3747
- mkdirSync5(resolve12(imageDir, "bin/hooks"), { recursive: true });
3748
- mkdirSync5(resolve12(imageDir, "bin/plugins"), { recursive: true });
3749
- mkdirSync5(resolve12(imageDir, "bin/validators"), { recursive: true });
3897
+ const imageDir = resolve13(imagesDir, currentId);
3898
+ mkdirSync6(resolve13(imageDir, "bin/hooks"), { recursive: true });
3899
+ mkdirSync6(resolve13(imageDir, "bin/plugins"), { recursive: true });
3900
+ mkdirSync6(resolve13(imageDir, "bin/validators"), { recursive: true });
3750
3901
  const hookNames = [
3751
3902
  "scope-guard",
3752
3903
  "import-guard",
@@ -3760,25 +3911,25 @@ async function executeDist(context, args) {
3760
3911
  ];
3761
3912
  const targets = [];
3762
3913
  const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || context.projectRoot;
3763
- targets.push({ source: "packages/runtime/bin/rig-agent.ts", dest: resolve12(imageDir, "bin/rig-agent"), cwd: hostProjectRoot });
3764
- targets.push({ source: "packages/runtime/bin/rig-agent-dispatch.ts", dest: resolve12(resolveControlPlaneHostBinDir(context.projectRoot), "rig-agent"), cwd: hostProjectRoot });
3914
+ targets.push({ source: "packages/runtime/bin/rig-agent.ts", dest: resolve13(imageDir, "bin/rig-agent"), cwd: hostProjectRoot });
3915
+ targets.push({ source: "packages/runtime/bin/rig-agent-dispatch.ts", dest: resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "rig-agent"), cwd: hostProjectRoot });
3765
3916
  for (const hookName of hookNames) {
3766
3917
  const src = `packages/runtime/src/control-plane/hooks/${hookName}.ts`;
3767
- targets.push({ source: src, dest: resolve12(imageDir, `bin/hooks/${hookName}`), cwd: hostProjectRoot });
3768
- targets.push({ source: src, dest: resolve12(resolveControlPlaneHostBinDir(context.projectRoot), `hooks/${hookName}`), cwd: hostProjectRoot });
3769
- }
3770
- const pluginsDir = resolve12(context.projectRoot, "rig/plugins");
3771
- const binPluginsDir = resolve12(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
3772
- const validatorsRoot = resolve12(hostProjectRoot, "packages/runtime/src/control-plane/validators");
3773
- const binValidatorsDir = resolve12(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
3774
- mkdirSync5(binPluginsDir, { recursive: true });
3775
- mkdirSync5(binValidatorsDir, { recursive: true });
3776
- if (existsSync7(pluginsDir)) {
3918
+ targets.push({ source: src, dest: resolve13(imageDir, `bin/hooks/${hookName}`), cwd: hostProjectRoot });
3919
+ targets.push({ source: src, dest: resolve13(resolveControlPlaneHostBinDir(context.projectRoot), `hooks/${hookName}`), cwd: hostProjectRoot });
3920
+ }
3921
+ const pluginsDir = resolve13(context.projectRoot, "rig/plugins");
3922
+ const binPluginsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
3923
+ const validatorsRoot = resolve13(hostProjectRoot, "packages/runtime/src/control-plane/validators");
3924
+ const binValidatorsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
3925
+ mkdirSync6(binPluginsDir, { recursive: true });
3926
+ mkdirSync6(binValidatorsDir, { recursive: true });
3927
+ if (existsSync8(pluginsDir)) {
3777
3928
  for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
3778
3929
  const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
3779
3930
  if (!m)
3780
3931
  continue;
3781
- targets.push({ source: `rig/plugins/${entry.name}`, dest: resolve12(imageDir, `bin/plugins/${m[1]}`), cwd: context.projectRoot });
3932
+ targets.push({ source: `rig/plugins/${entry.name}`, dest: resolve13(imageDir, `bin/plugins/${m[1]}`), cwd: context.projectRoot });
3782
3933
  }
3783
3934
  }
3784
3935
  targets.push(...collectRigValidatorBuildTargets({ contextProjectRoot: context.projectRoot, hostProjectRoot, imageDir }));
@@ -3789,17 +3940,17 @@ async function executeDist(context, args) {
3789
3940
  const isValidator = dest.includes("/bin/validators/");
3790
3941
  await buildBinary2(source, dest, cwd, isValidator ? { AGENT_BUN_PATH: Bun.which("bun") || "bun" } : { AGENT_PROJECT_ROOT: context.projectRoot });
3791
3942
  }
3792
- if (existsSync7(pluginsDir)) {
3943
+ if (existsSync8(pluginsDir)) {
3793
3944
  for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
3794
3945
  const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
3795
3946
  if (!m)
3796
3947
  continue;
3797
3948
  const pluginName = m[1];
3798
- const imageBin = resolve12(imageDir, `bin/plugins/${pluginName}`);
3949
+ const imageBin = resolve13(imageDir, `bin/plugins/${pluginName}`);
3799
3950
  if (!pluginName)
3800
3951
  continue;
3801
- const symlinkPath = resolve12(binPluginsDir, pluginName);
3802
- if (existsSync7(imageBin)) {
3952
+ const symlinkPath = resolve13(binPluginsDir, pluginName);
3953
+ if (existsSync8(imageBin)) {
3803
3954
  try {
3804
3955
  unlinkSync(symlinkPath);
3805
3956
  } catch {}
@@ -3807,10 +3958,10 @@ async function executeDist(context, args) {
3807
3958
  }
3808
3959
  }
3809
3960
  }
3810
- if (existsSync7(validatorsRoot)) {
3961
+ if (existsSync8(validatorsRoot)) {
3811
3962
  const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
3812
3963
  for (const category of categories) {
3813
- const categoryDir = resolve12(validatorsRoot, category.name);
3964
+ const categoryDir = resolve13(validatorsRoot, category.name);
3814
3965
  for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
3815
3966
  if (!entry.isFile() || !entry.name.endsWith(".ts"))
3816
3967
  continue;
@@ -3818,9 +3969,9 @@ async function executeDist(context, args) {
3818
3969
  if (!check || check === "index" || check === "shared")
3819
3970
  continue;
3820
3971
  const validatorName = `${category.name}-${check}`;
3821
- const imageBin = resolve12(imageDir, `bin/validators/${validatorName}`);
3822
- const symlinkPath = resolve12(binValidatorsDir, validatorName);
3823
- if (existsSync7(imageBin)) {
3972
+ const imageBin = resolve13(imageDir, `bin/validators/${validatorName}`);
3973
+ const symlinkPath = resolve13(binValidatorsDir, validatorName);
3974
+ if (existsSync8(imageBin)) {
3824
3975
  try {
3825
3976
  unlinkSync(symlinkPath);
3826
3977
  } catch {}
@@ -3829,18 +3980,18 @@ async function executeDist(context, args) {
3829
3980
  }
3830
3981
  }
3831
3982
  }
3832
- const agentsDir = resolve12(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "agents");
3833
- if (existsSync7(agentsDir)) {
3983
+ const agentsDir = resolve13(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "agents");
3984
+ if (existsSync8(agentsDir)) {
3834
3985
  let relinkCount = 0;
3835
3986
  for (const agentEntry of readdirSync(agentsDir, { withFileTypes: true })) {
3836
3987
  if (!agentEntry.isDirectory())
3837
3988
  continue;
3838
- const agentBinDir = resolve12(agentsDir, agentEntry.name, "worktree", ".rig", "bin");
3839
- if (!existsSync7(agentBinDir))
3989
+ const agentBinDir = resolve13(agentsDir, agentEntry.name, "worktree", ".rig", "bin");
3990
+ if (!existsSync8(agentBinDir))
3840
3991
  continue;
3841
3992
  const walkDir = (dir) => {
3842
3993
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
3843
- const fullPath = resolve12(dir, entry.name);
3994
+ const fullPath = resolve13(dir, entry.name);
3844
3995
  if (entry.isDirectory()) {
3845
3996
  walkDir(fullPath);
3846
3997
  } else if (entry.isSymbolicLink()) {
@@ -3874,8 +4025,8 @@ async function executeDist(context, args) {
3874
4025
 
3875
4026
  // packages/cli/src/commands/inbox.ts
3876
4027
  init_runner();
3877
- import { writeFileSync as writeFileSync4 } from "fs";
3878
- import { resolve as resolve13 } from "path";
4028
+ import { writeFileSync as writeFileSync5 } from "fs";
4029
+ import { resolve as resolve14 } from "path";
3879
4030
  import {
3880
4031
  listAuthorityRuns,
3881
4032
  readJsonlFile as readJsonlFile3,
@@ -4277,7 +4428,7 @@ async function listRemoteInboxRecords(context, kind, filters) {
4277
4428
  function listLocalInboxRecords(context, kind, filters) {
4278
4429
  const fileName = kind === "approvals" ? "approvals.jsonl" : "user-input.jsonl";
4279
4430
  const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!filters.run || entry.runId === filters.run) && (!filters.task || entry.taskId === filters.task));
4280
- return runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), fileName)).map((record) => ({
4431
+ return runs.flatMap((entry) => readJsonlFile3(resolve14(resolveAuthorityRunDir2(context.projectRoot, entry.runId), fileName)).map((record) => ({
4281
4432
  runId: entry.runId,
4282
4433
  taskId: entry.taskId ?? undefined,
4283
4434
  record
@@ -4325,11 +4476,11 @@ async function executeInbox(context, args) {
4325
4476
  if (isRemoteConnectionSelected(context.projectRoot)) {
4326
4477
  throw new CliError2("Remote approval resolution is not available from this CLI yet; use the server UI/API or switch to local state for direct JSONL edits.", 2);
4327
4478
  }
4328
- const approvalsPath = resolve13(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
4479
+ const approvalsPath = resolve14(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
4329
4480
  const approvals = readJsonlFile3(approvalsPath);
4330
4481
  const resolvedAt = new Date().toISOString();
4331
4482
  const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note: note4.value ?? null, resolvedAt } : entry);
4332
- writeFileSync4(approvalsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
4483
+ writeFileSync5(approvalsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
4333
4484
  `)}
4334
4485
  `, "utf8");
4335
4486
  return { ok: true, group: "inbox", command, details: { runId: run.value, requestId: request.value, decision: decision.value } };
@@ -4381,11 +4532,11 @@ async function executeInbox(context, args) {
4381
4532
  const [key, ...restValue] = entry.split("=");
4382
4533
  return [key, restValue.join("=")];
4383
4534
  }));
4384
- const requestsPath = resolve13(resolveAuthorityRunDir2(context.projectRoot, run.value), "user-input.jsonl");
4535
+ const requestsPath = resolve14(resolveAuthorityRunDir2(context.projectRoot, run.value), "user-input.jsonl");
4385
4536
  const requests = readJsonlFile3(requestsPath);
4386
4537
  const resolvedAt = new Date().toISOString();
4387
4538
  const next = requests.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", answers: parsedAnswers, respondedAt: resolvedAt, resolvedAt } : entry);
4388
- writeFileSync4(requestsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
4539
+ writeFileSync5(requestsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
4389
4540
  `)}
4390
4541
  `, "utf8");
4391
4542
  return { ok: true, group: "inbox", command, details: { runId: run.value, requestId: request.value, answers: parsedAnswers } };
@@ -4397,16 +4548,16 @@ async function executeInbox(context, args) {
4397
4548
 
4398
4549
  // packages/cli/src/commands/init.ts
4399
4550
  init_runner();
4400
- import { appendFileSync as appendFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
4551
+ import { appendFileSync as appendFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
4401
4552
  import { spawnSync } from "child_process";
4402
- import { resolve as resolve17 } from "path";
4553
+ import { resolve as resolve18 } from "path";
4403
4554
  import { buildRigInitConfigSource } from "@rig/core";
4404
4555
  import { listGitHubProjects as listGitHubProjectsDirect, resolveProjectStatusField as resolveProjectStatusFieldDirect } from "@rig/server";
4405
4556
 
4406
4557
  // packages/cli/src/commands/_pi-install.ts
4407
- import { existsSync as existsSync8, readFileSync as readFileSync4, rmSync as rmSync4 } from "fs";
4408
- import { homedir as homedir4 } from "os";
4409
- import { resolve as resolve14 } from "path";
4558
+ import { existsSync as existsSync9, readFileSync as readFileSync5, rmSync as rmSync4 } from "fs";
4559
+ import { homedir as homedir5 } from "os";
4560
+ import { resolve as resolve15 } from "path";
4410
4561
  var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
4411
4562
  var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
4412
4563
  var LEGACY_PI_RIG_MARKER = `// Managed by Rig. Source package: @rig/pi-rig.
@@ -4422,16 +4573,16 @@ async function defaultCommandRunner(command, options = {}) {
4422
4573
  return { exitCode, stdout, stderr };
4423
4574
  }
4424
4575
  function resolvePiRigExtensionPath(homeDir) {
4425
- return resolve14(homeDir, ".pi", "agent", "extensions", "pi-rig");
4576
+ return resolve15(homeDir, ".pi", "agent", "extensions", "pi-rig");
4426
4577
  }
4427
- function resolvePiRigPackageSource(projectRoot, exists = existsSync8) {
4428
- const localPackage = resolve14(projectRoot, "packages", "pi-rig");
4429
- if (exists(resolve14(localPackage, "package.json")))
4578
+ function resolvePiRigPackageSource(projectRoot, exists = existsSync9) {
4579
+ const localPackage = resolve15(projectRoot, "packages", "pi-rig");
4580
+ if (exists(resolve15(localPackage, "package.json")))
4430
4581
  return localPackage;
4431
4582
  return `npm:${PI_RIG_PACKAGE_NAME}`;
4432
4583
  }
4433
4584
  function resolvePiHomeDir(inputHomeDir) {
4434
- return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ?? homedir4();
4585
+ return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ?? homedir5();
4435
4586
  }
4436
4587
  function piListContainsPiRig(output) {
4437
4588
  return output.split(/\r?\n/).some((line) => {
@@ -4477,13 +4628,13 @@ async function ensurePiBinaryAvailable(input) {
4477
4628
  ...next.exitCode === 0 ? {} : { error: (next.stderr || next.stdout).trim() || "pi --version failed after install" }
4478
4629
  };
4479
4630
  }
4480
- function removeManagedLegacyPiRigBridge(homeDir, exists = existsSync8) {
4631
+ function removeManagedLegacyPiRigBridge(homeDir, exists = existsSync9) {
4481
4632
  const extensionPath = resolvePiRigExtensionPath(homeDir);
4482
- const indexPath = resolve14(extensionPath, "index.ts");
4633
+ const indexPath = resolve15(extensionPath, "index.ts");
4483
4634
  if (!exists(indexPath))
4484
4635
  return;
4485
4636
  try {
4486
- const content = readFileSync4(indexPath, "utf8");
4637
+ const content = readFileSync5(indexPath, "utf8");
4487
4638
  if (content === LEGACY_PI_RIG_MARKER || content.includes("Managed by Rig. Source package: @rig/pi-rig")) {
4488
4639
  rmSync4(extensionPath, { recursive: true, force: true });
4489
4640
  }
@@ -4499,13 +4650,13 @@ async function checkPiRigInstall(input = {}) {
4499
4650
  piRig: { ok: true, label: "pi-rig global extension", detail: extensionPath }
4500
4651
  };
4501
4652
  }
4502
- const exists = input.exists ?? existsSync8;
4653
+ const exists = input.exists ?? existsSync9;
4503
4654
  const runner = input.commandRunner ?? defaultCommandRunner;
4504
4655
  const piResult = await safeRun(runner, ["pi", "--version"]);
4505
4656
  const piListResult = piResult.exitCode === 0 ? await safeRun(runner, ["pi", "list"]) : { exitCode: 1, stdout: "", stderr: "" };
4506
4657
  const listedPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
4507
4658
  ${piListResult.stderr}`);
4508
- const legacyBridge = exists(resolve14(extensionPath, "index.ts"));
4659
+ const legacyBridge = exists(resolve15(extensionPath, "index.ts"));
4509
4660
  const hasPiRig = listedPiRig;
4510
4661
  return {
4511
4662
  extensionPath,
@@ -4582,7 +4733,7 @@ async function buildPiSetupChecks(input = {}) {
4582
4733
 
4583
4734
  // packages/cli/src/commands/_snapshot-upload.ts
4584
4735
  import { mkdir, readdir, readFile, writeFile } from "fs/promises";
4585
- import { dirname as dirname2, resolve as resolve15, relative, sep } from "path";
4736
+ import { dirname as dirname3, resolve as resolve16, relative, sep } from "path";
4586
4737
  var SNAPSHOT_ARCHIVE_VERSION = 1;
4587
4738
  var SNAPSHOT_ARCHIVE_CONTENT_TYPE = "application/vnd.rig.snapshot+json";
4588
4739
  var DEFAULT_EXCLUDED_DIRECTORIES = new Set([
@@ -4604,15 +4755,15 @@ function assertManifestPath(root, relativePath) {
4604
4755
  if (!relativePath || relativePath.startsWith("/") || relativePath.includes("\x00")) {
4605
4756
  throw new Error(`Invalid snapshot path: ${relativePath}`);
4606
4757
  }
4607
- const resolved = resolve15(root, relativePath);
4758
+ const resolved = resolve16(root, relativePath);
4608
4759
  const relativeToRoot = relative(root, resolved);
4609
- if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || resolve15(relativeToRoot) === resolved) {
4760
+ if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || resolve16(relativeToRoot) === resolved) {
4610
4761
  throw new Error(`Snapshot path escapes project root: ${relativePath}`);
4611
4762
  }
4612
4763
  return resolved;
4613
4764
  }
4614
4765
  async function buildSnapshotUploadManifest(projectRoot, options = {}) {
4615
- const root = resolve15(projectRoot);
4766
+ const root = resolve16(projectRoot);
4616
4767
  const excludedDirectories = [...new Set([
4617
4768
  ...DEFAULT_EXCLUDED_DIRECTORIES,
4618
4769
  ...options.excludedDirectories ?? []
@@ -4624,7 +4775,7 @@ async function buildSnapshotUploadManifest(projectRoot, options = {}) {
4624
4775
  for (const entry of entries) {
4625
4776
  if (entry.isDirectory() && excludedSet.has(entry.name))
4626
4777
  continue;
4627
- const fullPath = resolve15(dir, entry.name);
4778
+ const fullPath = resolve16(dir, entry.name);
4628
4779
  if (entry.isDirectory()) {
4629
4780
  await visit(fullPath);
4630
4781
  continue;
@@ -4673,8 +4824,8 @@ async function uploadSnapshotArchiveViaServer(context, input) {
4673
4824
 
4674
4825
  // packages/cli/src/commands/_doctor-checks.ts
4675
4826
  init_runner();
4676
- import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
4677
- import { resolve as resolve16 } from "path";
4827
+ import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
4828
+ import { resolve as resolve17 } from "path";
4678
4829
  import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
4679
4830
  init__parsers();
4680
4831
  function check(id, label, status, detail, remediation) {
@@ -4715,11 +4866,11 @@ function repoSlugFromConfig(config) {
4715
4866
  function loadFallbackConfig(projectRoot) {
4716
4867
  const candidates = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
4717
4868
  for (const name of candidates) {
4718
- const path = resolve16(projectRoot, name);
4719
- if (!existsSync9(path))
4869
+ const path = resolve17(projectRoot, name);
4870
+ if (!existsSync10(path))
4720
4871
  continue;
4721
4872
  try {
4722
- const source = readFileSync5(path, "utf8");
4873
+ const source = readFileSync6(path, "utf8");
4723
4874
  if (name.endsWith(".json"))
4724
4875
  return JSON.parse(source);
4725
4876
  const owner = source.match(/owner\s*:\s*["']([^"']+)["']/)?.[1];
@@ -4798,7 +4949,7 @@ async function runRigDoctorChecks(options) {
4798
4949
  checks.push(check("bun", `bun >= ${MIN_SUPPORTED_BUN_VERSION}`, isSupportedBunVersion(bunVersion) ? "pass" : "fail", `found ${bunVersion}`, `Install Bun ${MIN_SUPPORTED_BUN_VERSION} or newer.`), check("git", "git", which("git") ? "pass" : "fail", which("git") ?? undefined, "Install git and ensure it is on PATH."), check("jq", "jq", which("jq") ? "pass" : "warn", which("jq") ?? undefined, "Install jq (for example `brew install jq`)."));
4799
4950
  const loadedConfig = await loadConfig(projectRoot).catch(() => null);
4800
4951
  const config = loadedConfig ?? loadFallbackConfig(projectRoot);
4801
- const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync9(resolve16(projectRoot, name)));
4952
+ const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync10(resolve17(projectRoot, name)));
4802
4953
  checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "Run `rig init` or fix the config error."));
4803
4954
  const taskSourceKind = config?.taskSource?.kind;
4804
4955
  checks.push(taskSourceKind ? check("task-source", "task source configured", "pass", taskSourceKind) : check("task-source", "task source configured", "fail", "missing taskSource", "Configure taskSource in rig.config.ts."));
@@ -4917,20 +5068,20 @@ function parseRepoSlug(value) {
4917
5068
  return { owner: match[1], repo: match[2], slug: `${match[1]}/${match[2]}` };
4918
5069
  }
4919
5070
  function ensureRigPrivateDirs(projectRoot) {
4920
- const rigDir = resolve17(projectRoot, ".rig");
4921
- mkdirSync6(resolve17(rigDir, "state"), { recursive: true });
4922
- mkdirSync6(resolve17(rigDir, "logs"), { recursive: true });
4923
- mkdirSync6(resolve17(rigDir, "runs"), { recursive: true });
4924
- mkdirSync6(resolve17(rigDir, "tmp"), { recursive: true });
4925
- mkdirSync6(resolve17(projectRoot, "artifacts"), { recursive: true });
4926
- const taskConfigPath = resolve17(rigDir, "task-config.json");
4927
- if (!existsSync10(taskConfigPath))
4928
- writeFileSync5(taskConfigPath, `{}
5071
+ const rigDir = resolve18(projectRoot, ".rig");
5072
+ mkdirSync7(resolve18(rigDir, "state"), { recursive: true });
5073
+ mkdirSync7(resolve18(rigDir, "logs"), { recursive: true });
5074
+ mkdirSync7(resolve18(rigDir, "runs"), { recursive: true });
5075
+ mkdirSync7(resolve18(rigDir, "tmp"), { recursive: true });
5076
+ mkdirSync7(resolve18(projectRoot, "artifacts"), { recursive: true });
5077
+ const taskConfigPath = resolve18(rigDir, "task-config.json");
5078
+ if (!existsSync11(taskConfigPath))
5079
+ writeFileSync6(taskConfigPath, `{}
4929
5080
  `, "utf-8");
4930
5081
  }
4931
5082
  function ensureGitignoreEntries(projectRoot) {
4932
- const path = resolve17(projectRoot, ".gitignore");
4933
- const existing = existsSync10(path) ? readFileSync6(path, "utf8") : "";
5083
+ const path = resolve18(projectRoot, ".gitignore");
5084
+ const existing = existsSync11(path) ? readFileSync7(path, "utf8") : "";
4934
5085
  const entries = [".rig/state/", ".rig/logs/", ".rig/runs/", ".rig/tmp/"];
4935
5086
  const missing = entries.filter((entry) => !existing.split(/\r?\n/).includes(entry));
4936
5087
  if (missing.length === 0)
@@ -4943,17 +5094,17 @@ function ensureGitignoreEntries(projectRoot) {
4943
5094
  `, "utf8");
4944
5095
  }
4945
5096
  function ensureRigConfigPackageDependencies(projectRoot) {
4946
- const path = resolve17(projectRoot, "package.json");
4947
- const existing = existsSync10(path) ? JSON.parse(readFileSync6(path, "utf8")) : {};
5097
+ const path = resolve18(projectRoot, "package.json");
5098
+ const existing = existsSync11(path) ? JSON.parse(readFileSync7(path, "utf8")) : {};
4948
5099
  const devDependencies = existing.devDependencies && typeof existing.devDependencies === "object" && !Array.isArray(existing.devDependencies) ? { ...existing.devDependencies } : {};
4949
5100
  for (const [name, spec] of Object.entries(RIG_CONFIG_DEV_DEPENDENCIES)) {
4950
5101
  devDependencies[name] = spec;
4951
5102
  }
4952
5103
  const next = {
4953
- ...existsSync10(path) ? existing : { name: "rig-project", private: true },
5104
+ ...existsSync11(path) ? existing : { name: "rig-project", private: true },
4954
5105
  devDependencies
4955
5106
  };
4956
- writeFileSync5(path, `${JSON.stringify(next, null, 2)}
5107
+ writeFileSync6(path, `${JSON.stringify(next, null, 2)}
4957
5108
  `, "utf8");
4958
5109
  }
4959
5110
  function applyGitHubProjectConfig(source, options) {
@@ -5202,7 +5353,7 @@ async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken
5202
5353
  };
5203
5354
  }
5204
5355
  function sleep2(ms) {
5205
- return new Promise((resolve18) => setTimeout(resolve18, ms));
5356
+ return new Promise((resolve19) => setTimeout(resolve19, ms));
5206
5357
  }
5207
5358
  function positiveIntFromEnv(name, fallback) {
5208
5359
  const value = Number.parseInt(process.env[name] ?? "", 10);
@@ -5231,7 +5382,7 @@ function remoteGitHubAuthMetadata(payload) {
5231
5382
  };
5232
5383
  }
5233
5384
  function writeRemoteGitHubAuthState(projectRoot, input) {
5234
- writeFileSync5(resolve17(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
5385
+ writeFileSync6(resolve18(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
5235
5386
  authenticated: true,
5236
5387
  source: input.source,
5237
5388
  storedOnServer: true,
@@ -5288,9 +5439,9 @@ async function runControlPlaneInit(context, options) {
5288
5439
  });
5289
5440
  ensureRigPrivateDirs(projectRoot);
5290
5441
  ensureGitignoreEntries(projectRoot);
5291
- const configTsPath = resolve17(projectRoot, "rig.config.ts");
5292
- const configJsonPath = resolve17(projectRoot, "rig.config.json");
5293
- const configExists = existsSync10(configTsPath) || existsSync10(configJsonPath);
5442
+ const configTsPath = resolve18(projectRoot, "rig.config.ts");
5443
+ const configJsonPath = resolve18(projectRoot, "rig.config.json");
5444
+ const configExists = existsSync11(configTsPath) || existsSync11(configJsonPath);
5294
5445
  if (!options.privateStateOnly) {
5295
5446
  if (configExists && !options.repair) {
5296
5447
  if (context.outputMode !== "json")
@@ -5302,11 +5453,11 @@ async function runControlPlaneInit(context, options) {
5302
5453
  taskSource: { kind: "github-issues", owner: repo.owner, repo: repo.repo },
5303
5454
  useStandardPlugin: true
5304
5455
  }), options);
5305
- writeFileSync5(configTsPath, source, "utf-8");
5456
+ writeFileSync6(configTsPath, source, "utf-8");
5306
5457
  }
5307
5458
  ensureRigConfigPackageDependencies(projectRoot);
5308
5459
  }
5309
- writeFileSync5(resolve17(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
5460
+ writeFileSync6(resolve18(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
5310
5461
  `, "utf8");
5311
5462
  const checkout = checkoutForInit(projectRoot, serverKind, options.remoteCheckout);
5312
5463
  let uploadedSnapshot = null;
@@ -5502,7 +5653,7 @@ function parseInitOptions(args) {
5502
5653
  async function runInteractiveControlPlaneInit(context, prompts) {
5503
5654
  prompts.intro?.("Initialize a Rig control-plane project");
5504
5655
  const projectRoot = context.projectRoot;
5505
- const existingConfig = existsSync10(resolve17(projectRoot, "rig.config.ts")) || existsSync10(resolve17(projectRoot, "rig.config.json"));
5656
+ const existingConfig = existsSync11(resolve18(projectRoot, "rig.config.ts")) || existsSync11(resolve18(projectRoot, "rig.config.json"));
5506
5657
  let repair = false;
5507
5658
  let privateStateOnly = false;
5508
5659
  if (existingConfig) {
@@ -5805,8 +5956,8 @@ async function executeDoctor(context, args) {
5805
5956
 
5806
5957
  // packages/cli/src/commands/_run-driver-helpers.ts
5807
5958
  init_runner();
5808
- import { readFileSync as readFileSync7 } from "fs";
5809
- import { resolve as resolve18 } from "path";
5959
+ import { readFileSync as readFileSync8 } from "fs";
5960
+ import { resolve as resolve19 } from "path";
5810
5961
  import {
5811
5962
  appendJsonlRecord as appendJsonlRecord2,
5812
5963
  readAuthorityRun as readAuthorityRun2,
@@ -5826,7 +5977,7 @@ function patchAuthorityRun(projectRoot, runId, patch) {
5826
5977
  ...patch,
5827
5978
  updatedAt: new Date().toISOString()
5828
5979
  };
5829
- writeJsonFile4(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), next);
5980
+ writeJsonFile4(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), next);
5830
5981
  return next;
5831
5982
  }
5832
5983
  function touchAuthorityRun(projectRoot, runId) {
@@ -5834,21 +5985,21 @@ function touchAuthorityRun(projectRoot, runId) {
5834
5985
  if (!current) {
5835
5986
  return;
5836
5987
  }
5837
- writeJsonFile4(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), {
5988
+ writeJsonFile4(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), {
5838
5989
  ...current,
5839
5990
  updatedAt: new Date().toISOString()
5840
5991
  });
5841
5992
  }
5842
5993
  function appendRunTimeline(projectRoot, runId, value) {
5843
- appendJsonlRecord2(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), value);
5994
+ appendJsonlRecord2(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), value);
5844
5995
  touchAuthorityRun(projectRoot, runId);
5845
5996
  }
5846
5997
  function appendRunLog(projectRoot, runId, value) {
5847
- appendJsonlRecord2(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "logs.jsonl"), value);
5998
+ appendJsonlRecord2(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "logs.jsonl"), value);
5848
5999
  touchAuthorityRun(projectRoot, runId);
5849
6000
  }
5850
6001
  function appendRunAction(projectRoot, runId, value) {
5851
- appendJsonlRecord2(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), {
6002
+ appendJsonlRecord2(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), {
5852
6003
  id: value.id,
5853
6004
  type: "action",
5854
6005
  actionType: value.actionType,
@@ -5919,7 +6070,7 @@ function buildRunPrompt(input) {
5919
6070
  })();
5920
6071
  const scopeText = (() => {
5921
6072
  try {
5922
- const parsed = JSON.parse(readFileSync7(resolveControlPlaneTaskConfigPath(input.projectRoot), "utf8"));
6073
+ const parsed = JSON.parse(readFileSync8(resolveControlPlaneTaskConfigPath(input.projectRoot), "utf8"));
5923
6074
  const entry = parsed[input.taskId] ?? {};
5924
6075
  const scope = Array.isArray(entry.scope) ? entry.scope.filter((item) => typeof item === "string") : [];
5925
6076
  const validation = Array.isArray(entry.validation) ? entry.validation.filter((item) => typeof item === "string") : [];
@@ -6033,8 +6184,8 @@ function renderSourceScopeValidation(task, validation) {
6033
6184
 
6034
6185
  // packages/cli/src/commands/inspect.ts
6035
6186
  init_runner();
6036
- import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
6037
- import { resolve as resolve19 } from "path";
6187
+ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
6188
+ import { resolve as resolve20 } from "path";
6038
6189
  import {
6039
6190
  listAuthorityRuns as listAuthorityRuns2,
6040
6191
  readAuthorityRun as readAuthorityRun3,
@@ -6053,10 +6204,27 @@ async function executeInspect(context, args) {
6053
6204
  const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
6054
6205
  const latestRun = listAuthorityRuns2(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6055
6206
  if (!latestRun) {
6056
- throw new CliError2(`No runs found for ${requiredTask}.`);
6207
+ const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
6208
+ const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6209
+ if (!serverRun || typeof serverRun.runId !== "string") {
6210
+ throw new CliError2(`No runs found for ${requiredTask} (local or on the selected server).`);
6211
+ }
6212
+ const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
6213
+ const entries = Array.isArray(page.entries) ? page.entries : [];
6214
+ if (context.outputMode === "text") {
6215
+ for (const entry of entries) {
6216
+ const record = entry && typeof entry === "object" ? entry : {};
6217
+ const title = String(record.title ?? "");
6218
+ const detail = String(record.detail ?? "");
6219
+ console.log([title, detail].filter(Boolean).join(" \u2014 "));
6220
+ }
6221
+ if (entries.length === 0)
6222
+ console.log(`(no log entries for run ${serverRun.runId})`);
6223
+ }
6224
+ return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
6057
6225
  }
6058
- const logsPath = resolve19(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
6059
- if (!existsSync11(logsPath)) {
6226
+ const logsPath = resolve20(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
6227
+ if (!existsSync12(logsPath)) {
6060
6228
  throw new CliError2(`No logs found for run ${latestRun.runId}.`);
6061
6229
  }
6062
6230
  await context.runCommand(["cat", logsPath]);
@@ -6066,7 +6234,7 @@ async function executeInspect(context, args) {
6066
6234
  const { value: task, rest: remaining } = takeOption(rest, "--task");
6067
6235
  requireNoExtraArgs(remaining, "rig inspect artifacts --task <task-id>");
6068
6236
  const requiredTask = requireTask(task, "rig inspect artifacts --task <task-id>");
6069
- const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync11(path));
6237
+ const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync12(path));
6070
6238
  if (!artifactRoot) {
6071
6239
  throw new CliError2(`No artifacts found for ${requiredTask}.`);
6072
6240
  }
@@ -6123,10 +6291,10 @@ async function executeInspect(context, args) {
6123
6291
  case "failures": {
6124
6292
  requireNoExtraArgs(rest, "rig inspect failures");
6125
6293
  const failed = resolveHarnessPaths2(context.projectRoot).failedApproachesPath;
6126
- if (!existsSync11(failed)) {
6294
+ if (!existsSync12(failed)) {
6127
6295
  console.log("No failures recorded.");
6128
6296
  } else {
6129
- process.stdout.write(readFileSync8(failed, "utf-8"));
6297
+ process.stdout.write(readFileSync9(failed, "utf-8"));
6130
6298
  }
6131
6299
  return { ok: true, group: "inspect", command };
6132
6300
  }
@@ -6143,11 +6311,11 @@ async function executeInspect(context, args) {
6143
6311
  return { ok: true, group: "inspect", command };
6144
6312
  case "audit": {
6145
6313
  requireNoExtraArgs(rest, "rig inspect audit");
6146
- const auditPath = resolve19(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
6147
- if (!existsSync11(auditPath)) {
6314
+ const auditPath = resolve20(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
6315
+ if (!existsSync12(auditPath)) {
6148
6316
  console.log("No audit log found.");
6149
6317
  } else {
6150
- const lines = readFileSync8(auditPath, "utf-8").split(/\r?\n/).filter(Boolean).slice(-20);
6318
+ const lines = readFileSync9(auditPath, "utf-8").split(/\r?\n/).filter(Boolean).slice(-20);
6151
6319
  for (const line of lines) {
6152
6320
  console.log(line);
6153
6321
  }
@@ -7338,7 +7506,38 @@ function parseWsPayload(message2) {
7338
7506
  return JSON.parse(message2.data);
7339
7507
  return JSON.parse(Buffer.from(message2.data).toString("utf8"));
7340
7508
  }
7341
- async function connectWorkerStream(options, ctx, state) {
7509
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
7510
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
7511
+ for (const command of commands) {
7512
+ const record = recordOf(command);
7513
+ const name = typeof record?.name === "string" ? record.name : "";
7514
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
7515
+ continue;
7516
+ registered.add(name);
7517
+ const description = typeof record?.description === "string" ? record.description : undefined;
7518
+ const source = typeof record?.source === "string" ? record.source : "worker";
7519
+ try {
7520
+ pi.registerCommand(name, {
7521
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
7522
+ handler: async (args) => {
7523
+ const text2 = `/${name}${args ? ` ${args}` : ""}`;
7524
+ appendTranscript(state, "You", text2);
7525
+ try {
7526
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text2);
7527
+ const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
7528
+ appendTranscript(state, "System", message2);
7529
+ if (state.nativeStream)
7530
+ ctx.ui.notify(message2, "info");
7531
+ } catch (error) {
7532
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
7533
+ }
7534
+ updatePiUi(ctx, state);
7535
+ }
7536
+ });
7537
+ } catch {}
7538
+ }
7539
+ }
7540
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
7342
7541
  const ready = await waitForWorkerReady(options, ctx, state);
7343
7542
  if (!ready)
7344
7543
  return;
@@ -7346,7 +7545,7 @@ async function connectWorkerStream(options, ctx, state) {
7346
7545
  const buffered = [];
7347
7546
  const wsUrl = await buildRunPiEventsWebSocketUrl(options.context, options.runId);
7348
7547
  const socket = new WebSocket(wsUrl);
7349
- const closePromise = new Promise((resolve20) => {
7548
+ const closePromise = new Promise((resolve21) => {
7350
7549
  socket.onopen = () => {
7351
7550
  state.wsConnected = true;
7352
7551
  state.status = "live worker Pi WebSocket connected";
@@ -7371,7 +7570,7 @@ async function connectWorkerStream(options, ctx, state) {
7371
7570
  state.wsConnected = false;
7372
7571
  state.status = "worker Pi WebSocket disconnected";
7373
7572
  updatePiUi(ctx, state);
7374
- resolve20();
7573
+ resolve21();
7375
7574
  };
7376
7575
  });
7377
7576
  try {
@@ -7393,6 +7592,7 @@ async function connectWorkerStream(options, ctx, state) {
7393
7592
  const record = recordOf(command);
7394
7593
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
7395
7594
  });
7595
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
7396
7596
  catchupDone = true;
7397
7597
  for (const payload of buffered.splice(0))
7398
7598
  applyEnvelope(ctx, state, payload);
@@ -7407,11 +7607,11 @@ async function connectWorkerStream(options, ctx, state) {
7407
7607
  function createRemoteBashOperations(options, state, excludeFromContext) {
7408
7608
  return {
7409
7609
  exec(command, _cwd, execOptions) {
7410
- return new Promise((resolve20, reject) => {
7610
+ return new Promise((resolve21, reject) => {
7411
7611
  const pending = {
7412
7612
  command,
7413
7613
  onData: execOptions.onData,
7414
- resolve: resolve20,
7614
+ resolve: resolve21,
7415
7615
  reject,
7416
7616
  sawChunk: false
7417
7617
  };
@@ -7520,6 +7720,7 @@ function createRigWorkerPiBridgeExtension(options) {
7520
7720
  };
7521
7721
  if (options.initialMessageSent)
7522
7722
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
7723
+ const registeredDaemonCommands = new Set;
7523
7724
  let nativePiUiContextAvailable = false;
7524
7725
  pi.on("user_bash", (event) => {
7525
7726
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -7552,7 +7753,7 @@ function createRigWorkerPiBridgeExtension(options) {
7552
7753
  });
7553
7754
  return { consume: true };
7554
7755
  });
7555
- connectWorkerStream(options, ctx, state).catch((error) => {
7756
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
7556
7757
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
7557
7758
  updatePiUi(ctx, state);
7558
7759
  });
@@ -7599,8 +7800,6 @@ async function attachRunBundledPiFrontend(context, input) {
7599
7800
  "--no-tools",
7600
7801
  "--no-builtin-tools",
7601
7802
  "--no-skills",
7602
- "--no-prompt-templates",
7603
- "--no-themes",
7604
7803
  "--no-context-files",
7605
7804
  "--no-approve"
7606
7805
  ], {
@@ -8074,6 +8273,33 @@ async function executeRun(context, args) {
8074
8273
  }
8075
8274
  return { ok: true, group: "run", command, details: restarted };
8076
8275
  }
8276
+ case "steer": {
8277
+ const runOption = takeOption(rest, "--run");
8278
+ const messageOption = takeOption(runOption.rest, "--message");
8279
+ const shortMessageOption = takeOption(messageOption.rest, "-m");
8280
+ const positionalRunId = shortMessageOption.rest.length > 0 ? shortMessageOption.rest[0] : undefined;
8281
+ const extra = positionalRunId ? shortMessageOption.rest.slice(1) : shortMessageOption.rest;
8282
+ requireNoExtraArgs(extra, "rig run steer [<run-id>|--run <id>] --message <text>");
8283
+ const runId = runOption.value ?? positionalRunId;
8284
+ const message2 = messageOption.value ?? shortMessageOption.value;
8285
+ if (!runId) {
8286
+ throw new CliError2("run steer requires a run id (positional or --run <id>).", 2);
8287
+ }
8288
+ if (!message2?.trim()) {
8289
+ throw new CliError2("run steer requires --message <text>.", 2);
8290
+ }
8291
+ if (context.dryRun) {
8292
+ if (context.outputMode === "text") {
8293
+ console.log(`[dry-run] rig run steer ${runId} --message ${JSON.stringify(message2)}`);
8294
+ }
8295
+ return { ok: true, group: "run", command, details: { runId, dryRun: true } };
8296
+ }
8297
+ await steerRunViaServer(context, runId, message2.trim());
8298
+ if (context.outputMode === "text") {
8299
+ console.log(`Steering message queued for ${runId}.`);
8300
+ }
8301
+ return { ok: true, group: "run", command, details: { runId, queued: true } };
8302
+ }
8077
8303
  case "stop": {
8078
8304
  const runOption = takeOption(rest, "--run");
8079
8305
  const positionalRunId = runOption.rest.length > 0 ? runOption.rest[0] : undefined;
@@ -8118,6 +8344,7 @@ async function executeRun(context, args) {
8118
8344
 
8119
8345
  // packages/cli/src/commands/server.ts
8120
8346
  init_runner();
8347
+ import { resolveRigServerCommand } from "@rig/runtime/local-server";
8121
8348
  async function executeServer(context, args, options) {
8122
8349
  const [command = "status", ...rest] = args;
8123
8350
  if (["status", "list", "add", "use"].includes(command)) {
@@ -8135,7 +8362,8 @@ async function executeServer(context, args, options) {
8135
8362
  const authTokenResult = takeOption(pending, "--auth-token");
8136
8363
  pending = authTokenResult.rest;
8137
8364
  requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
8138
- const commandParts = ["rig-server", "start"];
8365
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8366
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
8139
8367
  if (hostResult.value) {
8140
8368
  commandParts.push("--host", hostResult.value);
8141
8369
  }
@@ -8158,7 +8386,8 @@ async function executeServer(context, args, options) {
8158
8386
  const eventResult = takeOption(pending, "--event");
8159
8387
  pending = eventResult.rest;
8160
8388
  requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
8161
- const commandParts = ["rig-server", "notify-test"];
8389
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8390
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
8162
8391
  if (eventResult.value) {
8163
8392
  commandParts.push("--event", eventResult.value);
8164
8393
  }
@@ -8220,9 +8449,9 @@ async function executeServer(context, args, options) {
8220
8449
 
8221
8450
  // packages/cli/src/commands/task.ts
8222
8451
  init_runner();
8223
- import { readFileSync as readFileSync9 } from "fs";
8452
+ import { readFileSync as readFileSync10 } from "fs";
8224
8453
  import { spawnSync as spawnSync3 } from "child_process";
8225
- import { resolve as resolve20 } from "path";
8454
+ import { resolve as resolve21 } from "path";
8226
8455
  import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
8227
8456
  import {
8228
8457
  taskArtifactDir,
@@ -8400,6 +8629,7 @@ var PRIMARY_GROUPS = [
8400
8629
  { command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
8401
8630
  { command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; --follow launches native bundled Pi for live Pi runs.", primary: true },
8402
8631
  { command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
8632
+ { command: "steer <run-id> --message <text>", description: "Queue a steering message into a live worker without attaching." },
8403
8633
  { command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
8404
8634
  { command: "resume", description: "Resume the most recent interrupted local run." },
8405
8635
  { command: "restart", description: "Restart the most recent local run from a clean runtime." },
@@ -8501,6 +8731,19 @@ var ADVANCED_GROUPS = [
8501
8731
  { command: "hp-next <dev|check|e2e|reset>", description: "Drive the hp-next browser test harness." }
8502
8732
  ]
8503
8733
  },
8734
+ {
8735
+ name: "pi",
8736
+ summary: "Manage Pi extension packages for this project (community extensions from npm/git).",
8737
+ usage: ["rig pi <list|add|remove|search> [args]"],
8738
+ commands: [
8739
+ { command: "list", description: "Show project and user Pi extension packages." },
8740
+ { command: "add <source>", description: "Add an npm/git Pi extension to .pi/settings.json (auto-installs at next session)." },
8741
+ { command: "remove <source>", description: "Remove an operator-added Pi extension." },
8742
+ { command: "search [term]", description: "Discover Pi extension packages on the npm registry." }
8743
+ ],
8744
+ examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
8745
+ next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
8746
+ },
8504
8747
  {
8505
8748
  name: "plugin",
8506
8749
  summary: "Plugin listing, validation, and plugin-contributed commands.",
@@ -8931,7 +9174,7 @@ async function executeTask(context, args, options) {
8931
9174
  const fileFlag = takeOption(rest.slice(1), "--file");
8932
9175
  let content;
8933
9176
  if (fileFlag.value) {
8934
- content = readFileSync9(resolve20(context.projectRoot, fileFlag.value), "utf-8");
9177
+ content = readFileSync10(resolve21(context.projectRoot, fileFlag.value), "utf-8");
8935
9178
  } else {
8936
9179
  content = await readStdin();
8937
9180
  }
@@ -9165,8 +9408,8 @@ async function executeTask(context, args, options) {
9165
9408
 
9166
9409
  // packages/cli/src/commands/task-run-driver.ts
9167
9410
  init_runner();
9168
- import { copyFileSync as copyFileSync3, existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync10, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
9169
- import { resolve as resolve21 } from "path";
9411
+ import { copyFileSync as copyFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
9412
+ import { resolve as resolve22 } from "path";
9170
9413
  import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
9171
9414
  import { createInterface as createLineInterface } from "readline";
9172
9415
  import { loadConfig as loadConfig2 } from "@rig/core/load-config";
@@ -9249,12 +9492,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
9249
9492
  return 0;
9250
9493
  let copied = 0;
9251
9494
  for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
9252
- const sourcePath = resolve21(sourceRoot, relativePath);
9253
- const targetPath = resolve21(targetRoot, relativePath);
9495
+ const sourcePath = resolve22(sourceRoot, relativePath);
9496
+ const targetPath = resolve22(targetRoot, relativePath);
9254
9497
  try {
9255
9498
  if (!statSync2(sourcePath).isFile())
9256
9499
  continue;
9257
- mkdirSync7(resolve21(targetPath, ".."), { recursive: true });
9500
+ mkdirSync8(resolve22(targetPath, ".."), { recursive: true });
9258
9501
  copyFileSync3(sourcePath, targetPath);
9259
9502
  copied += 1;
9260
9503
  } catch {}
@@ -9293,7 +9536,7 @@ function buildDirtyBaselineHandshakeEnv(input) {
9293
9536
  return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
9294
9537
  return {
9295
9538
  RIG_BASELINE_MODE: "dirty-snapshot",
9296
- RIG_DIRTY_BASELINE_READY_FILE: resolve21(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
9539
+ RIG_DIRTY_BASELINE_READY_FILE: resolve22(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
9297
9540
  };
9298
9541
  }
9299
9542
  function positiveInt(value, fallback) {
@@ -9404,9 +9647,9 @@ function createCommandRunner(binary) {
9404
9647
  const stderrChunks = [];
9405
9648
  child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
9406
9649
  child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
9407
- return await new Promise((resolve22) => {
9408
- child.once("error", (error) => resolve22({ exitCode: 1, stderr: error.message }));
9409
- child.once("close", (code) => resolve22({
9650
+ return await new Promise((resolve23) => {
9651
+ child.once("error", (error) => resolve23({ exitCode: 1, stderr: error.message }));
9652
+ child.once("close", (code) => resolve23({
9410
9653
  exitCode: code ?? 1,
9411
9654
  stdout: Buffer.concat(stdoutChunks).toString("utf8"),
9412
9655
  stderr: Buffer.concat(stderrChunks).toString("utf8")
@@ -9480,7 +9723,7 @@ async function runTaskRunPostValidationLifecycle(input) {
9480
9723
  config,
9481
9724
  sourceTask: input.sourceTask,
9482
9725
  uploadedSnapshot: input.uploadedSnapshot,
9483
- artifactRoot: resolve21(input.projectRoot, "artifacts", taskId3),
9726
+ artifactRoot: resolve22(input.projectRoot, "artifacts", taskId3),
9484
9727
  command: ghCommand,
9485
9728
  gitCommand,
9486
9729
  steerPi,
@@ -9610,7 +9853,7 @@ function summarizeValidationFailure(projectRoot, taskId3) {
9610
9853
  return null;
9611
9854
  }
9612
9855
  for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId3)) {
9613
- const summary = readJsonFile3(resolve21(artifactDir, "validation-summary.json"), null);
9856
+ const summary = readJsonFile3(resolve22(artifactDir, "validation-summary.json"), null);
9614
9857
  if (!summary || summary.status !== "fail") {
9615
9858
  continue;
9616
9859
  }
@@ -9691,9 +9934,9 @@ function readTaskRunAcceptedArtifactState(input) {
9691
9934
  if (!input.taskId || !input.workspaceDir) {
9692
9935
  return { accepted: false, reason: null };
9693
9936
  }
9694
- const artifactDir = resolve21(input.workspaceDir, "artifacts", input.taskId);
9695
- const reviewStatusPath = resolve21(artifactDir, "review-status.txt");
9696
- const taskResultPath = resolve21(artifactDir, "task-result.json");
9937
+ const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
9938
+ const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
9939
+ const taskResultPath = resolve22(artifactDir, "task-result.json");
9697
9940
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
9698
9941
  if (reviewStatus !== "APPROVED") {
9699
9942
  return { accepted: false, reason: null };
@@ -9730,12 +9973,12 @@ function resolveTaskRunRetryContext(input) {
9730
9973
  if (!input.taskId || !input.workspaceDir) {
9731
9974
  return { shouldRetry: false, failureDetail: null, nextPrompt: null };
9732
9975
  }
9733
- const artifactDir = resolve21(input.workspaceDir, "artifacts", input.taskId);
9734
- const reviewStatePath = resolve21(artifactDir, "review-state.json");
9735
- const reviewFeedbackPath = resolve21(artifactDir, "review-feedback.md");
9736
- const reviewStatusPath = resolve21(artifactDir, "review-status.txt");
9737
- const failedApproachesPath = resolve21(input.workspaceDir, ".rig", "state", "failed_approaches.md");
9738
- const validationSummaryPath = resolve21(artifactDir, "validation-summary.json");
9976
+ const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
9977
+ const reviewStatePath = resolve22(artifactDir, "review-state.json");
9978
+ const reviewFeedbackPath = resolve22(artifactDir, "review-feedback.md");
9979
+ const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
9980
+ const failedApproachesPath = resolve22(input.workspaceDir, ".rig", "state", "failed_approaches.md");
9981
+ const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
9739
9982
  const reviewState = readJsonFile3(reviewStatePath, null);
9740
9983
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
9741
9984
  const reviewRejected = isTaskRunReviewRejected(reviewState);
@@ -9921,11 +10164,11 @@ function appendToolTimelineFromLog(input) {
9921
10164
  });
9922
10165
  }
9923
10166
  function readTaskRunReviewStatus(reviewStatusPath) {
9924
- if (!existsSync12(reviewStatusPath)) {
10167
+ if (!existsSync13(reviewStatusPath)) {
9925
10168
  return null;
9926
10169
  }
9927
10170
  try {
9928
- const status = readFileSync10(reviewStatusPath, "utf8").trim().toUpperCase();
10171
+ const status = readFileSync11(reviewStatusPath, "utf8").trim().toUpperCase();
9929
10172
  return status === "APPROVED" || status === "REJECTED" ? status : null;
9930
10173
  } catch {
9931
10174
  return null;
@@ -10139,15 +10382,15 @@ async function executeRigOwnedTaskRun(context, input) {
10139
10382
  const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
10140
10383
  const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
10141
10384
  const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
10142
- const planningArtifactPath = resolve21("artifacts", runtimeTaskId, "implementation-plan.md");
10385
+ const planningArtifactPath = resolve22("artifacts", runtimeTaskId, "implementation-plan.md");
10143
10386
  const persistedPlanning = {
10144
10387
  ...planningClassification,
10145
10388
  classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
10146
10389
  artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
10147
10390
  classifiedAt: new Date().toISOString()
10148
10391
  };
10149
- mkdirSync7(resolve21(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
10150
- writeFileSync6(resolve21(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
10392
+ mkdirSync8(resolve22(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
10393
+ writeFileSync7(resolve22(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
10151
10394
  `, "utf8");
10152
10395
  patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
10153
10396
  prompt = `${prompt}
@@ -10197,7 +10440,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
10197
10440
  let verificationStarted = false;
10198
10441
  let reviewStarted = false;
10199
10442
  let latestRuntimeWorkspace = resumeMode && typeof existingRunRecord?.worktreePath === "string" ? existingRunRecord.worktreePath : null;
10200
- let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve21(existingRunRecord.sessionPath, "..") : null;
10443
+ let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve22(existingRunRecord.sessionPath, "..") : null;
10201
10444
  let latestLogsDir = resumeMode && typeof existingRunRecord?.logRoot === "string" ? existingRunRecord.logRoot : null;
10202
10445
  let latestProviderCommand = null;
10203
10446
  let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
@@ -10283,10 +10526,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
10283
10526
  patchAuthorityRun(context.projectRoot, input.runId, {
10284
10527
  status: "running",
10285
10528
  worktreePath: latestRuntimeWorkspace,
10286
- artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve21(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
10529
+ artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve22(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
10287
10530
  logRoot: latestLogsDir,
10288
- sessionPath: latestSessionDir ? resolve21(latestSessionDir, "session.json") : null,
10289
- sessionLogPath: latestLogsDir ? resolve21(latestLogsDir, "agent-stdout.log") : null,
10531
+ sessionPath: latestSessionDir ? resolve22(latestSessionDir, "session.json") : null,
10532
+ sessionLogPath: latestLogsDir ? resolve22(latestLogsDir, "agent-stdout.log") : null,
10290
10533
  branch: runtimeId
10291
10534
  });
10292
10535
  if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
@@ -10294,8 +10537,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
10294
10537
  const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
10295
10538
  const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
10296
10539
  if (readyFile) {
10297
- mkdirSync7(resolve21(readyFile, ".."), { recursive: true });
10298
- writeFileSync6(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
10540
+ mkdirSync8(resolve22(readyFile, ".."), { recursive: true });
10541
+ writeFileSync7(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
10299
10542
  `, "utf8");
10300
10543
  }
10301
10544
  appendRunLog(context.projectRoot, input.runId, {
@@ -10679,7 +10922,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
10679
10922
  let acceptedArtifactObservedAt = null;
10680
10923
  let acceptedArtifactPollTimer = null;
10681
10924
  let acceptedArtifactKillTimer = null;
10682
- const attemptExit = await new Promise((resolve22) => {
10925
+ const attemptExit = await new Promise((resolve23) => {
10683
10926
  let settled = false;
10684
10927
  const settle = (result) => {
10685
10928
  if (settled)
@@ -10687,7 +10930,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
10687
10930
  settled = true;
10688
10931
  if (acceptedArtifactPollTimer)
10689
10932
  clearInterval(acceptedArtifactPollTimer);
10690
- resolve22(result);
10933
+ resolve23(result);
10691
10934
  };
10692
10935
  const pollAcceptedArtifacts = () => {
10693
10936
  const artifactState = readTaskRunAcceptedArtifactState({
@@ -10889,8 +11132,8 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
10889
11132
  }
10890
11133
  if (planningClassification.planningRequired) {
10891
11134
  const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
10892
- const expectedPlanPath = resolve21(planWorkspace, planningArtifactPath);
10893
- if (!existsSync12(expectedPlanPath)) {
11135
+ const expectedPlanPath = resolve22(planWorkspace, planningArtifactPath);
11136
+ if (!existsSync13(expectedPlanPath)) {
10894
11137
  const failedAt = new Date().toISOString();
10895
11138
  const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
10896
11139
  patchAuthorityRun(context.projectRoot, input.runId, {
@@ -11060,9 +11303,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
11060
11303
  });
11061
11304
  emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
11062
11305
  });
11063
- const exitCode = await new Promise((resolve22) => {
11064
- child.once("error", () => resolve22(1));
11065
- child.once("close", (code) => resolve22(code ?? 1));
11306
+ const exitCode = await new Promise((resolve23) => {
11307
+ child.once("error", () => resolve23(1));
11308
+ child.once("close", (code) => resolve23(code ?? 1));
11066
11309
  });
11067
11310
  for (const pendingLog of flushPendingClaudeToolUseLogs({
11068
11311
  runId: input.runId,
@@ -11204,8 +11447,8 @@ async function executeTest(context, args) {
11204
11447
 
11205
11448
  // packages/cli/src/commands/setup.ts
11206
11449
  init_runner();
11207
- import { existsSync as existsSync13, mkdirSync as mkdirSync8, readdirSync as readdirSync2, writeFileSync as writeFileSync7 } from "fs";
11208
- import { resolve as resolve22 } from "path";
11450
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, readdirSync as readdirSync2, writeFileSync as writeFileSync8 } from "fs";
11451
+ import { resolve as resolve23 } from "path";
11209
11452
  import { createPluginHost } from "@rig/core";
11210
11453
  import {
11211
11454
  isSupportedBunVersion as isSupportedBunVersion2,
@@ -11260,12 +11503,12 @@ function runSetupInit(projectRoot) {
11260
11503
  const stateDir = resolveControlPlaneHostStateDir(projectRoot);
11261
11504
  const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
11262
11505
  const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
11263
- mkdirSync8(stateDir, { recursive: true });
11264
- mkdirSync8(logsDir, { recursive: true });
11265
- mkdirSync8(artifactsDir, { recursive: true });
11266
- const failuresPath = resolve22(stateDir, "failed_approaches.md");
11267
- if (!existsSync13(failuresPath)) {
11268
- writeFileSync7(failuresPath, `# Failed Approaches
11506
+ mkdirSync9(stateDir, { recursive: true });
11507
+ mkdirSync9(logsDir, { recursive: true });
11508
+ mkdirSync9(artifactsDir, { recursive: true });
11509
+ const failuresPath = resolve23(stateDir, "failed_approaches.md");
11510
+ if (!existsSync14(failuresPath)) {
11511
+ writeFileSync8(failuresPath, `# Failed Approaches
11269
11512
 
11270
11513
  `, "utf-8");
11271
11514
  }
@@ -11282,18 +11525,18 @@ async function runSetupCheck(projectRoot) {
11282
11525
  }
11283
11526
  async function runSetupPreflight(projectRoot) {
11284
11527
  await runSetupCheck(projectRoot);
11285
- const validationRoot = resolve22(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
11286
- if (existsSync13(validationRoot)) {
11528
+ const validationRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
11529
+ if (existsSync14(validationRoot)) {
11287
11530
  const validators = readdirSync2(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
11288
11531
  for (const validator of validators) {
11289
- const script = resolve22(validationRoot, validator.name, "validate.sh");
11290
- if (existsSync13(script)) {
11532
+ const script = resolve23(validationRoot, validator.name, "validate.sh");
11533
+ if (existsSync14(script)) {
11291
11534
  console.log(`OK: validator script ${script}`);
11292
11535
  }
11293
11536
  }
11294
11537
  }
11295
- const hooksRoot = resolve22(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
11296
- if (existsSync13(hooksRoot)) {
11538
+ const hooksRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
11539
+ if (existsSync14(hooksRoot)) {
11297
11540
  const hooks = readdirSync2(hooksRoot).filter((name) => name.endsWith(".sh"));
11298
11541
  for (const hook of hooks) {
11299
11542
  console.log(`OK: hook ${hook}`);
@@ -11438,7 +11681,7 @@ var PROJECT_REQUIRED_GROUPS = new Set([
11438
11681
  ]);
11439
11682
  var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
11440
11683
  function hasInitializedRigProject(projectRoot) {
11441
- return RIG_CONFIG_FILENAMES.some((name) => existsSync14(resolve23(projectRoot, name))) || existsSync14(resolve23(projectRoot, ".rig"));
11684
+ return RIG_CONFIG_FILENAMES.some((name) => existsSync15(resolve24(projectRoot, name))) || existsSync15(resolve24(projectRoot, ".rig"));
11442
11685
  }
11443
11686
  function requireInitializedRigProject(context, group) {
11444
11687
  if (hasInitializedRigProject(context.projectRoot)) {
@@ -11464,6 +11707,7 @@ var GROUPS = new Set([
11464
11707
  "review",
11465
11708
  "git",
11466
11709
  "harness",
11710
+ "pi",
11467
11711
  "plugin",
11468
11712
  "queue",
11469
11713
  "agent",
@@ -11609,6 +11853,8 @@ async function executeGroup(context, group, args) {
11609
11853
  return executeGit(context, args);
11610
11854
  case "harness":
11611
11855
  return executeHarness(context, args);
11856
+ case "pi":
11857
+ return executePi(context, args);
11612
11858
  case "plugin":
11613
11859
  return executePlugin(context, args);
11614
11860
  case "queue":