@kynver-app/runtime 0.1.95 → 0.1.99

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -725,7 +725,7 @@ function shouldEnforceMemoryCostPackageGuardCli(scope, action) {
725
725
  }
726
726
 
727
727
  // src/config.ts
728
- import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync2 } from "node:fs";
728
+ import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync2 } from "node:fs";
729
729
  import { homedir as homedir5, totalmem } from "node:os";
730
730
  import path10 from "node:path";
731
731
 
@@ -803,6 +803,7 @@ function readMemAvailableBytes(meminfoText) {
803
803
 
804
804
  // src/resource-gate.ts
805
805
  import path9 from "node:path";
806
+ import { readFileSync as readFileSync9 } from "node:fs";
806
807
 
807
808
  // src/disk-gate.ts
808
809
  import { statfsSync as statfsSync2 } from "node:fs";
@@ -827,23 +828,23 @@ function isWslHost() {
827
828
  function observeWslHostDisk(options = {}) {
828
829
  const wsl = options.forceWsl === void 0 ? isWslHost() : options.forceWsl;
829
830
  if (!wsl) return null;
830
- const path69 = options.wslHostMount?.trim() || process.env.KYNVER_WSL_HOST_MOUNT?.trim() || DEFAULT_WSL_HOST_MOUNT;
831
+ const path71 = options.wslHostMount?.trim() || process.env.KYNVER_WSL_HOST_MOUNT?.trim() || DEFAULT_WSL_HOST_MOUNT;
831
832
  const warnBelowBytes = options.wslHostFreeWarnBytes ?? DEFAULT_WSL_HOST_WARN_FREE_BYTES;
832
833
  const criticalBelowBytes = options.wslHostFreeCriticalBytes ?? DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES;
833
834
  const statfs = options.statfs ?? statfsSync;
834
835
  let stats;
835
836
  try {
836
- stats = statfs(path69);
837
+ stats = statfs(path71);
837
838
  } catch (error) {
838
839
  return {
839
840
  ok: false,
840
- path: path69,
841
+ path: path71,
841
842
  freeBytes: 0,
842
843
  totalBytes: 0,
843
844
  usedPercent: 100,
844
845
  warnBelowBytes,
845
846
  criticalBelowBytes,
846
- reason: `Windows host disk probe failed at ${path69}: ${error.message}`,
847
+ reason: `Windows host disk probe failed at ${path71}: ${error.message}`,
847
848
  probeError: error.message
848
849
  };
849
850
  }
@@ -857,11 +858,11 @@ function observeWslHostDisk(options = {}) {
857
858
  let reason = null;
858
859
  if (!ok) {
859
860
  const tag = criticalFree ? "critical" : "warning";
860
- reason = `Windows host disk ${path69} at ${tag}: ${freeGiB} GiB free (<${(criticalFree ? criticalBelowBytes : warnBelowBytes) / 1024 / 1024 / 1024} GiB); WSL VHDX cannot grow safely. ${summarizeWslRecoverySteps()}`;
861
+ reason = `Windows host disk ${path71} at ${tag}: ${freeGiB} GiB free (<${(criticalFree ? criticalBelowBytes : warnBelowBytes) / 1024 / 1024 / 1024} GiB); WSL VHDX cannot grow safely. ${summarizeWslRecoverySteps()}`;
861
862
  }
862
863
  return {
863
864
  ok,
864
- path: path69,
865
+ path: path71,
865
866
  freeBytes,
866
867
  totalBytes,
867
868
  usedPercent,
@@ -881,12 +882,12 @@ var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
881
882
  var DEFAULT_MAX_USED_PERCENT = 80;
882
883
  var DEFAULT_HARD_MAX_USED_PERCENT = 90;
883
884
  function observeRunnerDiskGate(input = {}) {
884
- const path69 = input.diskPath?.trim() || "/";
885
+ const path71 = input.diskPath?.trim() || "/";
885
886
  const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
886
887
  const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
887
888
  const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
888
889
  const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
889
- const stats = statfsSync2(path69);
890
+ const stats = statfsSync2(path71);
890
891
  const freeBytes = Number(stats.bavail) * Number(stats.bsize);
891
892
  const totalBytes = Number(stats.blocks) * Number(stats.bsize);
892
893
  const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
@@ -909,7 +910,7 @@ function observeRunnerDiskGate(input = {}) {
909
910
  }
910
911
  return {
911
912
  ok,
912
- path: path69,
913
+ path: path71,
913
914
  freeBytes,
914
915
  totalBytes,
915
916
  usedPercent,
@@ -2336,11 +2337,29 @@ function computeAutoMaxWorkers(totalMemBytes, opts = {}) {
2336
2337
  function readAvailableMemBytes() {
2337
2338
  return readMemAvailableBytes();
2338
2339
  }
2340
+ function pidCommandLine(pid) {
2341
+ if (!pid || process.platform !== "linux") return null;
2342
+ try {
2343
+ return readFileSync9(`/proc/${pid}/cmdline`, "utf8").replace(/\0/g, " ");
2344
+ } catch {
2345
+ return null;
2346
+ }
2347
+ }
2348
+ function workerProcessMatchesRecord(worker) {
2349
+ if (!worker.pid || process.platform !== "linux") return true;
2350
+ const cmdline = pidCommandLine(worker.pid);
2351
+ if (!cmdline) return false;
2352
+ const probes = [worker.worktreePath, worker.workerDir, worker.heartbeatPath].filter(
2353
+ (value) => typeof value === "string" && value.trim().length > 0
2354
+ );
2355
+ return probes.some((probe) => cmdline.includes(probe));
2356
+ }
2339
2357
  function isActiveHarnessWorker(worker) {
2340
2358
  if (typeof worker.completionBlocker === "string" && worker.completionBlocker.trim()) {
2341
2359
  return false;
2342
2360
  }
2343
2361
  const status = computeWorkerStatus(worker);
2362
+ if (status.alive && !workerProcessMatchesRecord(worker)) return false;
2344
2363
  return status.alive && !status.finalResult && status.attention.state !== "done";
2345
2364
  }
2346
2365
  function countActiveWorkersForRun(run) {
@@ -2491,7 +2510,7 @@ var CREDENTIALS_FILE = path10.join(CONFIG_DIR, "credentials");
2491
2510
  function loadUserConfig() {
2492
2511
  if (!existsSync11(CONFIG_FILE)) return {};
2493
2512
  try {
2494
- return JSON.parse(readFileSync9(CONFIG_FILE, "utf8"));
2513
+ return JSON.parse(readFileSync10(CONFIG_FILE, "utf8"));
2495
2514
  } catch {
2496
2515
  return {};
2497
2516
  }
@@ -2568,7 +2587,7 @@ function resolveSetupWorkerConfig(existing, args, totalMemBytes = totalmem()) {
2568
2587
  function loadCredentialsFile() {
2569
2588
  if (!existsSync11(CREDENTIALS_FILE)) return {};
2570
2589
  try {
2571
- return JSON.parse(readFileSync9(CREDENTIALS_FILE, "utf8"));
2590
+ return JSON.parse(readFileSync10(CREDENTIALS_FILE, "utf8"));
2572
2591
  } catch {
2573
2592
  return {};
2574
2593
  }
@@ -2845,15 +2864,30 @@ async function withTimeout(fn) {
2845
2864
  clearTimeout(timeout);
2846
2865
  }
2847
2866
  }
2867
+ function callbackFetchError(error) {
2868
+ return {
2869
+ ok: false,
2870
+ status: 0,
2871
+ response: {
2872
+ error: error instanceof Error ? error.message : String(error),
2873
+ timeoutMs: callbackTimeoutMs()
2874
+ }
2875
+ };
2876
+ }
2848
2877
  async function postJson(url, secret, body) {
2849
- const res = await withTimeout(
2850
- (signal) => fetch(url, {
2851
- method: "POST",
2852
- headers: buildHarnessCallbackHeaders(secret),
2853
- body: JSON.stringify(body),
2854
- signal
2855
- })
2856
- );
2878
+ let res;
2879
+ try {
2880
+ res = await withTimeout(
2881
+ (signal) => fetch(url, {
2882
+ method: "POST",
2883
+ headers: buildHarnessCallbackHeaders(secret),
2884
+ body: JSON.stringify(body),
2885
+ signal
2886
+ })
2887
+ );
2888
+ } catch (error) {
2889
+ return callbackFetchError(error);
2890
+ }
2857
2891
  let response = null;
2858
2892
  try {
2859
2893
  response = await res.json();
@@ -2871,13 +2905,18 @@ async function postJsonWithCredentialRefresh(url, secret, body, opts) {
2871
2905
  return { ...retry, refreshedAuth: true };
2872
2906
  }
2873
2907
  async function getJson(url, secret) {
2874
- const res = await withTimeout(
2875
- (signal) => fetch(url, {
2876
- method: "GET",
2877
- headers: buildHarnessCallbackHeaders(secret),
2878
- signal
2879
- })
2880
- );
2908
+ let res;
2909
+ try {
2910
+ res = await withTimeout(
2911
+ (signal) => fetch(url, {
2912
+ method: "GET",
2913
+ headers: buildHarnessCallbackHeaders(secret),
2914
+ signal
2915
+ })
2916
+ );
2917
+ } catch (error) {
2918
+ return callbackFetchError(error);
2919
+ }
2881
2920
  let response = null;
2882
2921
  try {
2883
2922
  response = await res.json();
@@ -2887,41 +2926,6 @@ async function getJson(url, secret) {
2887
2926
  return { ok: res.ok, status: res.status, response };
2888
2927
  }
2889
2928
 
2890
- // src/dispatch-lane-normalization.ts
2891
- function trimLower(value) {
2892
- return (value ?? "").trim().toLowerCase();
2893
- }
2894
- function roleLaneToDispatchLane(roleLane) {
2895
- switch (trimLower(roleLane)) {
2896
- case "implementer":
2897
- case "repair_implementer":
2898
- case "plan_author":
2899
- case "runtime_verifier":
2900
- return "implementation";
2901
- case "plan_reviewer":
2902
- case "report_reviewer":
2903
- case "deep_reviewer":
2904
- return "review";
2905
- default:
2906
- return null;
2907
- }
2908
- }
2909
- function normalizeDispatchNextLaneFilter(raw) {
2910
- const key = trimLower(raw);
2911
- if (!key) return void 0;
2912
- if (key === "implementation" || key === "review" || key === "landing" || key === "any") {
2913
- return key;
2914
- }
2915
- const mapped = roleLaneToDispatchLane(key);
2916
- if (mapped) return mapped;
2917
- if (key === "implement" || key === "repair" || key === "coding") return "implementation";
2918
- if (key === "land" || key === "merge") return "landing";
2919
- return void 0;
2920
- }
2921
- function resolveDispatchNextLaneFilter(raw) {
2922
- return normalizeDispatchNextLaneFilter(raw) ?? "any";
2923
- }
2924
-
2925
2929
  // src/worker-persona-catalog.ts
2926
2930
  var WORKER_PERSONA_CATALOG = [
2927
2931
  {
@@ -3036,6 +3040,41 @@ function workerPersonaLandingSlugs() {
3036
3040
  );
3037
3041
  }
3038
3042
 
3043
+ // src/dispatch-lane-normalization.ts
3044
+ function trimLower(value) {
3045
+ return (value ?? "").trim().toLowerCase();
3046
+ }
3047
+ function roleLaneToDispatchLane(roleLane) {
3048
+ switch (trimLower(roleLane)) {
3049
+ case "implementer":
3050
+ case "repair_implementer":
3051
+ case "plan_author":
3052
+ case "runtime_verifier":
3053
+ return "implementation";
3054
+ case "plan_reviewer":
3055
+ case "report_reviewer":
3056
+ case "deep_reviewer":
3057
+ return "review";
3058
+ default:
3059
+ return null;
3060
+ }
3061
+ }
3062
+ function normalizeDispatchNextLaneFilter(raw) {
3063
+ const key = trimLower(raw);
3064
+ if (!key) return void 0;
3065
+ if (key === "implementation" || key === "review" || key === "landing" || key === "any") {
3066
+ return key;
3067
+ }
3068
+ const mapped = roleLaneToDispatchLane(key);
3069
+ if (mapped) return mapped;
3070
+ if (key === "implement" || key === "repair" || key === "coding") return "implementation";
3071
+ if (key === "land" || key === "merge") return "landing";
3072
+ return void 0;
3073
+ }
3074
+ function resolveDispatchNextLaneFilter(raw) {
3075
+ return normalizeDispatchNextLaneFilter(raw) ?? "any";
3076
+ }
3077
+
3039
3078
  // src/model-routing-task-enrich.ts
3040
3079
  function taskString(task, key) {
3041
3080
  const v = task[key];
@@ -3503,7 +3542,7 @@ function probeCursorOAuthBinding(nowIso = (/* @__PURE__ */ new Date()).toISOStri
3503
3542
  }
3504
3543
 
3505
3544
  // src/orchestration-providers/hermes-cli-adapter.ts
3506
- import { existsSync as existsSync16, readFileSync as readFileSync10 } from "node:fs";
3545
+ import { existsSync as existsSync16, readFileSync as readFileSync11 } from "node:fs";
3507
3546
  import { homedir as homedir10 } from "node:os";
3508
3547
  import path15 from "node:path";
3509
3548
  var PROFILE_ENV_KEYS = [
@@ -3519,7 +3558,7 @@ function hermesProfileEnvPath() {
3519
3558
  }
3520
3559
  function profileEnvKeyPresence(envPath) {
3521
3560
  try {
3522
- const text = readFileSync10(envPath, "utf8");
3561
+ const text = readFileSync11(envPath, "utf8");
3523
3562
  const present = [];
3524
3563
  for (const key of PROFILE_ENV_KEYS) {
3525
3564
  const re = new RegExp(`^${key}=`, "m");
@@ -4493,7 +4532,7 @@ function buildPrompt(input) {
4493
4532
  "Completion handoff (required): before you stop, ensure the harness records a final result \u2014 summarize outcome in your last message and append a heartbeat line with phase `complete`. If you leave uncommitted changes or committed work without a PR, the orchestrator blocks completion until a GitHub PR exists (or you discard/commit cleanly). One-off helper scripts must be removed (`kynver worker discard-disposable --path <file>`) or committed before completion \u2014 maintenance/board-drain workers are not exempt. Exiting with only dirty files and no PR routes to salvage review, not production review.",
4494
4533
  "PR-ready handoff: for substantial implementation work, commit, push, and open a GitHub PR (draft OK) on your branch before finishing \u2014 or rely on the harness to run `gh pr create` at completion when `gh` is authenticated.",
4495
4534
  "Expert review / production-review workers (Dalton/Lorentz, plan-review-task, scheduledJob reviewer children): do NOT open new implementation PRs \u2014 review the parent task's existing PR and record reviewVerdict in finalResult; landing-contract targetPrReconciliation does not apply.",
4496
- "Worker resource guard: do not run full monorepo verification (`npm run typecheck`, `npm run build`, or equivalent) from this worker lane unless an operator explicitly requests it. Use targeted checks for touched paths and rely on CI/operator lanes for heavy gates.",
4535
+ "Worker resource guard: do not run full monorepo verification (`npm run typecheck`, `npm run build`, or equivalent) from this worker lane unless an operator explicitly requests it. Use targeted checks for touched paths and rely on CI/operator lanes for heavy gates. When heavy verification is required, route through `node scripts/verify-pr-local.mjs` or `kynver harness verify` \u2014 they acquire the global heavy-verification lease so parallel workers do not launch simultaneous typechecks.",
4497
4536
  "npm publish boundary: do not run `npm publish`, do not republish `@kynver-app/*` packages, and do not block on an operator to publish. When you need newer runtime code than npm, use this repo checkout (`npm run kynver:build`, `npm run kynver`) and record evidence: packages/kynver-runtime/package.json version + git ref in your completion report.",
4498
4537
  "If verification fails (including OOM), append a heartbeat line immediately with the last command, failure reason, dirty-file status, commit/PR handoff state, and next action so recovery does not require log spelunking.",
4499
4538
  "Landing-wrapper cleanup on a git ref: use `node scripts/agent-os-land-pr-cleanup-verify.mjs --ref origin/main` (JSON, exit 0). Do not use `git show <ref>:scripts/agent-os-land-pr.mjs | rg \u2026` \u2014 ripgrep exit 1 when markers are absent is reported as a failed command in Telegram/status tooling.",
@@ -5369,8 +5408,8 @@ function dirtyPathsCoveredByDisposableRemoval(changedFiles, removed) {
5369
5408
  if (removed.length === 0) return false;
5370
5409
  const removedSet = new Set(removed.map((p) => normalizeRelativePath(p)));
5371
5410
  return material.every((line) => {
5372
- const path69 = normalizeRelativePath(pathFromGitStatusLine(line));
5373
- return removedSet.has(path69);
5411
+ const path71 = normalizeRelativePath(pathFromGitStatusLine(line));
5412
+ return removedSet.has(path71);
5374
5413
  });
5375
5414
  }
5376
5415
 
@@ -6678,7 +6717,7 @@ function collectRunActiveHarnessWorkers(runId) {
6678
6717
  path24.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
6679
6718
  void 0
6680
6719
  );
6681
- if (!worker?.taskId || !isPidAlive(worker.pid)) continue;
6720
+ if (!worker?.taskId || !workerProcessMatchesRecord(worker)) continue;
6682
6721
  out.push({
6683
6722
  runId: run.id,
6684
6723
  workerName: name,
@@ -6917,7 +6956,7 @@ function isTmpOnlyPath(filePath) {
6917
6956
  // src/plan-persist/outbox-store.ts
6918
6957
  import {
6919
6958
  existsSync as existsSync23,
6920
- readFileSync as readFileSync11,
6959
+ readFileSync as readFileSync12,
6921
6960
  renameSync,
6922
6961
  readdirSync as readdirSync5,
6923
6962
  writeFileSync as writeFileSync3,
@@ -6945,7 +6984,7 @@ function findOutboxByIdempotencyKey(key) {
6945
6984
  function readOutboxItem(jsonPath) {
6946
6985
  if (!existsSync23(jsonPath)) return null;
6947
6986
  try {
6948
- return JSON.parse(readFileSync11(jsonPath, "utf8"));
6987
+ return JSON.parse(readFileSync12(jsonPath, "utf8"));
6949
6988
  } catch {
6950
6989
  return null;
6951
6990
  }
@@ -6953,7 +6992,7 @@ function readOutboxItem(jsonPath) {
6953
6992
  function readOutboxBody(item) {
6954
6993
  const { outboxDir } = ensurePlanOutboxDirs();
6955
6994
  const bodyFile = path26.join(outboxDir, item.bodyPath);
6956
- return readFileSync11(bodyFile, "utf8");
6995
+ return readFileSync12(bodyFile, "utf8");
6957
6996
  }
6958
6997
  function writeOutboxItem(input, opts) {
6959
6998
  const { outboxDir } = ensurePlanOutboxDirs();
@@ -8263,7 +8302,7 @@ import { existsSync as existsSync29, mkdirSync as mkdirSync6 } from "node:fs";
8263
8302
  import path37 from "node:path";
8264
8303
 
8265
8304
  // src/run-list.ts
8266
- import { existsSync as existsSync28, readFileSync as readFileSync14 } from "node:fs";
8305
+ import { existsSync as existsSync28, readFileSync as readFileSync15 } from "node:fs";
8267
8306
  import path36 from "node:path";
8268
8307
 
8269
8308
  // src/stale-reconcile.ts
@@ -9034,7 +9073,7 @@ function reconcileRunsCli() {
9034
9073
  function heartbeatByteLength(heartbeatPath) {
9035
9074
  if (!heartbeatPath || !existsSync28(heartbeatPath)) return 0;
9036
9075
  try {
9037
- return readFileSync14(heartbeatPath, "utf8").trim().length;
9076
+ return readFileSync15(heartbeatPath, "utf8").trim().length;
9038
9077
  } catch {
9039
9078
  return 0;
9040
9079
  }
@@ -9544,11 +9583,11 @@ var LIVE_SKIP_REASONS = /* @__PURE__ */ new Set([
9544
9583
  function collectPreservedLivePaths(actions, skips) {
9545
9584
  const out = [];
9546
9585
  const seen = /* @__PURE__ */ new Set();
9547
- const push = (path69, reason, detail) => {
9548
- const key = `${path69}\0${reason}`;
9586
+ const push = (path71, reason, detail) => {
9587
+ const key = `${path71}\0${reason}`;
9549
9588
  if (seen.has(key) || out.length >= MAX_PRESERVED_LIVE_PATH_SAMPLES) return;
9550
9589
  seen.add(key);
9551
- out.push({ path: path69, reason, ...detail ? { detail } : {} });
9590
+ out.push({ path: path71, reason, ...detail ? { detail } : {} });
9552
9591
  };
9553
9592
  for (const skip2 of skips) {
9554
9593
  if (!LIVE_SKIP_REASONS.has(skip2.reason)) continue;
@@ -10899,7 +10938,7 @@ function isPipelineCleanupEnabled() {
10899
10938
  }
10900
10939
 
10901
10940
  // src/cli.ts
10902
- import { mkdirSync as mkdirSync8, realpathSync } from "node:fs";
10941
+ import { mkdirSync as mkdirSync10, realpathSync } from "node:fs";
10903
10942
  import { fileURLToPath as fileURLToPath5 } from "node:url";
10904
10943
 
10905
10944
  // src/discard-disposable.ts
@@ -11087,12 +11126,12 @@ async function fireKynverCronJob(input) {
11087
11126
  }
11088
11127
 
11089
11128
  // src/cron/cron-lock.ts
11090
- import { closeSync as closeSync6, existsSync as existsSync43, openSync as openSync6, readFileSync as readFileSync15, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
11129
+ import { closeSync as closeSync6, existsSync as existsSync43, openSync as openSync6, readFileSync as readFileSync16, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
11091
11130
  var STALE_LOCK_MS = 10 * 6e4;
11092
11131
  function readLockInfo(lockPath) {
11093
11132
  if (!existsSync43(lockPath)) return null;
11094
11133
  try {
11095
- const parsed = JSON.parse(readFileSync15(lockPath, "utf8"));
11134
+ const parsed = JSON.parse(readFileSync16(lockPath, "utf8"));
11096
11135
  if (typeof parsed.pid === "number" && typeof parsed.at === "string") return parsed;
11097
11136
  } catch {
11098
11137
  return null;
@@ -11881,17 +11920,17 @@ async function runDaemon(args) {
11881
11920
  idleStreak = 0;
11882
11921
  }
11883
11922
  const backoff = idleStreak >= MAX_IDLE_STREAK ? IDLE_INTERVAL_MS : intervalMs;
11884
- sleepMs(backoff);
11923
+ await sleepMs(backoff);
11885
11924
  } catch (error) {
11886
11925
  console.error(JSON.stringify({ event: "daemon_tick_error", error: error.message }));
11887
- sleepMs(intervalMs);
11926
+ await sleepMs(intervalMs);
11888
11927
  }
11889
11928
  }
11890
11929
  console.error(JSON.stringify({ event: "daemon_stop", runId, agentOsId }));
11891
11930
  }
11892
11931
 
11893
11932
  // src/plan-progress.ts
11894
- import path59 from "node:path";
11933
+ import path61 from "node:path";
11895
11934
 
11896
11935
  // src/bounded-build/constants.ts
11897
11936
  var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
@@ -12021,14 +12060,235 @@ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
12021
12060
  }
12022
12061
 
12023
12062
  // src/bounded-build/exec.ts
12063
+ import { spawnSync as spawnSync9 } from "node:child_process";
12064
+
12065
+ // src/heavy-verification/slot.ts
12066
+ import {
12067
+ closeSync as closeSync7,
12068
+ existsSync as existsSync44,
12069
+ mkdirSync as mkdirSync8,
12070
+ openSync as openSync7,
12071
+ readdirSync as readdirSync15,
12072
+ readFileSync as readFileSync17,
12073
+ unlinkSync as unlinkSync4,
12074
+ writeFileSync as writeFileSync5
12075
+ } from "node:fs";
12076
+ import path59 from "node:path";
12077
+
12078
+ // src/heavy-verification/paths.ts
12079
+ import { mkdirSync as mkdirSync7 } from "node:fs";
12080
+ import path58 from "node:path";
12081
+ function resolveHeavyVerificationRoot() {
12082
+ return path58.join(resolveKynverStateRoot(), "heavy-verification");
12083
+ }
12084
+ function heavyVerificationSlotsDir() {
12085
+ return path58.join(resolveHeavyVerificationRoot(), "slots");
12086
+ }
12087
+ function ensureHeavyVerificationDirs() {
12088
+ const dir = heavyVerificationSlotsDir();
12089
+ mkdirSync7(dir, { recursive: true });
12090
+ return dir;
12091
+ }
12092
+
12093
+ // src/heavy-verification/slot.ts
12094
+ var DEFAULT_HEAVY_VERIFICATION_STALE_MS = 2 * 60 * 6e4;
12095
+ var DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT = 1;
12096
+ function positiveInt5(value, fallback) {
12097
+ const n = Number(value);
12098
+ if (!Number.isFinite(n) || n <= 0) return fallback;
12099
+ return Math.floor(n);
12100
+ }
12101
+ function isHeavyVerificationGateSkipped() {
12102
+ const v = process.env.KYNVER_HEAVY_VERIFICATION_SKIP?.trim().toLowerCase();
12103
+ return v === "1" || v === "true" || v === "yes";
12104
+ }
12105
+ function resolveHeavyVerificationMaxConcurrent() {
12106
+ const env = process.env.KYNVER_HEAVY_VERIFICATION_MAX_CONCURRENT;
12107
+ if (env) return positiveInt5(env, DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT);
12108
+ return DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT;
12109
+ }
12110
+ function indexedSlotId(index) {
12111
+ return `slot-${index}`;
12112
+ }
12113
+ function slotFilePath(slotId, slotsDir = heavyVerificationSlotsDir()) {
12114
+ return path59.join(slotsDir, `${slotId}.json`);
12115
+ }
12116
+ function readSlotRecord(filePath) {
12117
+ if (!existsSync44(filePath)) return null;
12118
+ try {
12119
+ const parsed = JSON.parse(readFileSync17(filePath, "utf8"));
12120
+ if (typeof parsed.slotId === "string" && typeof parsed.pid === "number" && typeof parsed.acquiredAt === "string" && typeof parsed.command === "string") {
12121
+ return parsed;
12122
+ }
12123
+ } catch {
12124
+ return null;
12125
+ }
12126
+ return null;
12127
+ }
12128
+ function slotIsStale(record3, staleMs = DEFAULT_HEAVY_VERIFICATION_STALE_MS) {
12129
+ if (!record3) return true;
12130
+ if (!isPidAlive(record3.pid)) return true;
12131
+ const atMs = Date.parse(record3.acquiredAt);
12132
+ if (Number.isNaN(atMs)) return true;
12133
+ return Date.now() - atMs > staleMs;
12134
+ }
12135
+ function reclaimStaleSlot(filePath, staleMs) {
12136
+ const record3 = readSlotRecord(filePath);
12137
+ if (!slotIsStale(record3, staleMs)) return;
12138
+ try {
12139
+ unlinkSync4(filePath);
12140
+ } catch {
12141
+ }
12142
+ }
12143
+ function ensureSlotsDir(slotsDir) {
12144
+ mkdirSync8(slotsDir, { recursive: true });
12145
+ return slotsDir;
12146
+ }
12147
+ function reclaimStaleHeavyVerificationSlots(opts = {}) {
12148
+ const slotsDir = ensureSlotsDir(opts.slotsDir ?? ensureHeavyVerificationDirs());
12149
+ const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;
12150
+ let reclaimed = 0;
12151
+ for (const name of readdirSync15(slotsDir)) {
12152
+ if (!name.endsWith(".json")) continue;
12153
+ const filePath = path59.join(slotsDir, name);
12154
+ const before = existsSync44(filePath);
12155
+ reclaimStaleSlot(filePath, staleMs);
12156
+ if (before && !existsSync44(filePath)) reclaimed += 1;
12157
+ }
12158
+ return reclaimed;
12159
+ }
12160
+ function listActiveHeavyVerificationSlots(opts = {}) {
12161
+ const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();
12162
+ const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;
12163
+ reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });
12164
+ const active = [];
12165
+ for (const name of readdirSync15(slotsDir)) {
12166
+ if (!name.endsWith(".json")) continue;
12167
+ const record3 = readSlotRecord(path59.join(slotsDir, name));
12168
+ if (record3 && !slotIsStale(record3, staleMs)) active.push(record3);
12169
+ }
12170
+ return active;
12171
+ }
12172
+ function countActiveHeavyVerificationSlots(opts = {}) {
12173
+ return listActiveHeavyVerificationSlots(opts).length;
12174
+ }
12175
+ function tryAcquireHeavyVerificationSlot(command, opts = {}) {
12176
+ if (isHeavyVerificationGateSkipped()) {
12177
+ return {
12178
+ admitted: true,
12179
+ slotId: null,
12180
+ activeSlots: 0,
12181
+ maxSlots: resolveHeavyVerificationMaxConcurrent(),
12182
+ reason: null
12183
+ };
12184
+ }
12185
+ const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();
12186
+ const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;
12187
+ const maxSlots = opts.maxSlots ?? resolveHeavyVerificationMaxConcurrent();
12188
+ reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });
12189
+ for (let index = 0; index < maxSlots; index += 1) {
12190
+ const slotId = indexedSlotId(index);
12191
+ const filePath = slotFilePath(slotId, slotsDir);
12192
+ const existing = readSlotRecord(filePath);
12193
+ if (existing && slotIsStale(existing, staleMs)) {
12194
+ try {
12195
+ unlinkSync4(filePath);
12196
+ } catch {
12197
+ }
12198
+ } else if (existing && !slotIsStale(existing, staleMs)) {
12199
+ continue;
12200
+ }
12201
+ const record3 = {
12202
+ slotId,
12203
+ pid: process.pid,
12204
+ acquiredAt: (/* @__PURE__ */ new Date()).toISOString(),
12205
+ command
12206
+ };
12207
+ try {
12208
+ const fd = openSync7(filePath, "wx");
12209
+ writeFileSync5(fd, JSON.stringify(record3, null, 2), "utf8");
12210
+ closeSync7(fd);
12211
+ const activeSlots2 = countActiveHeavyVerificationSlots({ slotsDir, staleMs });
12212
+ return {
12213
+ admitted: true,
12214
+ slotId,
12215
+ activeSlots: activeSlots2,
12216
+ maxSlots,
12217
+ reason: null
12218
+ };
12219
+ } catch (err) {
12220
+ if (err.code === "EEXIST") {
12221
+ continue;
12222
+ }
12223
+ throw err;
12224
+ }
12225
+ }
12226
+ const activeSlots = countActiveHeavyVerificationSlots({ slotsDir, staleMs });
12227
+ return {
12228
+ admitted: false,
12229
+ slotId: null,
12230
+ activeSlots,
12231
+ maxSlots,
12232
+ reason: `heavy verification at capacity (${activeSlots}/${maxSlots} slots)`
12233
+ };
12234
+ }
12235
+ function releaseHeavyVerificationSlot(slotId, opts = {}) {
12236
+ if (!slotId) return;
12237
+ const filePath = slotFilePath(slotId, opts.slotsDir ?? heavyVerificationSlotsDir());
12238
+ try {
12239
+ unlinkSync4(filePath);
12240
+ } catch {
12241
+ }
12242
+ }
12243
+ function assessHeavyVerificationGate(command, opts = {}) {
12244
+ if (isHeavyVerificationGateSkipped()) {
12245
+ return {
12246
+ admitted: true,
12247
+ slotId: null,
12248
+ activeSlots: 0,
12249
+ maxSlots: resolveHeavyVerificationMaxConcurrent(),
12250
+ reason: null
12251
+ };
12252
+ }
12253
+ const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();
12254
+ const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;
12255
+ const maxSlots = opts.maxSlots ?? resolveHeavyVerificationMaxConcurrent();
12256
+ reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });
12257
+ const activeSlots = countActiveHeavyVerificationSlots({ slotsDir, staleMs });
12258
+ const admitted = activeSlots < maxSlots;
12259
+ return {
12260
+ admitted,
12261
+ slotId: null,
12262
+ activeSlots,
12263
+ maxSlots,
12264
+ reason: admitted ? null : `heavy verification at capacity (${activeSlots}/${maxSlots} slots); waiting for ${command}`
12265
+ };
12266
+ }
12267
+
12268
+ // src/heavy-verification/gate.ts
12024
12269
  import { spawnSync as spawnSync8 } from "node:child_process";
12270
+ function sleepMs3(ms) {
12271
+ if (ms <= 0) return;
12272
+ spawnSync8(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
12273
+ stdio: "ignore"
12274
+ });
12275
+ }
12276
+ function waitForHeavyVerificationSlot(command, timeoutMs, pollMs = 2e3, opts = {}) {
12277
+ const deadline = Date.now() + Math.max(0, timeoutMs);
12278
+ let verdict = tryAcquireHeavyVerificationSlot(command, opts);
12279
+ while (!verdict.admitted && Date.now() < deadline) {
12280
+ sleepMs3(Math.min(pollMs, deadline - Date.now()));
12281
+ verdict = tryAcquireHeavyVerificationSlot(command, opts);
12282
+ }
12283
+ return verdict;
12284
+ }
12025
12285
 
12026
12286
  // src/harness-worktree-build-guard.ts
12027
- import path58 from "node:path";
12287
+ import path60 from "node:path";
12028
12288
  function isPathUnderHarnessWorktree(cwd) {
12029
12289
  const worktreesDir = harnessWorktreesDir(resolveHarnessRoot());
12030
- const rel = path58.relative(worktreesDir, path58.resolve(cwd));
12031
- return rel.length > 0 && !rel.startsWith("..") && !path58.isAbsolute(rel);
12290
+ const rel = path60.relative(worktreesDir, path60.resolve(cwd));
12291
+ return rel.length > 0 && !rel.startsWith("..") && !path60.isAbsolute(rel);
12032
12292
  }
12033
12293
  function assessHarnessWorktreeBuildGuard(cwd) {
12034
12294
  if (!isPathUnderHarnessWorktree(cwd)) return { ok: true };
@@ -12052,7 +12312,7 @@ function envArgv(env) {
12052
12312
  return out;
12053
12313
  }
12054
12314
  function runSpawn(argv, opts) {
12055
- const res = spawnSync8(argv[0], argv.slice(1), {
12315
+ const res = spawnSync9(argv[0], argv.slice(1), {
12056
12316
  cwd: opts.cwd,
12057
12317
  env: opts.env,
12058
12318
  encoding: "utf8",
@@ -12068,8 +12328,25 @@ function runSpawn(argv, opts) {
12068
12328
  }
12069
12329
  function runBoundedBuildCheck(input) {
12070
12330
  const waitMs = input.waitForAdmissionMs ?? 6e5;
12331
+ const verificationGate = waitMs > 0 ? waitForHeavyVerificationSlot(input.command, waitMs) : tryAcquireOrAssessVerificationGate(input.command);
12332
+ if (!verificationGate.admitted) {
12333
+ return {
12334
+ ok: false,
12335
+ exitCode: 1,
12336
+ stdout: "",
12337
+ stderr: verificationGate.reason ?? "heavy verification gate denied",
12338
+ admitted: false,
12339
+ wrappedWithSystemd: false,
12340
+ nodeOptionsFlag: formatNodeOptionsFlag(),
12341
+ admission: assessBuildAdmission(),
12342
+ verificationGate,
12343
+ command: input.command
12344
+ };
12345
+ }
12346
+ const slotId = verificationGate.slotId;
12071
12347
  const admission = waitMs > 0 ? waitForBuildAdmission(waitMs) : assessBuildAdmission();
12072
12348
  if (!admission.admitted) {
12349
+ releaseHeavyVerificationSlot(slotId);
12073
12350
  return {
12074
12351
  ok: false,
12075
12352
  exitCode: 1,
@@ -12079,11 +12356,13 @@ function runBoundedBuildCheck(input) {
12079
12356
  wrappedWithSystemd: false,
12080
12357
  nodeOptionsFlag: formatNodeOptionsFlag(),
12081
12358
  admission,
12359
+ verificationGate,
12082
12360
  command: input.command
12083
12361
  };
12084
12362
  }
12085
12363
  const worktreeGuard = assessHarnessWorktreeBuildGuard(input.cwd);
12086
12364
  if (!worktreeGuard.ok) {
12365
+ releaseHeavyVerificationSlot(slotId);
12087
12366
  return {
12088
12367
  ok: false,
12089
12368
  exitCode: 1,
@@ -12093,6 +12372,7 @@ function runBoundedBuildCheck(input) {
12093
12372
  wrappedWithSystemd: false,
12094
12373
  nodeOptionsFlag: formatNodeOptionsFlag(),
12095
12374
  admission,
12375
+ verificationGate,
12096
12376
  command: input.command
12097
12377
  };
12098
12378
  }
@@ -12125,12 +12405,19 @@ function runBoundedBuildCheck(input) {
12125
12405
  wrappedWithSystemd: useSystemd,
12126
12406
  nodeOptionsFlag,
12127
12407
  admission,
12408
+ verificationGate,
12128
12409
  command: input.command
12129
12410
  };
12130
12411
  } finally {
12131
12412
  registerBuildEnd();
12413
+ releaseHeavyVerificationSlot(slotId);
12132
12414
  }
12133
12415
  }
12416
+ function tryAcquireOrAssessVerificationGate(command) {
12417
+ const acquired = waitForHeavyVerificationSlot(command, 0);
12418
+ if (acquired.admitted) return acquired;
12419
+ return { ...assessHeavyVerificationGate(command), slotId: null };
12420
+ }
12134
12421
 
12135
12422
  // src/harness-verify.ts
12136
12423
  var DEFAULT_HARNESS_VERIFY_COMMANDS = ["npm run typecheck", "npm run test"];
@@ -12213,7 +12500,7 @@ async function emitPlanProgress(args) {
12213
12500
  }
12214
12501
  function verifyPlanLocal(args) {
12215
12502
  const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
12216
- const cwd = path59.resolve(worktree);
12503
+ const cwd = path61.resolve(worktree);
12217
12504
  const summary = runHarnessVerifyCommands(cwd);
12218
12505
  const emitJson = args.json === true || args.json === "true";
12219
12506
  const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
@@ -12262,9 +12549,9 @@ async function verifyPlan(args) {
12262
12549
  }
12263
12550
 
12264
12551
  // src/harness-verify-cli.ts
12265
- import path60 from "node:path";
12552
+ import path62 from "node:path";
12266
12553
  function runHarnessVerifyCli(args) {
12267
- const cwd = path60.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
12554
+ const cwd = path62.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
12268
12555
  const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
12269
12556
  const commands = [];
12270
12557
  const rawCmd = args.command;
@@ -12292,6 +12579,7 @@ function runHarnessVerifyCli(args) {
12292
12579
  wrappedWithSystemd: s.result.wrappedWithSystemd,
12293
12580
  nodeOptionsFlag: s.result.nodeOptionsFlag,
12294
12581
  admission: s.result.admission,
12582
+ verificationGate: s.result.verificationGate,
12295
12583
  stderr: s.result.stderr.slice(0, 4e3)
12296
12584
  }))
12297
12585
  };
@@ -12308,7 +12596,7 @@ function runHarnessVerifyCli(args) {
12308
12596
  }
12309
12597
 
12310
12598
  // src/plan-persist-cli.ts
12311
- import { readFileSync as readFileSync16 } from "node:fs";
12599
+ import { readFileSync as readFileSync18 } from "node:fs";
12312
12600
  var OPERATIONS = ["create", "add_version", "update_metadata"];
12313
12601
  var FAILURE_KINDS = [
12314
12602
  "approval_guard",
@@ -12320,7 +12608,7 @@ var FAILURE_KINDS = [
12320
12608
  function readBodyArg(args) {
12321
12609
  const bodyFile = args.bodyFile ? String(args.bodyFile) : void 0;
12322
12610
  if (bodyFile) {
12323
- return { body: readFileSync16(bodyFile, "utf8"), bodyPathHint: bodyFile };
12611
+ return { body: readFileSync18(bodyFile, "utf8"), bodyPathHint: bodyFile };
12324
12612
  }
12325
12613
  const inline = args.body ? String(args.body) : void 0;
12326
12614
  if (inline) return { body: inline };
@@ -12700,7 +12988,7 @@ ${text.slice(0, 800)}`,
12700
12988
  }
12701
12989
 
12702
12990
  // src/monitor/monitor.service.ts
12703
- import path62 from "node:path";
12991
+ import path64 from "node:path";
12704
12992
 
12705
12993
  // src/monitor/monitor.classify.ts
12706
12994
  function classifyWorkerHealth(input) {
@@ -12752,19 +13040,19 @@ function classifyWorkerHealth(input) {
12752
13040
  }
12753
13041
 
12754
13042
  // src/monitor/monitor.store.ts
12755
- import { existsSync as existsSync44, mkdirSync as mkdirSync7, readdirSync as readdirSync15, unlinkSync as unlinkSync4 } from "node:fs";
12756
- import path61 from "node:path";
13043
+ import { existsSync as existsSync45, mkdirSync as mkdirSync9, readdirSync as readdirSync16, unlinkSync as unlinkSync5 } from "node:fs";
13044
+ import path63 from "node:path";
12757
13045
  function monitorsDir() {
12758
13046
  const { harnessRoot } = getHarnessPaths();
12759
- const dir = path61.join(harnessRoot, "monitors");
12760
- mkdirSync7(dir, { recursive: true });
13047
+ const dir = path63.join(harnessRoot, "monitors");
13048
+ mkdirSync9(dir, { recursive: true });
12761
13049
  return dir;
12762
13050
  }
12763
13051
  function monitorIdFor(runId, workerName) {
12764
13052
  return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
12765
13053
  }
12766
13054
  function monitorPath(monitorId) {
12767
- return path61.join(monitorsDir(), `${monitorId}.json`);
13055
+ return path63.join(monitorsDir(), `${monitorId}.json`);
12768
13056
  }
12769
13057
  function loadMonitorSession(monitorId) {
12770
13058
  return readJson(monitorPath(monitorId), void 0);
@@ -12774,18 +13062,18 @@ function saveMonitorSession(session) {
12774
13062
  }
12775
13063
  function deleteMonitorSession(monitorId) {
12776
13064
  const file = monitorPath(monitorId);
12777
- if (!existsSync44(file)) return false;
12778
- unlinkSync4(file);
13065
+ if (!existsSync45(file)) return false;
13066
+ unlinkSync5(file);
12779
13067
  return true;
12780
13068
  }
12781
13069
  function listMonitorSessions() {
12782
13070
  const dir = monitorsDir();
12783
- if (!existsSync44(dir)) return [];
13071
+ if (!existsSync45(dir)) return [];
12784
13072
  const entries = [];
12785
- for (const name of readdirSync15(dir)) {
13073
+ for (const name of readdirSync16(dir)) {
12786
13074
  if (!name.endsWith(".json")) continue;
12787
13075
  const session = readJson(
12788
- path61.join(dir, name),
13076
+ path63.join(dir, name),
12789
13077
  void 0
12790
13078
  );
12791
13079
  if (!session?.monitorId) continue;
@@ -12876,7 +13164,7 @@ async function fetchTaskLeasesForWorkers(input) {
12876
13164
  // src/monitor/monitor.service.ts
12877
13165
  function workerRecord2(runId, name) {
12878
13166
  return readJson(
12879
- path62.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
13167
+ path64.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
12880
13168
  void 0
12881
13169
  );
12882
13170
  }
@@ -13082,21 +13370,21 @@ async function runMonitorLoop(args) {
13082
13370
 
13083
13371
  // src/monitor/monitor-spawn.ts
13084
13372
  import { spawn as spawn6 } from "node:child_process";
13085
- import { closeSync as closeSync7, existsSync as existsSync45, openSync as openSync7 } from "node:fs";
13086
- import path63 from "node:path";
13373
+ import { closeSync as closeSync8, existsSync as existsSync46, openSync as openSync8 } from "node:fs";
13374
+ import path65 from "node:path";
13087
13375
  import { fileURLToPath as fileURLToPath4 } from "node:url";
13088
13376
  function resolveDefaultCliPath2() {
13089
- return path63.join(fileURLToPath4(new URL(".", import.meta.url)), "cli.js");
13377
+ return path65.join(fileURLToPath4(new URL(".", import.meta.url)), "cli.js");
13090
13378
  }
13091
13379
  function spawnMonitorSidecar(opts) {
13092
13380
  const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
13093
- if (!existsSync45(cliPath)) return void 0;
13381
+ if (!existsSync46(cliPath)) return void 0;
13094
13382
  const monitorId = monitorIdFor(opts.runId, opts.workerName);
13095
13383
  const { harnessRoot } = getHarnessPaths();
13096
- const logPath = path63.join(harnessRoot, "monitors", `${monitorId}.log`);
13384
+ const logPath = path65.join(harnessRoot, "monitors", `${monitorId}.log`);
13097
13385
  let logFd;
13098
13386
  try {
13099
- logFd = openSync7(logPath, "a");
13387
+ logFd = openSync8(logPath, "a");
13100
13388
  } catch {
13101
13389
  logFd = void 0;
13102
13390
  }
@@ -13136,7 +13424,7 @@ function spawnMonitorSidecar(opts) {
13136
13424
  env: process.env
13137
13425
  })
13138
13426
  );
13139
- if (logFd !== void 0) closeSync7(logFd);
13427
+ if (logFd !== void 0) closeSync8(logFd);
13140
13428
  child.unref();
13141
13429
  const session = {
13142
13430
  monitorId,
@@ -13153,7 +13441,7 @@ function spawnMonitorSidecar(opts) {
13153
13441
  } catch {
13154
13442
  if (logFd !== void 0) {
13155
13443
  try {
13156
- closeSync7(logFd);
13444
+ closeSync8(logFd);
13157
13445
  } catch {
13158
13446
  }
13159
13447
  }
@@ -13213,7 +13501,7 @@ async function monitorTickCli(args) {
13213
13501
  }
13214
13502
 
13215
13503
  // src/post-restart-unblock.ts
13216
- import path64 from "node:path";
13504
+ import path66 from "node:path";
13217
13505
  function skip(runId, worker, taskId, agentOsId, leaseOwner, reason) {
13218
13506
  return { runId, worker, taskId, agentOsId, leaseOwner, action: "skipped", reason };
13219
13507
  }
@@ -13226,7 +13514,7 @@ async function postRestartUnblock(args) {
13226
13514
  const errors = [];
13227
13515
  for (const run of listRunRecords()) {
13228
13516
  for (const name of Object.keys(run.workers ?? {})) {
13229
- const workerPath = path64.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json");
13517
+ const workerPath = path66.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json");
13230
13518
  const worker = readJson(workerPath, void 0);
13231
13519
  if (!worker) {
13232
13520
  skipped.push(skip(run.id, name, "", "", "", "worker.json missing"));
@@ -13338,9 +13626,9 @@ async function postRestartUnblockCli(args) {
13338
13626
  }
13339
13627
 
13340
13628
  // src/default-repo-cli.ts
13341
- import path65 from "node:path";
13629
+ import path67 from "node:path";
13342
13630
  import { homedir as homedir15 } from "node:os";
13343
- var CONFIG_FILE2 = path65.join(homedir15(), ".kynver", "config.json");
13631
+ var CONFIG_FILE2 = path67.join(homedir15(), ".kynver", "config.json");
13344
13632
  function ensureDefaultRepo(opts) {
13345
13633
  const existing = loadUserConfig();
13346
13634
  const resolved = resolveDefaultRepo({ ...opts, config: existing });
@@ -13421,16 +13709,16 @@ function summarizeResolvedDefaultRepo(resolved) {
13421
13709
  }
13422
13710
 
13423
13711
  // src/doctor/runtime-takeover.ts
13424
- import path67 from "node:path";
13712
+ import path69 from "node:path";
13425
13713
 
13426
13714
  // src/doctor/runtime-takeover.probes.ts
13427
- import { accessSync, constants, existsSync as existsSync46, readFileSync as readFileSync17 } from "node:fs";
13715
+ import { accessSync, constants, existsSync as existsSync47, readFileSync as readFileSync19 } from "node:fs";
13428
13716
  import { homedir as homedir16 } from "node:os";
13429
- import path66 from "node:path";
13430
- import { spawnSync as spawnSync9 } from "node:child_process";
13717
+ import path68 from "node:path";
13718
+ import { spawnSync as spawnSync10 } from "node:child_process";
13431
13719
  function captureCommand(bin, args) {
13432
13720
  try {
13433
- const res = spawnSync9(bin, args, { encoding: "utf8" });
13721
+ const res = spawnSync10(bin, args, { encoding: "utf8" });
13434
13722
  const stdout = (res.stdout || "").trim();
13435
13723
  const stderr = (res.stderr || "").trim();
13436
13724
  const ok = res.status === 0;
@@ -13455,7 +13743,7 @@ function tokenPrefix(token) {
13455
13743
  return trimmed.length <= 12 ? `${trimmed}\u2026` : `${trimmed.slice(0, 12)}\u2026`;
13456
13744
  }
13457
13745
  function isWritable(target) {
13458
- if (!existsSync46(target)) return false;
13746
+ if (!existsSync47(target)) return false;
13459
13747
  try {
13460
13748
  accessSync(target, constants.W_OK);
13461
13749
  return true;
@@ -13468,15 +13756,15 @@ var defaultRuntimeTakeoverProbes = {
13468
13756
  commandOnPath: (bin) => captureCommand(process.platform === "win32" ? "where" : "which", [bin]),
13469
13757
  kynverVersion: (bin) => captureCommand(bin, ["--version"]),
13470
13758
  loadConfig: () => loadUserConfig(),
13471
- configFilePath: () => path66.join(homedir16(), ".kynver", "config.json"),
13472
- credentialsFilePath: () => path66.join(homedir16(), ".kynver", "credentials"),
13759
+ configFilePath: () => path68.join(homedir16(), ".kynver", "config.json"),
13760
+ credentialsFilePath: () => path68.join(homedir16(), ".kynver", "credentials"),
13473
13761
  readCredentials: () => {
13474
- const credPath = path66.join(homedir16(), ".kynver", "credentials");
13475
- if (!existsSync46(credPath)) {
13762
+ const credPath = path68.join(homedir16(), ".kynver", "credentials");
13763
+ if (!existsSync47(credPath)) {
13476
13764
  return { hasApiKey: false };
13477
13765
  }
13478
13766
  try {
13479
- const parsed = JSON.parse(readFileSync17(credPath, "utf8"));
13767
+ const parsed = JSON.parse(readFileSync19(credPath, "utf8"));
13480
13768
  return {
13481
13769
  hasApiKey: Boolean(parsed.apiKey?.trim()),
13482
13770
  runnerTokenPrefix: tokenPrefix(parsed.runnerToken),
@@ -13506,8 +13794,8 @@ var defaultRuntimeTakeoverProbes = {
13506
13794
  })()
13507
13795
  }),
13508
13796
  harnessRoot: () => resolveHarnessRoot(),
13509
- legacyOpenclawHarnessRoot: () => path66.join(homedir16(), ".openclaw", "harness"),
13510
- pathExists: (target) => existsSync46(target),
13797
+ legacyOpenclawHarnessRoot: () => path68.join(homedir16(), ".openclaw", "harness"),
13798
+ pathExists: (target) => existsSync47(target),
13511
13799
  pathWritable: (target) => isWritable(target)
13512
13800
  };
13513
13801
 
@@ -13913,8 +14201,8 @@ function assessVercelDeployEvidence(probes) {
13913
14201
  }
13914
14202
  function assessHarnessDirs(probes) {
13915
14203
  const harnessRoot = probes.harnessRoot();
13916
- const runsDir = path67.join(harnessRoot, "runs");
13917
- const worktreesDir = path67.join(harnessRoot, "worktrees");
14204
+ const runsDir = path69.join(harnessRoot, "runs");
14205
+ const worktreesDir = path69.join(harnessRoot, "worktrees");
13918
14206
  const displayHarnessRoot = redactHomePath(harnessRoot);
13919
14207
  const displayRunsDir = redactHomePath(runsDir);
13920
14208
  const displayWorktreesDir = redactHomePath(worktreesDir);
@@ -14178,9 +14466,9 @@ function applySchedulerCutoverAttestation(config) {
14178
14466
  }
14179
14467
 
14180
14468
  // src/scheduler-cutover-cli.ts
14181
- import path68 from "node:path";
14469
+ import path70 from "node:path";
14182
14470
  import { homedir as homedir17 } from "node:os";
14183
- var CONFIG_FILE3 = path68.join(homedir17(), ".kynver", "config.json");
14471
+ var CONFIG_FILE3 = path70.join(homedir17(), ".kynver", "config.json");
14184
14472
  function runSchedulerCutoverCheckCli(json = false) {
14185
14473
  const config = loadUserConfig();
14186
14474
  const report = assessSchedulerCutover(config);
@@ -14392,8 +14680,8 @@ async function main(argv = process.argv.slice(2)) {
14392
14680
  if (action && isHelpFlag(action) || rest.some(isHelpFlag)) return usage(0);
14393
14681
  const args = parseArgs(rest);
14394
14682
  const { runsDir, worktreesDir } = getPaths();
14395
- mkdirSync8(runsDir, { recursive: true });
14396
- mkdirSync8(worktreesDir, { recursive: true });
14683
+ mkdirSync10(runsDir, { recursive: true });
14684
+ mkdirSync10(worktreesDir, { recursive: true });
14397
14685
  if (shouldEnforceMemoryCostPackageGuardCli(scope, action)) {
14398
14686
  let repoRoot;
14399
14687
  const runId = args.run ? String(args.run).trim() : "";
@@ -14828,6 +15116,7 @@ export {
14828
15116
  CODEX_DEFAULT_MODEL,
14829
15117
  DEFAULT_DISPATCH_LEASE_MS,
14830
15118
  DEFAULT_HARNESS_VERIFY_COMMANDS,
15119
+ DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT,
14831
15120
  DEFAULT_MAX_ACTIONS_PER_SWEEP,
14832
15121
  DEFAULT_NODE_MODULES_AGE_MS,
14833
15122
  DEFAULT_RUN_DIRECTORIES_AGE_MS,
@@ -14856,6 +15145,7 @@ export {
14856
15145
  assessAutoCompleteEligibility,
14857
15146
  assessBuildAdmission,
14858
15147
  assessExitedWorkerSalvage,
15148
+ assessHeavyVerificationGate,
14859
15149
  assessOrphanWorktreeSafety,
14860
15150
  assessPrHandoffRequirement,
14861
15151
  assessWorkerLanding,
@@ -14889,6 +15179,7 @@ export {
14889
15179
  completeWorker,
14890
15180
  computeAttention,
14891
15181
  computeWorkerStatus,
15182
+ countActiveHeavyVerificationSlots,
14892
15183
  createRun,
14893
15184
  defaultBoxId,
14894
15185
  deriveRunStatus,
@@ -14942,6 +15233,7 @@ export {
14942
15233
  isForbiddenWorkerEnvKey,
14943
15234
  isGeneratedHarnessPath,
14944
15235
  isHarnessRunMetadataPath,
15236
+ isHeavyVerificationGateSkipped,
14945
15237
  isInspectableVercelTarget,
14946
15238
  isKnownWorkerPersonaSlug,
14947
15239
  isKynverMonorepoRoot,
@@ -14956,6 +15248,7 @@ export {
14956
15248
  isWslHost,
14957
15249
  joinHarnessNotice,
14958
15250
  landingContractAttentionReason,
15251
+ listActiveHeavyVerificationSlots,
14959
15252
  listForbiddenWorkerEnvKeys,
14960
15253
  listMonitors,
14961
15254
  listOrchestrationProviderCapabilities,
@@ -14995,12 +15288,14 @@ export {
14995
15288
  providerCapableForRisk,
14996
15289
  readMemAvailableBytes,
14997
15290
  readProductionDbKeysFromEnvFile,
15291
+ reclaimStaleHeavyVerificationSlots,
14998
15292
  reconcileRunsCli,
14999
15293
  reconcileStaleWorkers,
15000
15294
  reconcileWorkerMetadata,
15001
15295
  reconcileWorkerMetadataCli,
15002
15296
  redactHarness,
15003
15297
  redactProviderErrorText,
15298
+ releaseHeavyVerificationSlot,
15004
15299
  remediateDefaultRepo,
15005
15300
  repairMissingRunMetadata,
15006
15301
  repairNestedRunsPath,
@@ -15012,6 +15307,7 @@ export {
15012
15307
  resolveConfiguredWorkerProvider,
15013
15308
  resolveDefaultRepo,
15014
15309
  resolveHarnessRoot,
15310
+ resolveHeavyVerificationMaxConcurrent,
15015
15311
  resolveOpenAiCodexRetryBudget,
15016
15312
  resolveOrchestrationPolicyMode,
15017
15313
  resolveOrchestrationRouting,
@@ -15049,12 +15345,14 @@ export {
15049
15345
  tailWorker,
15050
15346
  taskAllowsClaudeWorker,
15051
15347
  terminalFinalResultFromHeartbeat,
15348
+ tryAcquireHeavyVerificationSlot,
15052
15349
  usage,
15053
15350
  validateOwnedPaths,
15054
15351
  validateRepo,
15055
15352
  validateRunId,
15056
15353
  validateTailLines,
15057
15354
  validateWorkerName,
15355
+ waitForHeavyVerificationSlot,
15058
15356
  workerDirHasActiveRetentionSignals,
15059
15357
  workerPersonaLandingSlugs,
15060
15358
  workerPersonaReviewSlugs,