@h-rig/runtime 0.0.6-alpha.33 → 0.0.6-alpha.35

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 (25) hide show
  1. package/dist/bin/rig-agent-dispatch.js +518 -459
  2. package/dist/bin/rig-agent.js +431 -362
  3. package/dist/src/control-plane/agent-wrapper.js +523 -464
  4. package/dist/src/control-plane/harness-main.js +529 -459
  5. package/dist/src/control-plane/hooks/completion-verification.js +353 -283
  6. package/dist/src/control-plane/hooks/inject-context.js +158 -99
  7. package/dist/src/control-plane/hooks/submodule-branch.js +538 -479
  8. package/dist/src/control-plane/hooks/task-runtime-start.js +538 -479
  9. package/dist/src/control-plane/materialize-task-config.js +68 -8
  10. package/dist/src/control-plane/native/git-ops.js +11 -1
  11. package/dist/src/control-plane/native/harness-cli.js +514 -444
  12. package/dist/src/control-plane/native/task-ops.js +392 -322
  13. package/dist/src/control-plane/native/validator.js +159 -100
  14. package/dist/src/control-plane/native/verifier.js +227 -166
  15. package/dist/src/control-plane/pi-sessiond/bin.js +62 -0
  16. package/dist/src/control-plane/pi-sessiond/server.js +62 -0
  17. package/dist/src/control-plane/pi-sessiond/session-service.js +62 -0
  18. package/dist/src/control-plane/pi-settings-materializer.js +52 -0
  19. package/dist/src/control-plane/plugin-host-context.js +59 -0
  20. package/dist/src/control-plane/runtime/index.js +469 -410
  21. package/dist/src/control-plane/runtime/isolation/index.js +493 -434
  22. package/dist/src/control-plane/runtime/isolation.js +493 -434
  23. package/dist/src/control-plane/runtime/queue.js +411 -352
  24. package/dist/src/control-plane/tasks/source-lifecycle.js +87 -28
  25. package/package.json +8 -8
@@ -2,8 +2,8 @@
2
2
  // @bun
3
3
 
4
4
  // packages/runtime/src/control-plane/hooks/inject-context.ts
5
- import { existsSync as existsSync21, readFileSync as readFileSync13 } from "fs";
6
- import { resolve as resolve22 } from "path";
5
+ import { existsSync as existsSync23, readFileSync as readFileSync14 } from "fs";
6
+ import { resolve as resolve23 } from "path";
7
7
  import { resolveProjectRoot } from "@rig/hook-kit";
8
8
 
9
9
  // packages/runtime/src/control-plane/memory-sync/db.ts
@@ -1128,8 +1128,8 @@ async function loadReviewProfile(path) {
1128
1128
  }
1129
1129
 
1130
1130
  // packages/runtime/src/control-plane/native/repo-ops.ts
