@kynver-app/runtime 0.1.92 → 0.1.95

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/cli.js CHANGED
@@ -315,7 +315,13 @@ function displayUserPath(value) {
315
315
  }
316
316
 
317
317
  // src/default-repo-discovery.ts
318
- var WELL_KNOWN_REPO_DIRS = ["Kynver", "repos/Kynver", "code/Kynver", "projects/Kynver"];
318
+ var WELL_KNOWN_REPO_DIRS = [
319
+ "Kynver",
320
+ "repos/Kynver",
321
+ "repos/kynver-source-main",
322
+ "code/Kynver",
323
+ "projects/Kynver"
324
+ ];
319
325
  function readPackageName(repoRoot) {
320
326
  const pkgPath = path3.join(repoRoot, "package.json");
321
327
  if (!existsSync2(pkgPath)) return null;
@@ -4069,14 +4075,15 @@ function buildPrompt(input) {
4069
4075
  input.planId ? `Active planId: ${input.planId}${input.taskId ? ` \xB7 taskId: ${input.taskId}` : ""}` : "No planId on this worker \u2014 still emit progress when you touch plan-scoped work."
4070
4076
  ];
4071
4077
  const mergeGateLines = compact ? [
4072
- "Merge-gate cost control: do not use Vercel previews/builds for PR verification. Run `node scripts/agent-os-pr-merge-gate.mjs --pr <url> --agent-os-id <id>` (or `verify-pr-local.mjs --from-pr` + POST pr-merge-gate/refresh) before any GitHub Actions run; request merge-gate only via refresh then POST pr-merge-gate/request-run (one Actions run per PR head unless human approves extra)."
4078
+ "Merge-gate cost control: do not use Vercel previews/builds for PR verification. Run `node scripts/agent-os-pr-merge-gate.mjs --pr <url> --agent-os-id <id>` (or `verify-pr-local.mjs --from-pr` + POST pr-merge-gate/refresh) before any GitHub Actions run; request merge-gate only via refresh then POST pr-merge-gate/request-run (one Actions run per PR head unless human approves extra). Per-PR Vercel preview builds are off by default \u2014 production deploy runs via release batch after merge."
4073
4079
  ] : [
4074
4080
  "GitHub Actions merge-gate cost control (Kynver/Hermes PRs):",
4075
4081
  "- Prefer local cached package verification (`node scripts/verify-pr-local.mjs --emit-json`) before GitHub Actions. Do not use Vercel previews/builds as PR evidence.",
4076
4082
  "- Do not push empty commits to re-trigger CI. One budgeted merge-gate Actions run per PR candidate (head SHA) unless a human approves extra.",
4077
4083
  "- Record evidence: POST `/api/agent-os/by-id/<agentOsId>/pr-merge-gate/refresh` with prUrl + local payloads.",
4078
4084
  "- Request the final Actions run only when local verification is green: POST `.../pr-merge-gate/request-run` (applies `merge-gate` label).",
4079
- "- Empty failed Actions jobs (no runner/steps/logs) are infra/quota \u2014 do not enter repair loops; escalate to operator."
4085
+ "- Empty failed Actions jobs (no runner/steps/logs) are infra/quota \u2014 do not enter repair loops; escalate to operator.",
4086
+ "- After merge, landed PRs accumulate into a release batch; run batch verification then manual Vercel production deploy from Command Center (release train). PR landing completes with: verification complete, awaiting release batch/deploy."
4080
4087
  ];
4081
4088
  const planArtifactLines = compact ? [
4082
4089
  "Plan artifacts: when authoring/revising docs/superpowers/plans/, open a GitHub PR early and iterate from that PR branch; do not leave the canonical plan only in the harness worktree."
@@ -7027,7 +7034,7 @@ async function dispatchRun(args) {
7027
7034
  runnerPresence,
7028
7035
  harnessBoardSnapshot: buildRunBoard(run.id),
7029
7036
  ...args.lane ? { lane: resolveDispatchNextLaneFilter(String(args.lane)) } : {},
7030
- executor: args.executor ? String(args.executor) : "harness",
7037
+ ...args.executor ? { executor: String(args.executor) } : {},
7031
7038
  ...args.diskPath ? { diskPath: String(args.diskPath) } : {},
7032
7039
  ...args.targetTaskId ? { targetTaskId: String(args.targetTaskId) } : {},
7033
7040
  ...!args.targetTaskId && args.targetTaskIds ? {
@@ -8793,7 +8800,7 @@ async function runKynverCronTick(opts = {}) {
8793
8800
  }
8794
8801
 
8795
8802
  // src/pipeline-tick.ts
8796
- import path54 from "node:path";
8803
+ import path55 from "node:path";
8797
8804
 
8798
8805
  // src/pipeline-dispatch.ts
8799
8806
  var RESERVED_REVIEW_STARTS = 1;
@@ -10683,7 +10690,192 @@ function isPipelineCleanupEnabled() {
10683
10690
  // src/installed-package-versions.ts
10684
10691
  import { readFile } from "node:fs/promises";
10685
10692
  import { homedir as homedir13 } from "node:os";
10693
+ import path54 from "node:path";
10694
+
10695
+ // src/memory-cost-package-version-guard.ts
10696
+ import { existsSync as existsSync40, readFileSync as readFileSync12 } from "node:fs";
10686
10697
  import path53 from "node:path";
10698
+ var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
10699
+ "@kynver-app/runtime": "0.1.83",
10700
+ "@kynver-app/openclaw-agent-os": "0.1.43",
10701
+ "@kynver-app/mcp-agent-os": "0.3.34"
10702
+ };
10703
+ var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
10704
+ MEMORY_COST_PACKAGE_MIN_VERSIONS
10705
+ );
10706
+ var DISPLAY_NAMES = {
10707
+ "@kynver-app/runtime": "Kynver runtime",
10708
+ "@kynver-app/openclaw-agent-os": "OpenClaw AgentOS plugin",
10709
+ "@kynver-app/mcp-agent-os": "AgentOS MCP server"
10710
+ };
10711
+ var REPO_PACKAGE_JSON_RELATIVE = {
10712
+ "@kynver-app/runtime": "packages/kynver-runtime/package.json",
10713
+ "@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
10714
+ "@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
10715
+ };
10716
+ function parseSemverParts(version) {
10717
+ const core = version.trim().split("-")[0]?.split("+")[0];
10718
+ if (!core) return null;
10719
+ const parts = core.split(".");
10720
+ if (parts.length < 1 || parts.length > 3) return null;
10721
+ const nums = parts.map((p) => Number.parseInt(p, 10));
10722
+ if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
10723
+ while (nums.length < 3) nums.push(0);
10724
+ return [nums[0], nums[1], nums[2]];
10725
+ }
10726
+ function compareSemver(a, b) {
10727
+ const pa = parseSemverParts(a);
10728
+ const pb = parseSemverParts(b);
10729
+ if (!pa || !pb) return 0;
10730
+ for (let i = 0; i < 3; i += 1) {
10731
+ if (pa[i] > pb[i]) return 1;
10732
+ if (pa[i] < pb[i]) return -1;
10733
+ }
10734
+ return 0;
10735
+ }
10736
+ function semverAtLeast(version, minimum) {
10737
+ return compareSemver(version, minimum) >= 0;
10738
+ }
10739
+ function maxSemver(versions) {
10740
+ let best = null;
10741
+ for (const version of versions) {
10742
+ if (!best || compareSemver(version, best) > 0) best = version;
10743
+ }
10744
+ return best;
10745
+ }
10746
+ function readPackageJsonVersion(packageJsonPath) {
10747
+ try {
10748
+ const parsed = JSON.parse(readFileSync12(packageJsonPath, "utf8"));
10749
+ return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
10750
+ } catch {
10751
+ return null;
10752
+ }
10753
+ }
10754
+ function resolveRepoRoot(cwd, explicitRepoRoot) {
10755
+ const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(
10756
+ (value) => Boolean(value?.trim())
10757
+ );
10758
+ for (const candidate of candidates) {
10759
+ const resolved = path53.resolve(candidate);
10760
+ if (existsSync40(path53.join(resolved, "packages/kynver-runtime/package.json")) && existsSync40(path53.join(resolved, "package.json"))) {
10761
+ return resolved;
10762
+ }
10763
+ }
10764
+ const discovered = discoverDefaultRepo({ cwd });
10765
+ return discovered?.repo ?? null;
10766
+ }
10767
+ function probeRepoPackageVersions(input = {}) {
10768
+ const cwd = input.cwd ?? process.cwd();
10769
+ const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
10770
+ if (!repoRoot) return {};
10771
+ const out = {};
10772
+ for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
10773
+ const packageJsonPath = path53.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
10774
+ const version = readPackageJsonVersion(packageJsonPath);
10775
+ if (!version) continue;
10776
+ out[packageName] = { version, source: "repo", path: packageJsonPath };
10777
+ }
10778
+ return out;
10779
+ }
10780
+ function repoSourceCommands(packageName) {
10781
+ if (packageName === "@kynver-app/runtime") {
10782
+ return ["npm run kynver:build", "npm run kynver"];
10783
+ }
10784
+ return [`npm run build -w ${packageName}`];
10785
+ }
10786
+ function buildRemediation(input) {
10787
+ const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;
10788
+ const lines = [];
10789
+ if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {
10790
+ lines.push(
10791
+ `Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join("; ")}.`
10792
+ );
10793
+ lines.push("Do not publish npm packages or wait on an operator release.");
10794
+ return lines;
10795
+ }
10796
+ if (effectiveVersion) {
10797
+ lines.push(
10798
+ `Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`
10799
+ );
10800
+ } else {
10801
+ lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);
10802
+ }
10803
+ if (packageName === "@kynver-app/runtime") {
10804
+ lines.push("Repo-source alternative: npm run kynver:build && npm run kynver");
10805
+ }
10806
+ if (effectiveSource === "installed" && repoVersion) {
10807
+ lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);
10808
+ }
10809
+ return lines;
10810
+ }
10811
+ function pickEffectiveCandidate(candidates) {
10812
+ if (candidates.length === 0) return { version: null, source: "unknown" };
10813
+ const best = maxSemver(candidates.map((candidate) => candidate.version));
10814
+ if (!best) return { version: null, source: "unknown" };
10815
+ const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
10816
+ return { version: winner.version, source: winner.source };
10817
+ }
10818
+ function evaluateMemoryCostPackageVersionGuard(input = {}) {
10819
+ const normalize2 = (value, fallbackSource) => {
10820
+ if (!value) return null;
10821
+ if (typeof value === "string") return { version: value, source: fallbackSource };
10822
+ return value;
10823
+ };
10824
+ const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
10825
+ const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
10826
+ const candidates = [];
10827
+ const installed = normalize2(input.installed?.[packageName], "installed");
10828
+ const repo = normalize2(input.repo?.[packageName], "repo");
10829
+ const self = normalize2(input.self?.[packageName], "self");
10830
+ if (installed) candidates.push(installed);
10831
+ if (repo) candidates.push(repo);
10832
+ if (self) candidates.push(self);
10833
+ const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
10834
+ const repoVersion = repo?.version ?? null;
10835
+ const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
10836
+ const remediation = ok2 ? [] : buildRemediation({
10837
+ packageName,
10838
+ minimumVersion,
10839
+ effectiveVersion,
10840
+ effectiveSource,
10841
+ repoVersion
10842
+ });
10843
+ const summary2 = ok2 ? `${DISPLAY_NAMES[packageName]} ${effectiveVersion} meets memory-cost minimum ${minimumVersion} (${effectiveSource}).` : `${DISPLAY_NAMES[packageName]} is below memory-cost minimum ${minimumVersion}` + (effectiveVersion ? ` (effective ${effectiveVersion} via ${effectiveSource})` : " (no version detected)") + ".";
10844
+ return {
10845
+ packageName,
10846
+ displayName: DISPLAY_NAMES[packageName],
10847
+ minimumVersion,
10848
+ effectiveVersion,
10849
+ effectiveSource,
10850
+ ok: ok2,
10851
+ summary: summary2,
10852
+ remediation
10853
+ };
10854
+ });
10855
+ const violations = packages.filter((row) => !row.ok);
10856
+ const ok = violations.length === 0;
10857
+ const summary = ok ? "All managed AgentOS packages meet memory-cost minimum versions." : `Memory-cost package guard blocked ${violations.length} stale package(s): ${violations.map((row) => `${row.packageName} < ${row.minimumVersion}`).join("; ")}.`;
10858
+ return { ok, summary, packages };
10859
+ }
10860
+ var MemoryCostPackageVersionGuardError = class extends Error {
10861
+ result;
10862
+ constructor(result) {
10863
+ const lines = [
10864
+ result.summary,
10865
+ ...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
10866
+ ];
10867
+ super(lines.join("\n"));
10868
+ this.name = "MemoryCostPackageVersionGuardError";
10869
+ this.result = result;
10870
+ }
10871
+ };
10872
+ function assertMemoryCostPackageVersionGuard(input = {}) {
10873
+ const result = evaluateMemoryCostPackageVersionGuard(input);
10874
+ if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
10875
+ return result;
10876
+ }
10877
+
10878
+ // src/installed-package-versions.ts
10687
10879
  var MANAGED_PACKAGES = [
10688
10880
  "@kynver-app/runtime",
10689
10881
  "@kynver-app/openclaw-agent-os",
@@ -10698,12 +10890,12 @@ function unique(values) {
10698
10890
  }
10699
10891
  function moduleRoots() {
10700
10892
  const home = homedir13();
10701
- const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path53.join(home, ".openclaw", "npm");
10702
- const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path53.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path53.join(home, ".npm-global", "lib", "node_modules"));
10893
+ const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path54.join(home, ".openclaw", "npm");
10894
+ const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path54.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path54.join(home, ".npm-global", "lib", "node_modules"));
10703
10895
  return unique([
10704
- path53.join(openClawPrefix, "lib", "node_modules"),
10705
- path53.join(openClawPrefix, "node_modules"),
10706
- npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path53.join(npmGlobalRoot, "lib", "node_modules")
10896
+ path54.join(openClawPrefix, "lib", "node_modules"),
10897
+ path54.join(openClawPrefix, "node_modules"),
10898
+ npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path54.join(npmGlobalRoot, "lib", "node_modules")
10707
10899
  ]);