1131
- import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync12, readdirSync as readdirSync5, rmSync as rmSync5, writeFileSync as writeFileSync10 } from "fs";
1132
- import { basename as basename7, dirname as dirname11, resolve as resolve21 } from "path";
1131
+ import { existsSync as existsSync22, mkdirSync as mkdirSync13, readFileSync as readFileSync13, readdirSync as readdirSync5, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "fs";
1132
+ import { basename as basename7, dirname as dirname12, resolve as resolve22 } from "path";
1133
1133
 
1134
1134
  // packages/runtime/src/control-plane/state-sync/types.ts
1135
1135
  var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
@@ -1626,8 +1626,8 @@ function syncManagedRepo(projectRoot, repoId) {
1626
1626
  return { layout, headCommit };
1627
1627
  }
1628
1628
  // packages/runtime/src/control-plane/native/task-ops.ts
1629
- import { appendFileSync as appendFileSync2, existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
1630
- import { resolve as resolve20 } from "path";
1629
+ import { appendFileSync as appendFileSync2, existsSync as existsSync21, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
1630
+ import { resolve as resolve21 } from "path";
1631
1631
 
1632
1632
  // packages/runtime/src/build-time-config.ts
1633
1633
  function normalizeBuildConfig(value) {
@@ -2084,6 +2084,8 @@ function buildBrowserGuidanceLines(browser) {
2084
2084
  }
2085
2085
 
2086
2086
  // packages/runtime/src/control-plane/plugin-host-context.ts
2087
+ import { existsSync as existsSync15 } from "fs";
2088
+ import { resolve as resolvePath } from "path";
2087
2089
  import { createPluginHost } from "@rig/core";
2088
2090
  import { loadConfig } from "@rig/core/load-config";
2089
2091
 
@@ -2365,6 +2367,55 @@ async function materializeSkills(projectRoot, entries) {
2365
2367
  return written;
2366
2368
  }
2367
2369
 
2370
+ // packages/runtime/src/control-plane/pi-settings-materializer.ts
2371
+ import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
2372
+ import { dirname as dirname11, resolve as resolve15 } from "path";
2373
+ var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
2374
+ var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
2375
+ function readJson(path, fallback) {
2376
+ if (!existsSync14(path))
2377
+ return fallback;
2378
+ try {
2379
+ return JSON.parse(readFileSync7(path, "utf-8"));
2380
+ } catch {
2381
+ return fallback;
2382
+ }
2383
+ }
2384
+ function packageKey(entry) {
2385
+ if (typeof entry === "string")
2386
+ return entry;
2387
+ if (entry && typeof entry === "object" && typeof entry.source === "string") {
2388
+ return entry.source;
2389
+ }
2390
+ return JSON.stringify(entry);
2391
+ }
2392
+ function materializePiPackages(projectRoot, declaredPackages) {
2393
+ const settingsPath = resolve15(projectRoot, SETTINGS_RELATIVE_PATH);
2394
+ const managedRecordPath = resolve15(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
2395
+ const settings = readJson(settingsPath, {});
2396
+ const previouslyManaged = new Set(readJson(managedRecordPath, []));
2397
+ const existing = Array.isArray(settings.packages) ? settings.packages : [];
2398
+ const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
2399
+ const operatorKeys = new Set(operatorEntries.map(packageKey));
2400
+ const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
2401
+ const nextPackages = [...operatorEntries, ...managedToAdd];
2402
+ if (nextPackages.length > 0 || existsSync14(settingsPath)) {
2403
+ const nextSettings = { ...settings };
2404
+ if (nextPackages.length > 0) {
2405
+ nextSettings.packages = nextPackages;
2406
+ } else {
2407
+ delete nextSettings.packages;
2408
+ }
2409
+ mkdirSync11(dirname11(settingsPath), { recursive: true });
2410
+ writeFileSync7(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
2411
+ `, "utf-8");
2412
+ }
2413
+ mkdirSync11(dirname11(managedRecordPath), { recursive: true });
2414
+ writeFileSync7(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
2415
+ `, "utf-8");
2416
+ return { settingsPath, packages: managedToAdd };
2417
+ }
2418
+
2368
2419
  // packages/runtime/src/control-plane/plugin-host-context.ts
2369
2420
  async function buildPluginHostContext(projectRoot) {
2370
2421
  let config;
@@ -2412,6 +2463,14 @@ async function buildPluginHostContext(projectRoot) {
2412
2463
  } catch (err) {
2413
2464
  console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
2414
2465
  }
2466
+ try {
2467
+ const piPackages = config.runtime?.pi?.packages ?? [];
2468
+ if (piPackages.length > 0 || existsSync15(resolvePath(projectRoot, ".rig/state/pi-managed-packages.json"))) {
2469
+ materializePiPackages(projectRoot, piPackages);
2470
+ }
2471
+ } catch (err) {
2472
+ console.warn(`[plugin-host] Pi package materialization failed: ${err instanceof Error ? err.message : err}`);
2473
+ }
2415
2474
  return {
2416
2475
  config,
2417
2476
  pluginHost,
@@ -2425,12 +2484,12 @@ async function buildPluginHostContext(projectRoot) {
2425
2484
 
2426
2485
  // packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
2427
2486
  import { spawnSync } from "child_process";
2428
- import { existsSync as existsSync15, readFileSync as readFileSync8, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync7 } from "fs";
2429
- import { basename as basename5, join as join4, resolve as resolve16 } from "path";
2487
+ import { existsSync as existsSync17, readFileSync as readFileSync9, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync8 } from "fs";
2488
+ import { basename as basename5, join as join4, resolve as resolve17 } from "path";
2430
2489
 
2431
2490
  // packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
2432
- import { existsSync as existsSync14, readFileSync as readFileSync7 } from "fs";
2433
- import { resolve as resolve15 } from "path";
2491
+ import { existsSync as existsSync16, readFileSync as readFileSync8 } from "fs";
2492
+ import { resolve as resolve16 } from "path";
2434
2493
 
2435
2494
  // packages/runtime/src/control-plane/tasks/task-record-reader.ts
2436
2495
  async function findTaskById(reader, id) {
@@ -2453,7 +2512,7 @@ class LegacyTaskConfigReadError extends Error {
2453
2512
  }
2454
2513
  }
2455
2514
  function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
2456
- const configPath = options.configPath ?? resolve15(projectRoot, ".rig", "task-config.json");
2515
+ const configPath = options.configPath ?? resolve16(projectRoot, ".rig", "task-config.json");
2457
2516
  const reader = {
2458
2517
  async listTasks() {
2459
2518
  return readLegacyTaskRecords(projectRoot, configPath);
@@ -2464,8 +2523,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
2464
2523
  };
2465
2524
  return reader;
2466
2525
  }
2467
- function readLegacyTaskRecords(projectRoot, configPath = resolve15(projectRoot, ".rig", "task-config.json")) {
2468
- if (!existsSync14(configPath)) {
2526
+ function readLegacyTaskRecords(projectRoot, configPath = resolve16(projectRoot, ".rig", "task-config.json")) {
2527
+ if (!existsSync16(configPath)) {
2469
2528
  return [];
2470
2529
  }
2471
2530
  const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
@@ -2473,7 +2532,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve15(projectRoot,
2473
2532
  }
2474
2533
  function readLegacyTaskConfigJson(projectRoot, configPath) {
2475
2534
  try {
2476
- const parsed = JSON.parse(readFileSync7(configPath, "utf8"));
2535
+ const parsed = JSON.parse(readFileSync8(configPath, "utf8"));
2477
2536
  if (isPlainRecord(parsed)) {
2478
2537
  return parsed;
2479
2538
  }
@@ -2557,7 +2616,7 @@ function isPlainRecord(candidate) {
2557
2616
  var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
2558
2617
  var FILE_TASK_PATTERN = /\.(task\.)?json$/;
2559
2618
  function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
2560
- const configPath = options.configPath ?? resolve16(projectRoot, ".rig", "task-config.json");
2619
+ const configPath = options.configPath ?? resolve17(projectRoot, ".rig", "task-config.json");
2561
2620
  const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
2562
2621
  const spawnFn = options.spawn ?? spawnSync;
2563
2622
  const ghBinary = options.ghBinary ?? "gh";
@@ -2640,10 +2699,10 @@ function readMaterializedTaskMetadata(entry) {
2640
2699
  return metadata;
2641
2700
  }
2642
2701
  function readConfiguredFilesTaskSourcePath(projectRoot) {
2643
- const jsonPath = resolve16(projectRoot, "rig.config.json");
2644
- if (existsSync15(jsonPath)) {
2702
+ const jsonPath = resolve17(projectRoot, "rig.config.json");
2703
+ if (existsSync17(jsonPath)) {
2645
2704
  try {
2646
- const parsed = JSON.parse(readFileSync8(jsonPath, "utf8"));
2705
+ const parsed = JSON.parse(readFileSync9(jsonPath, "utf8"));
2647
2706
  if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
2648
2707
  const source = parsed.taskSource;
2649
2708
  return source.kind === "files" && typeof source.path === "string" ? source.path : null;
@@ -2652,12 +2711,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
2652
2711
  return null;
2653
2712
  }
2654
2713
  }
2655
- const tsPath = resolve16(projectRoot, "rig.config.ts");
2656
- if (!existsSync15(tsPath)) {
2714
+ const tsPath = resolve17(projectRoot, "rig.config.ts");
2715
+ if (!existsSync17(tsPath)) {
2657
2716
  return null;
2658
2717
  }
2659
2718
  try {
2660
- const source = readFileSync8(tsPath, "utf8");
2719
+ const source = readFileSync9(tsPath, "utf8");
2661
2720
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
2662
2721
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
2663
2722
  if (kind !== "files") {
@@ -2677,10 +2736,10 @@ function readRawTaskEntry(configPath, taskId) {
2677
2736
  return isPlainRecord2(entry) ? entry : null;
2678
2737
  }
2679
2738
  function readRawTaskConfig(configPath) {
2680
- if (!existsSync15(configPath)) {
2739
+ if (!existsSync17(configPath)) {
2681
2740
  return null;
2682
2741
  }
2683
- const parsed = JSON.parse(readFileSync8(configPath, "utf8"));
2742
+ const parsed = JSON.parse(readFileSync9(configPath, "utf8"));
2684
2743
  return isPlainRecord2(parsed) ? parsed : null;
2685
2744
  }
2686
2745
  function stripLegacyTaskConfigMetadata2(raw) {
@@ -2688,8 +2747,8 @@ function stripLegacyTaskConfigMetadata2(raw) {
2688
2747
  return tasks;
2689
2748
  }
2690
2749
  function listFileBackedTasks(projectRoot, sourcePath) {
2691
- const directory = resolve16(projectRoot, sourcePath);
2692
- if (!existsSync15(directory)) {
2750
+ const directory = resolve17(projectRoot, sourcePath);
2751
+ if (!existsSync17(directory)) {
2693
2752
  return [];
2694
2753
  }
2695
2754
  const tasks = [];
@@ -2704,11 +2763,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
2704
2763
  return tasks;
2705
2764
  }
2706
2765
  function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
2707
- const file = findFileBackedTaskFile(resolve16(projectRoot, sourcePath), taskId);
2766
+ const file = findFileBackedTaskFile(resolve17(projectRoot, sourcePath), taskId);
2708
2767
  if (!file) {
2709
2768
  return null;
2710
2769
  }
2711
- const raw = JSON.parse(readFileSync8(file, "utf8"));
2770
+ const raw = JSON.parse(readFileSync9(file, "utf8"));
2712
2771
  if (!isPlainRecord2(raw)) {
2713
2772
  return null;
2714
2773
  }
@@ -2721,7 +2780,7 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
2721
2780
  };
2722
2781
  }
2723
2782
  function findFileBackedTaskFile(directory, taskId) {
2724
- if (!existsSync15(directory)) {
2783
+ if (!existsSync17(directory)) {
2725
2784
  return null;
2726
2785
  }
2727
2786
  for (const name of readdirSync3(directory)) {
@@ -2731,7 +2790,7 @@ function findFileBackedTaskFile(directory, taskId) {
2731
2790
  try {
2732
2791
  if (!statSync3(file).isFile())
2733
2792
  continue;
2734
- const raw = JSON.parse(readFileSync8(file, "utf8"));
2793
+ const raw = JSON.parse(readFileSync9(file, "utf8"));
2735
2794
  const inferredId = basename5(file).replace(FILE_TASK_PATTERN, "");
2736
2795
  const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
2737
2796
  if (id === taskId) {
@@ -2891,20 +2950,20 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
2891
2950
  }
2892
2951
 
2893
2952
  // packages/runtime/src/control-plane/native/task-state.ts
2894
- import { existsSync as existsSync18, readFileSync as readFileSync10, readdirSync as readdirSync4, statSync as statSync4, writeFileSync as writeFileSync8 } from "fs";
2895
- import { basename as basename6, resolve as resolve19 } from "path";
2953
+ import { existsSync as existsSync20, readFileSync as readFileSync11, readdirSync as readdirSync4, statSync as statSync4, writeFileSync as writeFileSync9 } from "fs";
2954
+ import { basename as basename6, resolve as resolve20 } from "path";
2896
2955
  // packages/runtime/src/control-plane/state-sync/read.ts
2897
- import { existsSync as existsSync17, readFileSync as readFileSync9 } from "fs";
2898
- import { resolve as resolve18 } from "path";
2956
+ import { existsSync as existsSync19, readFileSync as readFileSync10 } from "fs";
2957
+ import { resolve as resolve19 } from "path";
2899
2958
 
2900
2959
  // packages/runtime/src/control-plane/state-sync/repo.ts
2901
- import { existsSync as existsSync16 } from "fs";
2902
- import { resolve as resolve17 } from "path";
2960
+ import { existsSync as existsSync18 } from "fs";
2961
+ import { resolve as resolve18 } from "path";
2903
2962
  function resolveTrackerRepoPath(projectRoot) {
2904
2963
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
2905
2964
  try {
2906
2965
  const layout = resolveMonorepoRepoLayout(projectRoot);
2907
- if (existsSync16(resolve17(layout.mirrorRoot, "HEAD"))) {
2966
+ if (existsSync18(resolve18(layout.mirrorRoot, "HEAD"))) {
2908
2967
  return layout.mirrorRoot;
2909
2968
  }
2910
2969
  } catch {}
@@ -2915,8 +2974,8 @@ function resolveTrackerRepoPath(projectRoot) {
2915
2974
  var DEFAULT_READ_DEPS = {
2916
2975
  fetchRef: nativeFetchRef,
2917
2976
  readBlobAtRef: nativeReadBlobAtRef,
2918
- exists: existsSync17,
2919
- readFile: (path) => readFileSync9(path, "utf8")
2977
+ exists: existsSync19,
2978
+ readFile: (path) => readFileSync10(path, "utf8")
2920
2979
  };
2921
2980
  function parseIssueStatus(rawStatus) {
2922
2981
  const normalized = normalizeTaskLifecycleStatus(rawStatus);
@@ -2997,12 +3056,12 @@ function shouldPreferLocalTrackerState(options) {
2997
3056
  if (runtimeContextPath) {
2998
3057
  return true;
2999
3058
  }
3000
- return existsSync17(resolve18(runtimeWorkspace, ".rig", "runtime-context.json"));
3059
+ return existsSync19(resolve19(runtimeWorkspace, ".rig", "runtime-context.json"));
3001
3060
  }
3002
3061
  function readLocalTrackerState(projectRoot, deps) {
3003
3062
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
3004
- const issuesPath = resolve18(monorepoRoot, ".beads", "issues.jsonl");
3005
- const taskStatePath = resolve18(monorepoRoot, ".beads", "task-state.json");
3063
+ const issuesPath = resolve19(monorepoRoot, ".beads", "issues.jsonl");
3064
+ const taskStatePath = resolve19(monorepoRoot, ".beads", "task-state.json");
3006
3065
  return projectSyncedTrackerSnapshot({
3007
3066
  source: "local",
3008
3067
  issuesBaseOid: null,
@@ -3064,7 +3123,7 @@ function readValidationDescriptions(projectRoot) {
3064
3123
  return readValidationDescriptionMap(raw);
3065
3124
  }
3066
3125
  function readSourceValidationDescriptions(projectRoot) {
3067
- const rootRaw = readJsonFile(resolve19(projectRoot, "rig", "task-config.json"), {});
3126
+ const rootRaw = readJsonFile(resolve20(projectRoot, "rig", "task-config.json"), {});
3068
3127
  const sourcePath = findSourceTaskConfigPath(projectRoot);
3069
3128
  const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
3070
3129
  const rootDescriptions = readValidationDescriptionMap(rootRaw);
@@ -3140,15 +3199,15 @@ function readValidationDescriptionsFromMeta(meta) {
3140
3199
  return meta.validation_descriptions;
3141
3200
  }
3142
3201
  function readLocalSourceTaskStateEnvelope(projectRoot) {
3143
- const taskStatePath = resolve19(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
3202
+ const taskStatePath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
3144
3203
  return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
3145
3204
  }
3146
3205
  function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
3147
- const issuesPath = resolve19(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
3148
- if (!existsSync18(issuesPath)) {
3206
+ const issuesPath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
3207
+ if (!existsSync20(issuesPath)) {
3149
3208
  return null;
3150
3209
  }
3151
- for (const line of readFileSync10(issuesPath, "utf8").split(/\r?\n/)) {
3210
+ for (const line of readFileSync11(issuesPath, "utf8").split(/\r?\n/)) {
3152
3211
  const trimmed = line.trim();
3153
3212
  if (!trimmed) {
3154
3213
  continue;
@@ -3173,25 +3232,25 @@ function inferTaskIdFromRuntimePath(path) {
3173
3232
  function artifactDirForId(projectRoot, id) {
3174
3233
  const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
3175
3234
  if (workspaceDir) {
3176
- const worktreeArtifacts = resolve19(workspaceDir, "artifacts", id);
3177
- if (existsSync18(worktreeArtifacts) || existsSync18(resolve19(workspaceDir, "artifacts"))) {
3235
+ const worktreeArtifacts = resolve20(workspaceDir, "artifacts", id);
3236
+ if (existsSync20(worktreeArtifacts) || existsSync20(resolve20(workspaceDir, "artifacts"))) {
3178
3237
  return worktreeArtifacts;
3179
3238
  }
3180
3239
  }
3181
3240
  try {
3182
3241
  const paths = resolveHarnessPaths(projectRoot);
3183
- return resolve19(paths.artifactsDir, id);
3242
+ return resolve20(paths.artifactsDir, id);
3184
3243
  } catch {
3185
- return resolve19(resolveMonorepoRoot2(projectRoot), "artifacts", id);
3244
+ return resolve20(resolveMonorepoRoot2(projectRoot), "artifacts", id);
3186
3245
  }
3187
3246
  }
3188
3247
  function resolveTaskConfigPath(projectRoot) {
3189
3248
  const paths = resolveHarnessPaths(projectRoot);
3190
- if (existsSync18(paths.taskConfigPath)) {
3249
+ if (existsSync20(paths.taskConfigPath)) {
3191
3250
  return paths.taskConfigPath;
3192
3251
  }
3193
3252
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
3194
- if (existsSync18(candidate)) {
3253
+ if (existsSync20(candidate)) {
3195
3254
  return candidate;
3196
3255
  }
3197
3256
  }
@@ -3199,7 +3258,7 @@ function resolveTaskConfigPath(projectRoot) {
3199
3258
  }
3200
3259
  function findSourceTaskConfigPath(projectRoot) {
3201
3260
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
3202
- if (existsSync18(candidate)) {
3261
+ if (existsSync20(candidate)) {
3203
3262
  return candidate;
3204
3263
  }
3205
3264
  }
@@ -3212,7 +3271,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
3212
3271
  const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
3213
3272
  if (sourcePath && synced.updated) {
3214
3273
  try {
3215
- writeFileSync8(sourcePath, `${JSON.stringify(synced.config, null, 2)}
3274
+ writeFileSync9(sourcePath, `${JSON.stringify(synced.config, null, 2)}
3216
3275
  `, "utf-8");
3217
3276
  } catch {}
3218
3277
  }
@@ -3264,12 +3323,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
3264
3323
  return !candidate.role;
3265
3324
  }
3266
3325
  function readSourceIssueRecords(projectRoot) {
3267
- const issuesPath = resolve19(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
3268
- if (!existsSync18(issuesPath)) {
3326
+ const issuesPath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
3327
+ if (!existsSync20(issuesPath)) {
3269
3328
  return [];
3270
3329
  }
3271
3330
  const records = [];
3272
- for (const line of readFileSync10(issuesPath, "utf-8").split(/\r?\n/)) {
3331
+ for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
3273
3332
  const trimmed = line.trim();
3274
3333
  if (!trimmed) {
3275
3334
  continue;
@@ -3325,19 +3384,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
3325
3384
  if (!sourcePath) {
3326
3385
  return {};
3327
3386
  }
3328
- const directory = resolve19(projectRoot, sourcePath);
3329
- if (!existsSync18(directory)) {
3387
+ const directory = resolve20(projectRoot, sourcePath);
3388
+ if (!existsSync20(directory)) {
3330
3389
  return {};
3331
3390
  }
3332
3391
  const config = {};
3333
3392
  for (const name of readdirSync4(directory)) {
3334
3393
  if (!FILE_TASK_PATTERN2.test(name))
3335
3394
  continue;
3336
- const file = resolve19(directory, name);
3395
+ const file = resolve20(directory, name);
3337
3396
  try {
3338
3397
  if (!statSync4(file).isFile())
3339
3398
  continue;
3340
- const raw = JSON.parse(readFileSync10(file, "utf8"));
3399
+ const raw = JSON.parse(readFileSync11(file, "utf8"));
3341
3400
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
3342
3401
  continue;
3343
3402
  const record = raw;
@@ -3379,10 +3438,10 @@ function firstStringList2(...candidates) {
3379
3438
  return [];
3380
3439
  }
3381
3440
  function readConfiguredFilesTaskSourcePath2(projectRoot) {
3382
- const jsonPath = resolve19(projectRoot, "rig.config.json");
3383
- if (existsSync18(jsonPath)) {
3441
+ const jsonPath = resolve20(projectRoot, "rig.config.json");
3442
+ if (existsSync20(jsonPath)) {
3384
3443
  try {
3385
- const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
3444
+ const parsed = JSON.parse(readFileSync11(jsonPath, "utf8"));
3386
3445
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3387
3446
  const taskSource = parsed.taskSource;
3388
3447
  if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
@@ -3394,12 +3453,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
3394
3453
  return null;
3395
3454
  }
3396
3455
  }
3397
- const tsPath = resolve19(projectRoot, "rig.config.ts");
3398
- if (!existsSync18(tsPath)) {
3456
+ const tsPath = resolve20(projectRoot, "rig.config.ts");
3457
+ if (!existsSync20(tsPath)) {
3399
3458
  return null;
3400
3459
  }
3401
3460
  try {
3402
- const source = readFileSync10(tsPath, "utf8");
3461
+ const source = readFileSync11(tsPath, "utf8");
3403
3462
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
3404
3463
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
3405
3464
  if (kind !== "files") {
@@ -3413,9 +3472,9 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
3413
3472
  function sourceTaskConfigCandidates(projectRoot) {
3414
3473
  const runtimeContext = loadRuntimeContextFromEnv();
3415
3474
  return [
3416
- runtimeContext?.monorepoMainRoot ? resolve19(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
3417
- process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve19(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
3418
- resolve19(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
3475
+ runtimeContext?.monorepoMainRoot ? resolve20(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
3476
+ process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve20(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
3477
+ resolve20(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
3419
3478
  ].filter(Boolean);
3420
3479
  }
3421
3480
 
@@ -3714,16 +3773,16 @@ async function taskDeps(projectRoot, taskId) {
3714
3773
  for (const dep of deps) {
3715
3774
  const artifactDir = artifactDirForId(projectRoot, dep);
3716
3775
  console.log(`=== ${dep} ===`);
3717
- if (!existsSync19(artifactDir)) {
3776
+ if (!existsSync21(artifactDir)) {
3718
3777
  console.log(` (no artifacts yet)
3719
3778
  `);
3720
3779
  continue;
3721
3780
  }
3722
- printArtifactSection(resolve20(artifactDir, "decision-log.md"), "--- Decisions ---");
3723
- printArtifactSection(resolve20(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
3724
- const changedFiles = resolve20(artifactDir, "changed-files.txt");
3725
- if (existsSync19(changedFiles)) {
3726
- const lines = readFileSync11(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
3781
+ printArtifactSection(resolve21(artifactDir, "decision-log.md"), "--- Decisions ---");
3782
+ printArtifactSection(resolve21(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
3783
+ const changedFiles = resolve21(artifactDir, "changed-files.txt");
3784
+ if (existsSync21(changedFiles)) {
3785
+ const lines = readFileSync12(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
3727
3786
  console.log(`--- Changed Files (${lines.length}) ---`);
3728
3787
  for (const line of lines) {
3729
3788
  console.log(line);
@@ -3824,12 +3883,12 @@ function printIndented(text) {
3824
3883
  }
3825
3884
  }
3826
3885
  function readLocalBeadsTasks(projectRoot) {
3827
- const issuesPath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
3828
- if (!existsSync19(issuesPath)) {
3886
+ const issuesPath = resolve21(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
3887
+ if (!existsSync21(issuesPath)) {
3829
3888
  return [];
3830
3889
  }
3831
3890
  const tasks = [];
3832
- for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
3891
+ for (const line of readFileSync12(issuesPath, "utf-8").split(/\r?\n/)) {
3833
3892
  const trimmed = line.trim();
3834
3893
  if (!trimmed) {
3835
3894
  continue;
@@ -3942,11 +4001,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
3942
4001
  return [...ids].sort();
3943
4002
  }
3944
4003
  function printArtifactSection(path, header) {
3945
- if (!existsSync19(path)) {
4004
+ if (!existsSync21(path)) {
3946
4005
  return;
3947
4006
  }
3948
4007
  console.log(header);
3949
- process.stdout.write(readFileSync11(path, "utf-8"));
4008
+ process.stdout.write(readFileSync12(path, "utf-8"));
3950
4009
  console.log("");
3951
4010
  }
3952
4011
 
@@ -3972,7 +4031,7 @@ function repoDiscover(projectRoot, taskId) {
3972
4031
  }
3973
4032
  function repoBaseline(projectRoot, refresh = false) {
3974
4033
  const paths = resolveRepoDiscoveryPaths(projectRoot);
3975
- if (!refresh && existsSync20(paths.baseRepoPinsPath)) {
4034
+ if (!refresh && existsSync22(paths.baseRepoPinsPath)) {
3976
4035
  const baseline = readJsonFile(paths.baseRepoPinsPath, { recorded_at: nowIso(), repos: {} });
3977
4036
  return baseline.repos || {};
3978
4037
  }
@@ -3986,8 +4045,8 @@ function repoBaseline(projectRoot, refresh = false) {
3986
4045
  }
3987
4046
  function persistBaselinePins(projectRoot, repos) {
3988
4047
  const paths = resolveRepoDiscoveryPaths(projectRoot);
3989
- mkdirSync12(resolve21(paths.baseRepoPinsPath, ".."), { recursive: true });
3990
- writeFileSync10(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
4048
+ mkdirSync13(resolve22(paths.baseRepoPinsPath, ".."), { recursive: true });
4049
+ writeFileSync11(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
3991
4050
  `, "utf-8");
3992
4051
  return repos;
3993
4052
  }
@@ -4059,28 +4118,28 @@ function readRepoDiscoveryTaskConfig(projectRoot) {
4059
4118
  function resolveRepoDiscoveryPaths(projectRoot) {
4060
4119
  const monorepoRoot = resolveMonorepoRepoLayout(projectRoot).checkoutRoot;
4061
4120
  const explicitHostProjectRoot = (process.env.RIG_HOST_PROJECT_ROOT || "").trim();
4062
- const normalizedProjectRoot = resolve21(projectRoot);
4121
+ const normalizedProjectRoot = resolve22(projectRoot);
4063
4122
  const hostProjectRoot = explicitHostProjectRoot && shouldUseHostProjectStateRoot(normalizedProjectRoot) ? explicitHostProjectRoot : normalizedProjectRoot;
4064
- const stateDir = resolve21(hostProjectRoot, ".rig", "state");
4123
+ const stateDir = resolve22(hostProjectRoot, ".rig", "state");
4065
4124
  return {
4066
4125
  monorepoRoot,
4067
- taskRepoCommitsPath: resolve21(stateDir, "task-repo-commits.json"),
4068
- baseRepoPinsPath: resolve21(stateDir, "base-repo-pins.json")
4126
+ taskRepoCommitsPath: resolve22(stateDir, "task-repo-commits.json"),
4127
+ baseRepoPinsPath: resolve22(stateDir, "base-repo-pins.json")
4069
4128
  };
4070
4129
  }
4071
4130
  function shouldUseHostProjectStateRoot(projectRoot) {
4072
4131
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
4073
- if (runtimeWorkspace && resolve21(runtimeWorkspace) === projectRoot) {
4132
+ if (runtimeWorkspace && resolve22(runtimeWorkspace) === projectRoot) {
4074
4133
  return true;
4075
4134
  }
4076
- return basename7(dirname11(projectRoot)) === ".worktrees";
4135
+ return basename7(dirname12(projectRoot)) === ".worktrees";
4077
4136
  }
4078
4137
  function readPinFromArtifact(projectRoot, depTask, repoKey) {
4079
- const snapshot = resolve21(artifactDirForId(projectRoot, depTask), "git-state.txt");
4080
- if (!existsSync20(snapshot)) {
4138
+ const snapshot = resolve22(artifactDirForId(projectRoot, depTask), "git-state.txt");
4139
+ if (!existsSync22(snapshot)) {
4081
4140
  return "";
4082
4141
  }
4083
- const content = readFileSync12(snapshot, "utf-8");
4142
+ const content = readFileSync13(snapshot, "utf-8");
4084
4143
  const chunk = content.split(/\r?\n/);
4085
4144
  let inSection = false;
4086
4145
  for (const line of chunk) {
@@ -4109,7 +4168,7 @@ function defaultMemoryQuery(taskId, runtimeContext) {
4109
4168
  async function printSharedMemorySection(taskId) {
4110
4169
  const runtimeContext = loadRuntimeContextFromEnv();
4111
4170
  const memory = runtimeContext?.memory;
4112
- if (!memory?.hydratedPath || !existsSync21(memory.hydratedPath)) {
4171
+ if (!memory?.hydratedPath || !existsSync23(memory.hydratedPath)) {
4113
4172
  return;
4114
4173
  }
4115
4174
  const db = await openMemoryDb(memory.hydratedPath);
@@ -4156,17 +4215,17 @@ async function main() {
4156
4215
  console.log("(no explicit/discovered task pins)");
4157
4216
  } else {
4158
4217
  for (const [key, expected] of Object.entries(pins)) {
4159
- const repoPath = key.startsWith("/") ? key : resolve22(projectRoot, key);
4218
+ const repoPath = key.startsWith("/") ? key : resolve23(projectRoot, key);
4160
4219
  let current = "missing";
4161
- if (existsSync21(resolve22(repoPath, ".git"))) {
4220
+ if (existsSync23(resolve23(repoPath, ".git"))) {
4162
4221
  current = runCapture(["git", "-C", repoPath, "rev-parse", "HEAD"], projectRoot).stdout.trim() || "unknown";
4163
4222
  }
4164
4223
  console.log(`${current === expected ? "OK " : "WARN"} ${key} expected ${expected} got ${current}`);
4165
4224
  }
4166
4225
  }
4167
- const failedPath = resolve22(resolveHarnessPaths(projectRoot).stateDir, "failed_approaches.md");
4168
- if (existsSync21(failedPath)) {
4169
- const lines = readFileSync13(failedPath, "utf-8").split(/\r?\n/);
4226
+ const failedPath = resolve23(resolveHarnessPaths(projectRoot).stateDir, "failed_approaches.md");
4227
+ if (existsSync23(failedPath)) {
4228
+ const lines = readFileSync14(failedPath, "utf-8").split(/\r?\n/);
4170
4229
  let printing = false;
4171
4230
  const failureLines = [];
4172
4231
  for (const line of lines) {