10708
10900
  }
10709
10901
  async function readVersion(packageJsonPath) {
@@ -10714,16 +10906,31 @@ async function readVersion(packageJsonPath) {
10714
10906
  return null;
10715
10907
  }
10716
10908
  }
10717
- async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
10909
+ function installedPackageJsonCandidates(packageName) {
10718
10910
  const roots = moduleRoots();
10911
+ const seen = /* @__PURE__ */ new Set();
10912
+ const out = [];
10913
+ for (const root of roots) {
10914
+ const candidate = path54.join(root, packageName, "package.json");
10915
+ if (seen.has(candidate)) continue;
10916
+ seen.add(candidate);
10917
+ out.push(candidate);
10918
+ }
10919
+ return out;
10920
+ }
10921
+ async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
10719
10922
  const out = {};
10720
10923
  for (const packageName of MANAGED_PACKAGES) {
10721
- for (const root of roots) {
10722
- const packageJsonPath = path53.join(root, packageName, "package.json");
10924
+ let best = null;
10925
+ for (const packageJsonPath of installedPackageJsonCandidates(packageName)) {
10723
10926
  const version = await readVersion(packageJsonPath);
10724
10927
  if (!version) continue;
10725
- out[packageName] = { version, observedAt, path: packageJsonPath };
10726
- break;
10928
+ if (!best || compareSemver(version, best.version) > 0) {
10929
+ best = { version, path: packageJsonPath };
10930
+ }
10931
+ }
10932
+ if (best) {
10933
+ out[packageName] = { version: best.version, observedAt, path: best.path };
10727
10934
  }
10728
10935
  }
10729
10936
  return out;
@@ -10735,7 +10942,7 @@ async function completeFinishedWorkers(runId, args) {
10735
10942
  const outcomes = [];
10736
10943
  for (const name of Object.keys(run.workers || {})) {
10737
10944
  const worker = readJson(
10738
- path54.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
10945
+ path55.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
10739
10946
  void 0
10740
10947
  );
10741
10948
  if (!worker?.taskId || worker.localOnly) continue;
@@ -10949,7 +11156,7 @@ async function runDaemon(args) {
10949
11156
  }
10950
11157
 
10951
11158
  // src/plan-progress.ts
10952
- import path56 from "node:path";
11159
+ import path57 from "node:path";
10953
11160
 
10954
11161
  // src/bounded-build/constants.ts
10955
11162
  var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
@@ -11082,11 +11289,11 @@ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
11082
11289
  import { spawnSync as spawnSync7 } from "node:child_process";
11083
11290
 
11084
11291
  // src/harness-worktree-build-guard.ts
11085
- import path55 from "node:path";
11292
+ import path56 from "node:path";
11086
11293
  function isPathUnderHarnessWorktree(cwd) {
11087
11294
  const worktreesDir = harnessWorktreesDir(resolveHarnessRoot());
11088
- const rel = path55.relative(worktreesDir, path55.resolve(cwd));
11089
- return rel.length > 0 && !rel.startsWith("..") && !path55.isAbsolute(rel);
11295
+ const rel = path56.relative(worktreesDir, path56.resolve(cwd));
11296
+ return rel.length > 0 && !rel.startsWith("..") && !path56.isAbsolute(rel);
11090
11297
  }
11091
11298
  function assessHarnessWorktreeBuildGuard(cwd) {
11092
11299
  if (!isPathUnderHarnessWorktree(cwd)) return { ok: true };
@@ -11271,7 +11478,7 @@ async function emitPlanProgress(args) {
11271
11478
  }
11272
11479
  function verifyPlanLocal(args) {
11273
11480
  const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
11274
- const cwd = path56.resolve(worktree);
11481
+ const cwd = path57.resolve(worktree);
11275
11482
  const summary = runHarnessVerifyCommands(cwd);
11276
11483
  const emitJson = args.json === true || args.json === "true";
11277
11484
  const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
@@ -11320,9 +11527,9 @@ async function verifyPlan(args) {
11320
11527
  }
11321
11528
 
11322
11529
  // src/harness-verify-cli.ts
11323
- import path57 from "node:path";
11530
+ import path58 from "node:path";
11324
11531
  function runHarnessVerifyCli(args) {
11325
- const cwd = path57.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
11532
+ const cwd = path58.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
11326
11533
  const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
11327
11534
  const commands = [];
11328
11535
  const rawCmd = args.command;
@@ -11366,7 +11573,7 @@ function runHarnessVerifyCli(args) {
11366
11573
  }
11367
11574
 
11368
11575
  // src/plan-persist-cli.ts
11369
- import { readFileSync as readFileSync12 } from "node:fs";
11576
+ import { readFileSync as readFileSync13 } from "node:fs";
11370
11577
  var OPERATIONS = ["create", "add_version", "update_metadata"];
11371
11578
  var FAILURE_KINDS = [
11372
11579
  "approval_guard",
@@ -11378,7 +11585,7 @@ var FAILURE_KINDS = [
11378
11585
  function readBodyArg(args) {
11379
11586
  const bodyFile = args.bodyFile ? String(args.bodyFile) : void 0;
11380
11587
  if (bodyFile) {
11381
- return { body: readFileSync12(bodyFile, "utf8"), bodyPathHint: bodyFile };
11588
+ return { body: readFileSync13(bodyFile, "utf8"), bodyPathHint: bodyFile };
11382
11589
  }
11383
11590
  const inline = args.body ? String(args.body) : void 0;
11384
11591
  if (inline) return { body: inline };
@@ -11529,7 +11736,7 @@ function formatMonitorTickNotice(tick) {
11529
11736
  }
11530
11737
 
11531
11738
  // src/monitor/monitor.service.ts
11532
- import path59 from "node:path";
11739
+ import path60 from "node:path";
11533
11740
 
11534
11741
  // src/monitor/monitor.classify.ts
11535
11742
  function classifyWorkerHealth(input) {
@@ -11581,11 +11788,11 @@ function classifyWorkerHealth(input) {
11581
11788
  }
11582
11789
 
11583
11790
  // src/monitor/monitor.store.ts
11584
- import { existsSync as existsSync40, mkdirSync as mkdirSync7, readdirSync as readdirSync15, unlinkSync as unlinkSync4 } from "node:fs";
11585
- import path58 from "node:path";
11791
+ import { existsSync as existsSync41, mkdirSync as mkdirSync7, readdirSync as readdirSync15, unlinkSync as unlinkSync4 } from "node:fs";
11792
+ import path59 from "node:path";
11586
11793
  function monitorsDir() {
11587
11794
  const { harnessRoot } = getHarnessPaths();
11588
- const dir = path58.join(harnessRoot, "monitors");
11795
+ const dir = path59.join(harnessRoot, "monitors");
11589
11796
  mkdirSync7(dir, { recursive: true });
11590
11797
  return dir;
11591
11798
  }
@@ -11593,7 +11800,7 @@ function monitorIdFor(runId, workerName) {
11593
11800
  return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
11594
11801
  }
11595
11802
  function monitorPath(monitorId) {
11596
- return path58.join(monitorsDir(), `${monitorId}.json`);
11803
+ return path59.join(monitorsDir(), `${monitorId}.json`);
11597
11804
  }
11598
11805
  function loadMonitorSession(monitorId) {
11599
11806
  return readJson(monitorPath(monitorId), void 0);
@@ -11603,18 +11810,18 @@ function saveMonitorSession(session) {
11603
11810
  }
11604
11811
  function deleteMonitorSession(monitorId) {
11605
11812
  const file = monitorPath(monitorId);
11606
- if (!existsSync40(file)) return false;
11813
+ if (!existsSync41(file)) return false;
11607
11814
  unlinkSync4(file);
11608
11815
  return true;
11609
11816
  }
11610
11817
  function listMonitorSessions() {
11611
11818
  const dir = monitorsDir();
11612
- if (!existsSync40(dir)) return [];
11819
+ if (!existsSync41(dir)) return [];
11613
11820
  const entries = [];
11614
11821
  for (const name of readdirSync15(dir)) {
11615
11822
  if (!name.endsWith(".json")) continue;
11616
11823
  const session = readJson(
11617
- path58.join(dir, name),
11824
+ path59.join(dir, name),
11618
11825
  void 0
11619
11826
  );
11620
11827
  if (!session?.monitorId) continue;
@@ -11705,7 +11912,7 @@ async function fetchTaskLeasesForWorkers(input) {
11705
11912
  // src/monitor/monitor.service.ts
11706
11913
  function workerRecord2(runId, name) {
11707
11914
  return readJson(
11708
- path59.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
11915
+ path60.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
11709
11916
  void 0
11710
11917
  );
11711
11918
  }
@@ -11911,18 +12118,18 @@ async function runMonitorLoop(args) {
11911
12118
 
11912
12119
  // src/monitor/monitor-spawn.ts
11913
12120
  import { spawn as spawn6 } from "node:child_process";
11914
- import { closeSync as closeSync7, existsSync as existsSync41, openSync as openSync7 } from "node:fs";
11915
- import path60 from "node:path";
12121
+ import { closeSync as closeSync7, existsSync as existsSync42, openSync as openSync7 } from "node:fs";
12122
+ import path61 from "node:path";
11916
12123
  import { fileURLToPath as fileURLToPath3 } from "node:url";
11917
12124
  function resolveDefaultCliPath2() {
11918
- return path60.join(fileURLToPath3(new URL(".", import.meta.url)), "cli.js");
12125
+ return path61.join(fileURLToPath3(new URL(".", import.meta.url)), "cli.js");
11919
12126
  }
11920
12127
  function spawnMonitorSidecar(opts) {
11921
12128
  const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
11922
- if (!existsSync41(cliPath)) return void 0;
12129
+ if (!existsSync42(cliPath)) return void 0;
11923
12130
  const monitorId = monitorIdFor(opts.runId, opts.workerName);
11924
12131
  const { harnessRoot } = getHarnessPaths();
11925
- const logPath = path60.join(harnessRoot, "monitors", `${monitorId}.log`);
12132
+ const logPath = path61.join(harnessRoot, "monitors", `${monitorId}.log`);
11926
12133
  let logFd;
11927
12134
  try {
11928
12135
  logFd = openSync7(logPath, "a");
@@ -12042,13 +12249,13 @@ async function monitorTickCli(args) {
12042
12249
  }
12043
12250
 
12044
12251
  // src/package-version.ts
12045
- import { existsSync as existsSync42, readFileSync as readFileSync13 } from "node:fs";
12252
+ import { existsSync as existsSync43, readFileSync as readFileSync14 } from "node:fs";
12046
12253
  import { dirname, join } from "node:path";
12047
12254
  import { fileURLToPath as fileURLToPath4 } from "node:url";
12048
12255
  function resolvePackageRoot(moduleUrl) {
12049
12256
  let dir = dirname(fileURLToPath4(moduleUrl));
12050
12257
  for (let depth = 0; depth < 6; depth += 1) {
12051
- if (existsSync42(join(dir, "package.json"))) return dir;
12258
+ if (existsSync43(join(dir, "package.json"))) return dir;
12052
12259
  const parent = dirname(dir);
12053
12260
  if (parent === dir) break;
12054
12261
  dir = parent;
@@ -12057,7 +12264,7 @@ function resolvePackageRoot(moduleUrl) {
12057
12264
  }
12058
12265
  function readOwnPackageVersion(moduleUrl = import.meta.url) {
12059
12266
  const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
12060
- const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
12267
+ const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
12061
12268
  if (typeof pkg.version !== "string" || !pkg.version.trim()) {
12062
12269
  throw new Error(`Missing package.json version at ${pkgPath}`);
12063
12270
  }
@@ -12077,188 +12284,6 @@ function handleCliVersionFlag(argv, moduleUrl = import.meta.url, binName) {
12077
12284
  return true;
12078
12285
  }
12079
12286
 
12080
- // src/memory-cost-package-version-guard.ts
12081
- import { existsSync as existsSync43, readFileSync as readFileSync14 } from "node:fs";
12082
- import path61 from "node:path";
12083
- var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
12084
- "@kynver-app/runtime": "0.1.83",
12085
- "@kynver-app/openclaw-agent-os": "0.1.43",
12086
- "@kynver-app/mcp-agent-os": "0.3.34"
12087
- };
12088
- var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
12089
- MEMORY_COST_PACKAGE_MIN_VERSIONS
12090
- );
12091
- var DISPLAY_NAMES = {
12092
- "@kynver-app/runtime": "Kynver runtime",
12093
- "@kynver-app/openclaw-agent-os": "OpenClaw AgentOS plugin",
12094
- "@kynver-app/mcp-agent-os": "AgentOS MCP server"
12095
- };
12096
- var REPO_PACKAGE_JSON_RELATIVE = {
12097
- "@kynver-app/runtime": "packages/kynver-runtime/package.json",
12098
- "@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
12099
- "@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
12100
- };
12101
- function parseSemverParts(version) {
12102
- const core = version.trim().split("-")[0]?.split("+")[0];
12103
- if (!core) return null;
12104
- const parts = core.split(".");
12105
- if (parts.length < 1 || parts.length > 3) return null;
12106
- const nums = parts.map((p) => Number.parseInt(p, 10));
12107
- if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
12108
- while (nums.length < 3) nums.push(0);
12109
- return [nums[0], nums[1], nums[2]];
12110
- }
12111
- function compareSemver(a, b) {
12112
- const pa = parseSemverParts(a);
12113
- const pb = parseSemverParts(b);
12114
- if (!pa || !pb) return 0;
12115
- for (let i = 0; i < 3; i += 1) {
12116
- if (pa[i] > pb[i]) return 1;
12117
- if (pa[i] < pb[i]) return -1;
12118
- }
12119
- return 0;
12120
- }
12121
- function semverAtLeast(version, minimum) {
12122
- return compareSemver(version, minimum) >= 0;
12123
- }
12124
- function maxSemver(versions) {
12125
- let best = null;
12126
- for (const version of versions) {
12127
- if (!best || compareSemver(version, best) > 0) best = version;
12128
- }
12129
- return best;
12130
- }
12131
- function readPackageJsonVersion(packageJsonPath) {
12132
- try {
12133
- const parsed = JSON.parse(readFileSync14(packageJsonPath, "utf8"));
12134
- return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
12135
- } catch {
12136
- return null;
12137
- }
12138
- }
12139
- function resolveRepoRoot(cwd, explicitRepoRoot) {
12140
- const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(
12141
- (value) => Boolean(value?.trim())
12142
- );
12143
- for (const candidate of candidates) {
12144
- const resolved = path61.resolve(candidate);
12145
- if (existsSync43(path61.join(resolved, "packages/kynver-runtime/package.json")) && existsSync43(path61.join(resolved, "package.json"))) {
12146
- return resolved;
12147
- }
12148
- }
12149
- return null;
12150
- }
12151
- function probeRepoPackageVersions(input = {}) {
12152
- const cwd = input.cwd ?? process.cwd();
12153
- const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
12154
- if (!repoRoot) return {};
12155
- const out = {};
12156
- for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
12157
- const packageJsonPath = path61.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
12158
- const version = readPackageJsonVersion(packageJsonPath);
12159
- if (!version) continue;
12160
- out[packageName] = { version, source: "repo", path: packageJsonPath };
12161
- }
12162
- return out;
12163
- }
12164
- function repoSourceCommands(packageName) {
12165
- if (packageName === "@kynver-app/runtime") {
12166
- return ["npm run kynver:build", "npm run kynver"];
12167
- }
12168
- return [`npm run build -w ${packageName}`];
12169
- }
12170
- function buildRemediation(input) {
12171
- const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;
12172
- const lines = [];
12173
- if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {
12174
- lines.push(
12175
- `Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join("; ")}.`
12176
- );
12177
- lines.push("Do not publish npm packages or wait on an operator release.");
12178
- return lines;
12179
- }
12180
- if (effectiveVersion) {
12181
- lines.push(
12182
- `Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`
12183
- );
12184
- } else {
12185
- lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);
12186
- }
12187
- if (packageName === "@kynver-app/runtime") {
12188
- lines.push("Repo-source alternative: npm run kynver:build && npm run kynver");
12189
- }
12190
- if (effectiveSource === "installed" && repoVersion) {
12191
- lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);
12192
- }
12193
- return lines;
12194
- }
12195
- function pickEffectiveCandidate(candidates) {
12196
- if (candidates.length === 0) return { version: null, source: "unknown" };
12197
- const best = maxSemver(candidates.map((candidate) => candidate.version));
12198
- if (!best) return { version: null, source: "unknown" };
12199
- const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
12200
- return { version: winner.version, source: winner.source };
12201
- }
12202
- function evaluateMemoryCostPackageVersionGuard(input = {}) {
12203
- const normalize2 = (value, fallbackSource) => {
12204
- if (!value) return null;
12205
- if (typeof value === "string") return { version: value, source: fallbackSource };
12206
- return value;
12207
- };
12208
- const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
12209
- const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
12210
- const candidates = [];
12211
- const installed = normalize2(input.installed?.[packageName], "installed");
12212
- const repo = normalize2(input.repo?.[packageName], "repo");
12213
- const self = normalize2(input.self?.[packageName], "self");
12214
- if (installed) candidates.push(installed);
12215
- if (repo) candidates.push(repo);
12216
- if (self) candidates.push(self);
12217
- const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
12218
- const repoVersion = repo?.version ?? null;
12219
- const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
12220
- const remediation = ok2 ? [] : buildRemediation({
12221
- packageName,
12222
- minimumVersion,
12223
- effectiveVersion,
12224
- effectiveSource,
12225
- repoVersion
12226
- });
12227
- const summary2 = ok2 ? `${DISPLAY_NAMES[packageName]} ${effectiveVersion} meets memory-cost minimum ${minimumVersion} (${effectiveSource}).` : `${DISPLAY_NAMES[packageName]} is below memory-cost minimum ${minimumVersion}` + (effectiveVersion ? ` (effective ${effectiveVersion} via ${effectiveSource})` : " (no version detected)") + ".";
12228
- return {
12229
- packageName,
12230
- displayName: DISPLAY_NAMES[packageName],
12231
- minimumVersion,
12232
- effectiveVersion,
12233
- effectiveSource,
12234
- ok: ok2,
12235
- summary: summary2,
12236
- remediation
12237
- };
12238
- });
12239
- const violations = packages.filter((row) => !row.ok);
12240
- const ok = violations.length === 0;
12241
- const summary = ok ? "All managed AgentOS packages meet memory-cost minimum versions." : `Memory-cost package guard blocked ${violations.length} stale package(s): ${violations.map((row) => `${row.packageName} < ${row.minimumVersion}`).join("; ")}.`;
12242
- return { ok, summary, packages };
12243
- }
12244
- var MemoryCostPackageVersionGuardError = class extends Error {
12245
- result;
12246
- constructor(result) {
12247
- const lines = [
12248
- result.summary,
12249
- ...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
12250
- ];
12251
- super(lines.join("\n"));
12252
- this.name = "MemoryCostPackageVersionGuardError";
12253
- this.result = result;
12254
- }
12255
- };
12256
- function assertMemoryCostPackageVersionGuard(input = {}) {
12257
- const result = evaluateMemoryCostPackageVersionGuard(input);
12258
- if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
12259
- return result;
12260
- }
12261
-
12262
12287
  // src/memory-cost-package-version-guard-enforce.ts
12263
12288
  function installedVersionMap(observed) {
12264
12289
  const out = {};
@@ -12278,10 +12303,10 @@ async function buildMemoryCostPackageGuardInput(input = {}) {
12278
12303
  Promise.resolve(probeRepoPackageVersions({ cwd: input.cwd, repoRoot: input.repoRoot }))
12279
12304
  ]);
12280
12305
  const self = {};
12281
- if (input.selfPackageName && input.selfVersion) {
12306
+ const runtimeSelfVersion = input.selfPackageName === "@kynver-app/runtime" && input.selfVersion ? input.selfVersion : PACKAGE_VERSION;
12307
+ self["@kynver-app/runtime"] = { version: runtimeSelfVersion, source: "self" };
12308
+ if (input.selfPackageName && input.selfVersion && input.selfPackageName !== "@kynver-app/runtime") {
12282
12309
  self[input.selfPackageName] = { version: input.selfVersion, source: "self" };
12283
- } else {
12284
- self["@kynver-app/runtime"] = { version: PACKAGE_VERSION, source: "self" };
12285
12310
  }
12286
12311
  return {
12287
12312
  installed: installedVersionMap(installed),
@@ -12601,9 +12626,7 @@ var defaultRuntimeTakeoverProbes = {
12601
12626
  harnessRoot: () => resolveHarnessRoot(),
12602
12627
  legacyOpenclawHarnessRoot: () => path64.join(homedir15(), ".openclaw", "harness"),
12603
12628
  pathExists: (target) => existsSync44(target),
12604
- pathWritable: (target) => isWritable(target),
12605
- vercelVersion: () => captureCommand("vercel", ["--version"]),
12606
- vercelWhoami: () => captureCommand("vercel", ["whoami"])
12629
+ pathWritable: (target) => isWritable(target)
12607
12630
  };
12608
12631
 
12609
12632
  // src/doctor/runtime-takeover-scheduler.ts
@@ -12970,29 +12993,38 @@ function assessRunnerToken(probes) {
12970
12993
  ];
12971
12994
  return { id: "runner_token", label: "Runner token readiness", checks };
12972
12995
  }
12973
- function assessVercelCli(probes) {
12974
- const version = probes.vercelVersion();
12975
- const whoami = probes.vercelWhoami();
12976
- const installed = version.ok;
12996
+ function assessVercelDeployEvidence(probes) {
12997
+ const globalCli = probes.commandOnPath("vercel");
12998
+ const cliInstalled = globalCli.ok;
12999
+ const githubToken = Boolean(
13000
+ process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim()
13001
+ );
13002
+ const vercelToken = Boolean(process.env.VERCEL_TOKEN?.trim());
12977
13003
  return {
12978
- id: "vercel_cli",
12979
- label: "Vercel CLI",
13004
+ id: "vercel_deploy_evidence",
13005
+ label: "Vercel deploy evidence",
12980
13006
  checks: [
12981
13007
  check2({
12982
- id: "vercel_installed",
12983
- label: "Vercel CLI installed",
12984
- status: installed ? "pass" : "warn",
12985
- summary: installed ? version.stdout || "vercel CLI found" : version.error ?? "vercel not found on PATH",
12986
- remediation: installed ? void 0 : "Install Vercel CLI (`npm i -g vercel`) for deploy evidence and env pulls.",
12987
- details: { stderr: version.stderr || null }
13008
+ id: "vercel_global_cli_absent",
13009
+ label: "Global Vercel CLI not installed",
13010
+ status: cliInstalled ? "warn" : "pass",
13011
+ summary: cliInstalled ? `Global Vercel CLI found (${globalCli.stdout || "on PATH"}) \u2014 uninstall after operator approval` : "No global Vercel CLI on PATH",
13012
+ remediation: cliInstalled ? "Uninstall global Vercel CLI (`npm uninstall -g vercel`) \u2014 use GitHub commit status or scoped VERCEL_TOKEN + REST API instead." : void 0,
13013
+ details: { path: cliInstalled ? globalCli.stdout || null : null }
13014
+ }),
13015
+ check2({
13016
+ id: "github_token_for_vercel_status",
13017
+ label: "GitHub token for Vercel status",
13018
+ status: githubToken ? "pass" : "warn",
13019
+ summary: githubToken ? "GITHUB_TOKEN/GH_TOKEN present for GitHub Vercel StatusContext evidence" : "No GITHUB_TOKEN \u2014 merge-gate Vercel evidence requires GitHub commit status API",
13020
+ remediation: githubToken ? void 0 : "Export GITHUB_TOKEN (or GH_TOKEN) for PR head commit status lookups."
12988
13021
  }),
12989
13022
  check2({
12990
- id: "vercel_authenticated",
12991
- label: "Vercel CLI authenticated",
12992
- status: !installed ? "warn" : whoami.ok ? "pass" : "warn",
12993
- summary: !installed ? "Skipped \u2014 Vercel CLI not installed" : whoami.ok ? `Authenticated as ${whoami.stdout}` : whoami.stderr || whoami.error || "Not logged in",
12994
- remediation: installed && !whoami.ok ? "Run `vercel login` and link the Kynver project if needed." : void 0,
12995
- details: { account: whoami.ok ? whoami.stdout : null }
13023
+ id: "vercel_api_token_optional",
13024
+ label: "Vercel API token (optional fallback)",
13025
+ status: vercelToken ? "pass" : "warn",
13026
+ summary: vercelToken ? "VERCEL_TOKEN configured for optional REST API deployment lookup" : "VERCEL_TOKEN unset \u2014 GitHub status is the default path; API fallback disabled",
13027
+ remediation: vercelToken ? void 0 : "Set ephemeral/scoped VERCEL_TOKEN only when GitHub status is insufficient; avoid persistent ~/.vercel auth on runner hosts."
12996
13028
  })
12997
13029
  ]
12998
13030
  };
@@ -13131,7 +13163,7 @@ function assessRuntimeTakeoverReadiness(probes = defaultRuntimeTakeoverProbes) {
13131
13163
  assessCliPackage(probes),
13132
13164
  assessUserConfig(probes),
13133
13165
  assessRunnerToken(probes),
13134
- assessVercelCli(probes),
13166
+ assessVercelDeployEvidence(probes),
13135
13167
  assessHarnessDirs(probes),
13136
13168
  assessCallbackAuth(probes),
13137
13169
  assessOpenclawHotspots(probes)
@@ -13481,7 +13513,19 @@ async function main(argv = process.argv.slice(2)) {
13481
13513
  mkdirSync8(runsDir, { recursive: true });
13482
13514
  mkdirSync8(worktreesDir, { recursive: true });
13483
13515
  if (shouldEnforceMemoryCostPackageGuardCli(scope, action)) {
13484
- await enforceMemoryCostPackageGuardAtStartup();
13516
+ let repoRoot;
13517
+ const runId = args.run ? String(args.run).trim() : "";
13518
+ if (runId) {
13519
+ try {
13520
+ repoRoot = loadRun(runId).repo;
13521
+ } catch {
13522
+ repoRoot = void 0;
13523
+ }
13524
+ }
13525
+ await enforceMemoryCostPackageGuardAtStartup({
13526
+ repoRoot,
13527
+ cwd: repoRoot
13528
+ });
13485
13529
  }
13486
13530
  if (scope === "login") return void await runLogin(args);
13487
13531
  if (scope === "runner" && action === "credential") return void await mintRunnerCredential(args);