@kynver-app/runtime 0.1.112 → 0.1.116

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
@@ -1,51 +1,12 @@
1
- // src/package-version.ts
2
- import { existsSync, readFileSync } from "node:fs";
3
- import { dirname, join } from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- function resolvePackageRoot(moduleUrl) {
6
- let dir = dirname(fileURLToPath(moduleUrl));
7
- for (let depth = 0; depth < 6; depth += 1) {
8
- if (existsSync(join(dir, "package.json"))) return dir;
9
- const parent = dirname(dir);
10
- if (parent === dir) break;
11
- dir = parent;
12
- }
13
- throw new Error(`package.json not found above ${dirname(fileURLToPath(moduleUrl))}`);
14
- }
15
- function readOwnPackageVersion(moduleUrl = import.meta.url) {
16
- const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
17
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
18
- if (typeof pkg.version !== "string" || !pkg.version.trim()) {
19
- throw new Error(`Missing package.json version at ${pkgPath}`);
20
- }
21
- return pkg.version;
22
- }
23
- var PACKAGE_VERSION = readOwnPackageVersion();
24
- function wantsCliVersion(argv) {
25
- return argv.some((arg) => arg === "--version" || arg === "-v");
26
- }
27
- function printCliVersionAndExit(version, binName) {
28
- console.log(binName ? `${binName} ${version}` : version);
29
- process.exit(0);
30
- }
31
- function handleCliVersionFlag(argv, moduleUrl = import.meta.url, binName) {
32
- if (!wantsCliVersion(argv)) return false;
33
- printCliVersionAndExit(readOwnPackageVersion(moduleUrl), binName);
34
- return true;
35
- }
36
-
37
- // src/memory-cost-package-version-guard.ts
38
- import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
39
- import path4 from "node:path";
40
-
41
- // src/default-repo-discovery.ts
42
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
43
- import { homedir as homedir2 } from "node:os";
44
- import path3 from "node:path";
45
- import { fileURLToPath as fileURLToPath2 } from "node:url";
46
-
47
- // src/git.ts
48
- import { spawnSync } from "node:child_process";
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
49
10
 
50
11
  // src/util.ts
51
12
  import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, readdirSync, statSync, writeFileSync } from "node:fs";
@@ -154,42 +115,13 @@ function latestIso(values) {
154
115
  function secsAgo(ms) {
155
116
  return Math.max(0, Math.round((Date.now() - ms) / 1e3));
156
117
  }
118
+ var init_util = __esm({
119
+ "src/util.ts"() {
120
+ "use strict";
121
+ }
122
+ });
157
123
 
158
124
  // src/worker-env.ts
159
- var FORBIDDEN_WORKER_ENV_KEYS = [
160
- "ANTHROPIC_API_KEY",
161
- "ANALYST_API_KEY",
162
- "RECRUITER_API_KEY",
163
- "AUTH_SECRET",
164
- "NEXTAUTH_SECRET",
165
- "DATABASE_URL",
166
- "PRODUCTION_DATABASE_URL",
167
- "KYNVER_PRODUCTION_DATABASE_URL",
168
- "REDIS_URL",
169
- "GOOGLE_CLIENT_SECRET",
170
- "GITHUB_CLIENT_SECRET",
171
- "KYNVER_API_KEY",
172
- "KYNVER_SERVICE_SECRET",
173
- "KYNVER_RUNTIME_SECRET",
174
- "KYNVER_CRON_SECRET",
175
- "OPENCLAW_CRON_SECRET",
176
- "QSTASH_TOKEN",
177
- "QSTASH_CURRENT_SIGNING_KEY",
178
- "QSTASH_NEXT_SIGNING_KEY",
179
- "TOOL_SECRETS_KEK",
180
- "TOOL_EXECUTOR_DISPATCH_SECRET",
181
- "CLOUDFLARE_API_TOKEN",
182
- "STRIPE_SECRET_KEY",
183
- "STRIPE_WEBHOOK_SECRET",
184
- "STRIPE_IDENTITY_WEBHOOK_SECRET",
185
- "VOYAGE_API_KEY",
186
- "PERPLEXITY_API_KEY",
187
- "FRED_API_KEY",
188
- "FMP_API_KEY",
189
- "CURSOR_API_KEY"
190
- ];
191
- var FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
192
- var FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
193
125
  function isForbiddenWorkerEnvKey(key) {
194
126
  if (FORBIDDEN_KEY_SET.has(key)) return true;
195
127
  return FORBIDDEN_SUFFIXES.some((suffix) => key.endsWith(suffix));
@@ -211,8 +143,49 @@ function auditWorkerEnv(env) {
211
143
  function scrubClaudeEnv(env) {
212
144
  return scrubWorkerEnv(env);
213
145
  }
146
+ var FORBIDDEN_WORKER_ENV_KEYS, FORBIDDEN_KEY_SET, FORBIDDEN_SUFFIXES;
147
+ var init_worker_env = __esm({
148
+ "src/worker-env.ts"() {
149
+ "use strict";
150
+ FORBIDDEN_WORKER_ENV_KEYS = [
151
+ "ANTHROPIC_API_KEY",
152
+ "ANALYST_API_KEY",
153
+ "RECRUITER_API_KEY",
154
+ "AUTH_SECRET",
155
+ "NEXTAUTH_SECRET",
156
+ "DATABASE_URL",
157
+ "PRODUCTION_DATABASE_URL",
158
+ "KYNVER_PRODUCTION_DATABASE_URL",
159
+ "REDIS_URL",
160
+ "GOOGLE_CLIENT_SECRET",
161
+ "GITHUB_CLIENT_SECRET",
162
+ "KYNVER_API_KEY",
163
+ "KYNVER_SERVICE_SECRET",
164
+ "KYNVER_RUNTIME_SECRET",
165
+ "KYNVER_CRON_SECRET",
166
+ "OPENCLAW_CRON_SECRET",
167
+ "QSTASH_TOKEN",
168
+ "QSTASH_CURRENT_SIGNING_KEY",
169
+ "QSTASH_NEXT_SIGNING_KEY",
170
+ "TOOL_SECRETS_KEK",
171
+ "TOOL_EXECUTOR_DISPATCH_SECRET",
172
+ "CLOUDFLARE_API_TOKEN",
173
+ "STRIPE_SECRET_KEY",
174
+ "STRIPE_WEBHOOK_SECRET",
175
+ "STRIPE_IDENTITY_WEBHOOK_SECRET",
176
+ "VOYAGE_API_KEY",
177
+ "PERPLEXITY_API_KEY",
178
+ "FRED_API_KEY",
179
+ "FMP_API_KEY",
180
+ "CURSOR_API_KEY"
181
+ ];
182
+ FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
183
+ FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
184
+ }
185
+ });
214
186
 
215
187
  // src/git.ts
188
+ import { spawnSync } from "node:child_process";
216
189
  function git(cwd, args, options = {}) {
217
190
  const res = spawnSync(
218
191
  "git",
@@ -336,6 +309,13 @@ function unknownAncestry(base, error, head = null) {
336
309
  error
337
310
  };
338
311
  }
312
+ var init_git = __esm({
313
+ "src/git.ts"() {
314
+ "use strict";
315
+ init_util();
316
+ init_worker_env();
317
+ }
318
+ });
339
319
 
340
320
  // src/path-values.ts
341
321
  import { homedir } from "node:os";
@@ -365,15 +345,17 @@ function redactHomePath(value) {
365
345
  function displayUserPath(value) {
366
346
  return redactHomePath(value);
367
347
  }
348
+ var init_path_values = __esm({
349
+ "src/path-values.ts"() {
350
+ "use strict";
351
+ }
352
+ });
368
353
 
369
354
  // src/default-repo-discovery.ts
370
- var WELL_KNOWN_REPO_DIRS = [
371
- "Kynver",
372
- "repos/Kynver",
373
- "repos/kynver-source-main",
374
- "code/Kynver",
375
- "projects/Kynver"
376
- ];
355
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
356
+ import { homedir as homedir2 } from "node:os";
357
+ import path3 from "node:path";
358
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
377
359
  function readPackageName(repoRoot) {
378
360
  const pkgPath = path3.join(repoRoot, "package.json");
379
361
  if (!existsSync3(pkgPath)) return null;
@@ -438,425 +420,135 @@ function discoverDefaultRepoCandidates(opts) {
438
420
  function discoverDefaultRepo(opts) {
439
421
  return discoverDefaultRepoCandidates(opts)[0] ?? null;
440
422
  }
441
-
442
- // src/memory-cost-package-version-guard.ts
443
- var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
444
- "@kynver-app/runtime": "0.1.83",
445
- "@kynver-app/openclaw-agent-os": "0.1.43",
446
- "@kynver-app/mcp-agent-os": "0.3.34"
447
- };
448
- var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
449
- MEMORY_COST_PACKAGE_MIN_VERSIONS
450
- );
451
- var DISPLAY_NAMES = {
452
- "@kynver-app/runtime": "Kynver runtime",
453
- "@kynver-app/openclaw-agent-os": "OpenClaw AgentOS plugin",
454
- "@kynver-app/mcp-agent-os": "AgentOS MCP server"
455
- };
456
- var REPO_PACKAGE_JSON_RELATIVE = {
457
- "@kynver-app/runtime": "packages/kynver-runtime/package.json",
458
- "@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
459
- "@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
460
- };
461
- function parseSemverParts(version) {
462
- const core = version.trim().split("-")[0]?.split("+")[0];
463
- if (!core) return null;
464
- const parts = core.split(".");
465
- if (parts.length < 1 || parts.length > 3) return null;
466
- const nums = parts.map((p) => Number.parseInt(p, 10));
467
- if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
468
- while (nums.length < 3) nums.push(0);
469
- return [nums[0], nums[1], nums[2]];
470
- }
471
- function compareSemver(a, b) {
472
- const pa = parseSemverParts(a);
473
- const pb = parseSemverParts(b);
474
- if (!pa || !pb) return 0;
475
- for (let i = 0; i < 3; i += 1) {
476
- if (pa[i] > pb[i]) return 1;
477
- if (pa[i] < pb[i]) return -1;
423
+ var WELL_KNOWN_REPO_DIRS;
424
+ var init_default_repo_discovery = __esm({
425
+ "src/default-repo-discovery.ts"() {
426
+ "use strict";
427
+ init_git();
428
+ init_path_values();
429
+ WELL_KNOWN_REPO_DIRS = [
430
+ "Kynver",
431
+ "repos/Kynver",
432
+ "repos/kynver-source-main",
433
+ "code/Kynver",
434
+ "projects/Kynver"
435
+ ];
478
436
  }
479
- return 0;
437
+ });
438
+
439
+ // src/box-identity.ts
440
+ function normalizeWorkerPoolBoxKind(raw) {
441
+ const kind = (raw ?? "").trim().toLowerCase();
442
+ if (kind === "ghost" || kind === "forge") return kind;
443
+ if (kind.includes("forge")) return "forge";
444
+ if (kind.includes("ghost") || kind.includes("openclaw")) return "ghost";
445
+ return "forge";
480
446
  }
481
- function semverAtLeast(version, minimum) {
482
- return compareSemver(version, minimum) >= 0;
447
+ function trimEnv(env, key) {
448
+ const value = env[key]?.trim();
449
+ return value || null;
483
450
  }
484
- function maxSemver(versions) {
485
- let best = null;
486
- for (const version of versions) {
487
- if (!best || compareSemver(version, best) > 0) best = version;
451
+ function resolveBoxIdentity(env = process.env, config = {}) {
452
+ const warnings = [];
453
+ const configKind = config.boxKind?.trim();
454
+ if (configKind) {
455
+ return {
456
+ boxKind: normalizeWorkerPoolBoxKind(configKind),
457
+ source: "config",
458
+ slugInferenceBlocked: false,
459
+ warnings
460
+ };
488
461
  }
489
- return best;
490
- }
491
- function readPackageJsonVersion(packageJsonPath) {
492
- try {
493
- const parsed = JSON.parse(readFileSync4(packageJsonPath, "utf8"));
494
- return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
495
- } catch {
496
- return null;
462
+ const envKind = trimEnv(env, "KYNVER_BOX_KIND");
463
+ if (envKind) {
464
+ return {
465
+ boxKind: normalizeWorkerPoolBoxKind(envKind),
466
+ source: "env",
467
+ slugInferenceBlocked: false,
468
+ warnings
469
+ };
497
470
  }
498
- }
499
- function resolveRepoRoot(cwd, explicitRepoRoot) {
500
- const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(
501
- (value) => Boolean(value?.trim())
502
- );
503
- for (const candidate of candidates) {
504
- const resolved = path4.resolve(candidate);
505
- if (existsSync4(path4.join(resolved, "packages/kynver-runtime/package.json")) && existsSync4(path4.join(resolved, "package.json"))) {
506
- return resolved;
507
- }
471
+ const agentOsSlug = trimEnv(env, "KYNVER_AGENT_OS_SLUG");
472
+ if (agentOsSlug) {
473
+ warnings.push(
474
+ `KYNVER_AGENT_OS_SLUG=${agentOsSlug} is a workspace slug, not box identity \u2014 set boxKind via \`kynver setup --box-kind forge|ghost\` or KYNVER_BOX_KIND (defaulting box kind to forge)`
475
+ );
508
476
  }
509
- const discovered = discoverDefaultRepo({ cwd });
510
- return discovered?.repo ?? null;
477
+ return {
478
+ boxKind: "forge",
479
+ source: "default",
480
+ slugInferenceBlocked: Boolean(agentOsSlug),
481
+ warnings
482
+ };
511
483
  }
512
- function probeRepoPackageVersions(input = {}) {
513
- const cwd = input.cwd ?? process.cwd();
514
- const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
515
- if (!repoRoot) return {};
516
- const out = {};
517
- for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
518
- const packageJsonPath = path4.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
519
- const version = readPackageJsonVersion(packageJsonPath);
520
- if (!version) continue;
521
- out[packageName] = { version, source: "repo", path: packageJsonPath };
522
- }
523
- return out;
484
+ function resolveBoxKindFromConfig(config = {}, env = process.env) {
485
+ return resolveBoxIdentity(env, config).boxKind;
524
486
  }
525
- function repoSourceCommands(packageName) {
526
- if (packageName === "@kynver-app/runtime") {
527
- return ["npm run kynver:build", "npm run kynver"];
487
+ var init_box_identity = __esm({
488
+ "src/box-identity.ts"() {
489
+ "use strict";
528
490
  }
529
- return [`npm run build -w ${packageName}`];
530
- }
531
- function buildRemediation(input) {
532
- const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;
533
- const lines = [];
534
- if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {
535
- lines.push(
536
- `Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join("; ")}.`
537
- );
538
- lines.push("Do not publish npm packages or wait on an operator release.");
539
- return lines;
491
+ });
492
+
493
+ // src/bounded-build/meminfo.ts
494
+ import { readFileSync as readFileSync5 } from "node:fs";
495
+ import os from "node:os";
496
+ function readMemAvailableBytes(meminfoText) {
497
+ if (meminfoText !== void 0) {
498
+ const match = meminfoText.match(/^MemAvailable:\s+(\d+)\s*kB/m);
499
+ if (match) return Number(match[1]) * 1024;
500
+ return os.freemem();
540
501
  }
541
- if (effectiveVersion) {
542
- lines.push(
543
- `Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`
544
- );
545
- } else {
546
- lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);
502
+ if (process.platform === "linux") {
503
+ try {
504
+ const meminfo = readFileSync5("/proc/meminfo", "utf8");
505
+ const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
506
+ if (match) return Number(match[1]) * 1024;
507
+ } catch {
508
+ }
547
509
  }
548
- if (packageName === "@kynver-app/runtime") {
549
- lines.push("Repo-source alternative: npm run kynver:build && npm run kynver");
510
+ return os.freemem();
511
+ }
512
+ var init_meminfo = __esm({
513
+ "src/bounded-build/meminfo.ts"() {
514
+ "use strict";
550
515
  }
551
- if (effectiveSource === "installed" && repoVersion) {
552
- lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);
516
+ });
517
+
518
+ // src/wsl-host.ts
519
+ import { existsSync as existsSync5, readFileSync as readFileSync6, statfsSync } from "node:fs";
520
+ function isWslHost() {
521
+ if (process.platform !== "linux") return false;
522
+ for (const probe of ["/proc/sys/kernel/osrelease", "/proc/version"]) {
523
+ try {
524
+ if (!existsSync5(probe)) continue;
525
+ const text = readFileSync6(probe, "utf8");
526
+ if (/microsoft|wsl/i.test(text)) return true;
527
+ } catch {
528
+ }
553
529
  }
554
- return lines;
555
- }
556
- function pickEffectiveCandidate(candidates) {
557
- if (candidates.length === 0) return { version: null, source: "unknown" };
558
- const best = maxSemver(candidates.map((candidate) => candidate.version));
559
- if (!best) return { version: null, source: "unknown" };
560
- const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
561
- return { version: winner.version, source: winner.source };
562
- }
563
- function evaluateMemoryCostPackageVersionGuard(input = {}) {
564
- const normalize2 = (value, fallbackSource) => {
565
- if (!value) return null;
566
- if (typeof value === "string") return { version: value, source: fallbackSource };
567
- return value;
568
- };
569
- const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
570
- const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
571
- const candidates = [];
572
- const installed = normalize2(input.installed?.[packageName], "installed");
573
- const repo = normalize2(input.repo?.[packageName], "repo");
574
- const self = normalize2(input.self?.[packageName], "self");
575
- if (installed) candidates.push(installed);
576
- if (repo) candidates.push(repo);
577
- if (self) candidates.push(self);
578
- const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
579
- const repoVersion = repo?.version ?? null;
580
- const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
581
- const remediation = ok2 ? [] : buildRemediation({
582
- packageName,
583
- minimumVersion,
584
- effectiveVersion,
585
- effectiveSource,
586
- repoVersion
587
- });
588
- 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)") + ".";
589
- return {
590
- packageName,
591
- displayName: DISPLAY_NAMES[packageName],
592
- minimumVersion,
593
- effectiveVersion,
594
- effectiveSource,
595
- ok: ok2,
596
- summary: summary2,
597
- remediation
598
- };
599
- });
600
- const violations = packages.filter((row) => !row.ok);
601
- const ok = violations.length === 0;
602
- 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("; ")}.`;
603
- return { ok, summary, packages };
604
- }
605
- var MemoryCostPackageVersionGuardError = class extends Error {
606
- result;
607
- constructor(result) {
608
- const lines = [
609
- result.summary,
610
- ...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
611
- ];
612
- super(lines.join("\n"));
613
- this.name = "MemoryCostPackageVersionGuardError";
614
- this.result = result;
615
- }
616
- };
617
- function assertMemoryCostPackageVersionGuard(input = {}) {
618
- const result = evaluateMemoryCostPackageVersionGuard(input);
619
- if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
620
- return result;
621
- }
622
- function formatMemoryCostPackageGuardError(result) {
623
- return new MemoryCostPackageVersionGuardError(result).message;
624
- }
625
-
626
- // src/installed-package-versions.ts
627
- import { readFile } from "node:fs/promises";
628
- import { homedir as homedir3 } from "node:os";
629
- import path5 from "node:path";
630
- var MANAGED_PACKAGES = [
631
- "@kynver-app/runtime",
632
- "@kynver-app/openclaw-agent-os",
633
- "@kynver-app/mcp-agent-os"
634
- ];
635
- function trim(value) {
636
- const out = value?.trim();
637
- return out ? out : null;
638
- }
639
- function unique(values) {
640
- return [...new Set(values.filter((value) => Boolean(value)))];
641
- }
642
- function moduleRoots() {
643
- const home = homedir3();
644
- const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path5.join(home, ".openclaw", "npm");
645
- const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path5.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path5.join(home, ".npm-global", "lib", "node_modules"));
646
- return unique([
647
- path5.join(openClawPrefix, "lib", "node_modules"),
648
- path5.join(openClawPrefix, "node_modules"),
649
- npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path5.join(npmGlobalRoot, "lib", "node_modules")
650
- ]);
651
- }
652
- async function readVersion(packageJsonPath) {
653
- try {
654
- const parsed = JSON.parse(await readFile(packageJsonPath, "utf8"));
655
- return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
656
- } catch {
657
- return null;
658
- }
659
- }
660
- function installedPackageJsonCandidates(packageName) {
661
- const roots = moduleRoots();
662
- const seen = /* @__PURE__ */ new Set();
663
- const out = [];
664
- for (const root of roots) {
665
- const candidate = path5.join(root, packageName, "package.json");
666
- if (seen.has(candidate)) continue;
667
- seen.add(candidate);
668
- out.push(candidate);
669
- }
670
- return out;
671
- }
672
- async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
673
- const out = {};
674
- for (const packageName of MANAGED_PACKAGES) {
675
- let best = null;
676
- for (const packageJsonPath of installedPackageJsonCandidates(packageName)) {
677
- const version = await readVersion(packageJsonPath);
678
- if (!version) continue;
679
- if (!best || compareSemver(version, best.version) > 0) {
680
- best = { version, path: packageJsonPath };
681
- }
682
- }
683
- if (best) {
684
- out[packageName] = { version: best.version, observedAt, path: best.path };
685
- }
686
- }
687
- return out;
688
- }
689
-
690
- // src/memory-cost-package-version-guard-enforce.ts
691
- function installedVersionMap(observed) {
692
- const out = {};
693
- for (const [packageName, row] of Object.entries(observed)) {
694
- if (!row?.version) continue;
695
- out[packageName] = {
696
- version: row.version,
697
- source: "installed",
698
- path: row.path
699
- };
700
- }
701
- return out;
702
- }
703
- async function buildMemoryCostPackageGuardInput(input = {}) {
704
- const [installed, repo] = await Promise.all([
705
- collectInstalledPackageVersions(),
706
- Promise.resolve(probeRepoPackageVersions({ cwd: input.cwd, repoRoot: input.repoRoot }))
707
- ]);
708
- const self = {};
709
- const runtimeSelfVersion = input.selfPackageName === "@kynver-app/runtime" && input.selfVersion ? input.selfVersion : PACKAGE_VERSION;
710
- self["@kynver-app/runtime"] = { version: runtimeSelfVersion, source: "self" };
711
- if (input.selfPackageName && input.selfVersion && input.selfPackageName !== "@kynver-app/runtime") {
712
- self[input.selfPackageName] = { version: input.selfVersion, source: "self" };
713
- }
714
- return {
715
- installed: installedVersionMap(installed),
716
- repo,
717
- self
718
- };
719
- }
720
- async function evaluateMemoryCostPackageGuardAtStartup(input = {}) {
721
- const guardInput = await buildMemoryCostPackageGuardInput(input);
722
- return evaluateMemoryCostPackageVersionGuard(guardInput);
723
- }
724
- async function enforceMemoryCostPackageGuardAtStartup(input = {}) {
725
- const guardInput = await buildMemoryCostPackageGuardInput(input);
726
- return assertMemoryCostPackageVersionGuard(guardInput);
727
- }
728
- function shouldEnforceMemoryCostPackageGuardCli(scope, action) {
729
- if (!scope) return false;
730
- if (scope === "daemon") return true;
731
- if (scope === "worker") return true;
732
- if (scope === "monitor") return true;
733
- if (scope === "run" && (action === "dispatch" || action === "sweep" || action === "reconcile" || action === "unblock")) {
734
- return true;
735
- }
736
- if (scope === "cron" && action === "tick") return true;
737
- return false;
738
- }
739
-
740
- // src/config.ts
741
- import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync2 } from "node:fs";
742
- import { homedir as homedir5, totalmem } from "node:os";
743
- import path10 from "node:path";
744
-
745
- // src/box-identity.ts
746
- function normalizeWorkerPoolBoxKind(raw) {
747
- const kind = (raw ?? "").trim().toLowerCase();
748
- if (kind === "ghost" || kind === "forge") return kind;
749
- if (kind.includes("forge")) return "forge";
750
- if (kind.includes("ghost") || kind.includes("openclaw")) return "ghost";
751
- return "forge";
752
- }
753
- function trimEnv(env, key) {
754
- const value = env[key]?.trim();
755
- return value || null;
756
- }
757
- function resolveBoxIdentity(env = process.env, config = {}) {
758
- const warnings = [];
759
- const configKind = config.boxKind?.trim();
760
- if (configKind) {
761
- return {
762
- boxKind: normalizeWorkerPoolBoxKind(configKind),
763
- source: "config",
764
- slugInferenceBlocked: false,
765
- warnings
766
- };
767
- }
768
- const envKind = trimEnv(env, "KYNVER_BOX_KIND");
769
- if (envKind) {
770
- return {
771
- boxKind: normalizeWorkerPoolBoxKind(envKind),
772
- source: "env",
773
- slugInferenceBlocked: false,
774
- warnings
775
- };
776
- }
777
- const agentOsSlug = trimEnv(env, "KYNVER_AGENT_OS_SLUG");
778
- if (agentOsSlug) {
779
- warnings.push(
780
- `KYNVER_AGENT_OS_SLUG=${agentOsSlug} is a workspace slug, not box identity \u2014 set boxKind via \`kynver setup --box-kind forge|ghost\` or KYNVER_BOX_KIND (defaulting box kind to forge)`
781
- );
782
- }
783
- return {
784
- boxKind: "forge",
785
- source: "default",
786
- slugInferenceBlocked: Boolean(agentOsSlug),
787
- warnings
788
- };
789
- }
790
- function resolveBoxKindFromConfig(config = {}, env = process.env) {
791
- return resolveBoxIdentity(env, config).boxKind;
792
- }
793
-
794
- // src/resource-gate.ts
795
- import os2 from "node:os";
796
-
797
- // src/bounded-build/meminfo.ts
798
- import { readFileSync as readFileSync5 } from "node:fs";
799
- import os from "node:os";
800
- function readMemAvailableBytes(meminfoText) {
801
- if (meminfoText !== void 0) {
802
- const match = meminfoText.match(/^MemAvailable:\s+(\d+)\s*kB/m);
803
- if (match) return Number(match[1]) * 1024;
804
- return os.freemem();
805
- }
806
- if (process.platform === "linux") {
807
- try {
808
- const meminfo = readFileSync5("/proc/meminfo", "utf8");
809
- const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
810
- if (match) return Number(match[1]) * 1024;
811
- } catch {
812
- }
813
- }
814
- return os.freemem();
815
- }
816
-
817
- // src/resource-gate.ts
818
- import path9 from "node:path";
819
-
820
- // src/disk-gate.ts
821
- import { statfsSync as statfsSync2 } from "node:fs";
822
-
823
- // src/wsl-host.ts
824
- import { existsSync as existsSync5, readFileSync as readFileSync6, statfsSync } from "node:fs";
825
- var DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
826
- var DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
827
- var DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
828
- function isWslHost() {
829
- if (process.platform !== "linux") return false;
830
- for (const probe of ["/proc/sys/kernel/osrelease", "/proc/version"]) {
831
- try {
832
- if (!existsSync5(probe)) continue;
833
- const text = readFileSync6(probe, "utf8");
834
- if (/microsoft|wsl/i.test(text)) return true;
835
- } catch {
836
- }
837
- }
838
- return false;
530
+ return false;
839
531
  }
840
532
  function observeWslHostDisk(options = {}) {
841
533
  const wsl = options.forceWsl === void 0 ? isWslHost() : options.forceWsl;
842
534
  if (!wsl) return null;
843
- const path73 = options.wslHostMount?.trim() || process.env.KYNVER_WSL_HOST_MOUNT?.trim() || DEFAULT_WSL_HOST_MOUNT;
535
+ const path75 = options.wslHostMount?.trim() || process.env.KYNVER_WSL_HOST_MOUNT?.trim() || DEFAULT_WSL_HOST_MOUNT;
844
536
  const warnBelowBytes = options.wslHostFreeWarnBytes ?? DEFAULT_WSL_HOST_WARN_FREE_BYTES;
845
537
  const criticalBelowBytes = options.wslHostFreeCriticalBytes ?? DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES;
846
538
  const statfs = options.statfs ?? statfsSync;
847
539
  let stats;
848
540
  try {
849
- stats = statfs(path73);
541
+ stats = statfs(path75);
850
542
  } catch (error) {
851
543
  return {
852
544
  ok: false,
853
- path: path73,
545
+ path: path75,
854
546
  freeBytes: 0,
855
547
  totalBytes: 0,
856
548
  usedPercent: 100,
857
549
  warnBelowBytes,
858
550
  criticalBelowBytes,
859
- reason: `Windows host disk probe failed at ${path73}: ${error.message}`,
551
+ reason: `Windows host disk probe failed at ${path75}: ${error.message}`,
860
552
  probeError: error.message
861
553
  };
862
554
  }
@@ -870,11 +562,11 @@ function observeWslHostDisk(options = {}) {
870
562
  let reason = null;
871
563
  if (!ok) {
872
564
  const tag = criticalFree ? "critical" : "warning";
873
- reason = `Windows host disk ${path73} at ${tag}: ${freeGiB} GiB free (<${(criticalFree ? criticalBelowBytes : warnBelowBytes) / 1024 / 1024 / 1024} GiB); WSL VHDX cannot grow safely. ${summarizeWslRecoverySteps()}`;
565
+ reason = `Windows host disk ${path75} at ${tag}: ${freeGiB} GiB free (<${(criticalFree ? criticalBelowBytes : warnBelowBytes) / 1024 / 1024 / 1024} GiB); WSL VHDX cannot grow safely. ${summarizeWslRecoverySteps()}`;
874
566
  }
875
567
  return {
876
568
  ok,
877
- path: path73,
569
+ path: path75,
878
570
  freeBytes,
879
571
  totalBytes,
880
572
  usedPercent,
@@ -887,19 +579,25 @@ function observeWslHostDisk(options = {}) {
887
579
  function summarizeWslRecoverySteps() {
888
580
  return "Recovery: 1) free Windows C: (empty Recycle Bin / Storage Sense / clear %TEMP%); 2) shut down WSL (`wsl --shutdown`) then compact the VHDX (`Optimize-VHD` or `diskpart compact vdisk`); 3) clear local node_modules / .next / harness worktrees before restarting workers. Full runbook: docs/runbooks/wsl-disk-pressure.md.";
889
581
  }
582
+ var DEFAULT_WSL_HOST_WARN_FREE_BYTES, DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES, DEFAULT_WSL_HOST_MOUNT;
583
+ var init_wsl_host = __esm({
584
+ "src/wsl-host.ts"() {
585
+ "use strict";
586
+ DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
587
+ DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
588
+ DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
589
+ }
590
+ });
890
591
 
891
592
  // src/disk-gate.ts
892
- var DEFAULT_WARN_FREE_BYTES = 30 * 1024 * 1024 * 1024;
893
- var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
894
- var DEFAULT_MAX_USED_PERCENT = 80;
895
- var DEFAULT_HARD_MAX_USED_PERCENT = 90;
593
+ import { statfsSync as statfsSync2 } from "node:fs";
896
594
  function observeRunnerDiskGate(input = {}) {
897
- const path73 = input.diskPath?.trim() || "/";
595
+ const path75 = input.diskPath?.trim() || "/";
898
596
  const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
899
597
  const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
900
598
  const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
901
599
  const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
902
- const stats = statfsSync2(path73);
600
+ const stats = statfsSync2(path75);
903
601
  const freeBytes = Number(stats.bavail) * Number(stats.bsize);
904
602
  const totalBytes = Number(stats.blocks) * Number(stats.bsize);
905
603
  const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
@@ -922,7 +620,7 @@ function observeRunnerDiskGate(input = {}) {
922
620
  }
923
621
  return {
924
622
  ok,
925
- path: path73,
623
+ path: path75,
926
624
  freeBytes,
927
625
  totalBytes,
928
626
  usedPercent,
@@ -934,17 +632,22 @@ function observeRunnerDiskGate(input = {}) {
934
632
  wslHost
935
633
  };
936
634
  }
937
-
938
- // src/run-store.ts
939
- import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
940
- import path7 from "node:path";
635
+ var DEFAULT_WARN_FREE_BYTES, DEFAULT_CRITICAL_FREE_BYTES, DEFAULT_MAX_USED_PERCENT, DEFAULT_HARD_MAX_USED_PERCENT;
636
+ var init_disk_gate = __esm({
637
+ "src/disk-gate.ts"() {
638
+ "use strict";
639
+ init_wsl_host();
640
+ DEFAULT_WARN_FREE_BYTES = 30 * 1024 * 1024 * 1024;
641
+ DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
642
+ DEFAULT_MAX_USED_PERCENT = 80;
643
+ DEFAULT_HARD_MAX_USED_PERCENT = 90;
644
+ }
645
+ });
941
646
 
942
647
  // src/paths.ts
943
648
  import { existsSync as existsSync6 } from "node:fs";
944
649
  import { homedir as homedir4 } from "node:os";
945
650
  import path6 from "node:path";
946
- var LEGACY_ROOT = path6.join(homedir4(), ".openclaw", "harness");
947
- var HARNESS_LAYOUT_DIR_NAMES = /* @__PURE__ */ new Set(["runs", "worktrees"]);
948
651
  function normalizeHarnessRoot(root) {
949
652
  let resolved = path6.resolve(resolveUserPath(root.trim()));
950
653
  while (HARNESS_LAYOUT_DIR_NAMES.has(path6.basename(resolved))) {
@@ -979,8 +682,21 @@ function getHarnessPaths() {
979
682
  function runDir(runsDir, id) {
980
683
  return path6.join(runsDir, safeSlug(id));
981
684
  }
685
+ var LEGACY_ROOT, HARNESS_LAYOUT_DIR_NAMES;
686
+ var init_paths = __esm({
687
+ "src/paths.ts"() {
688
+ "use strict";
689
+ init_config();
690
+ init_path_values();
691
+ init_util();
692
+ LEGACY_ROOT = path6.join(homedir4(), ".openclaw", "harness");
693
+ HARNESS_LAYOUT_DIR_NAMES = /* @__PURE__ */ new Set(["runs", "worktrees"]);
694
+ }
695
+ });
982
696
 
983
697
  // src/run-store.ts
698
+ import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
699
+ import path7 from "node:path";
984
700
  function getPaths() {
985
701
  return getHarnessPaths();
986
702
  }
@@ -1038,6 +754,13 @@ function runDirectory(id) {
1038
754
  function runDirectoryAt(harnessRoot, id) {
1039
755
  return runDir(harnessRunsDir(harnessRoot), safeSlug(id));
1040
756
  }
757
+ var init_run_store = __esm({
758
+ "src/run-store.ts"() {
759
+ "use strict";
760
+ init_paths();
761
+ init_util();
762
+ }
763
+ });
1041
764
 
1042
765
  // src/run-worker-index.ts
1043
766
  import { existsSync as existsSync8, readdirSync as readdirSync3 } from "node:fs";
@@ -1055,12 +778,13 @@ function listRunWorkerNames(run) {
1055
778
  }
1056
779
  return [...names];
1057
780
  }
1058
-
1059
- // src/harness-worker-active.ts
1060
- import { readFileSync as readFileSync9 } from "node:fs";
1061
-
1062
- // src/heartbeat.ts
1063
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
781
+ var init_run_worker_index = __esm({
782
+ "src/run-worker-index.ts"() {
783
+ "use strict";
784
+ init_run_store();
785
+ init_util();
786
+ }
787
+ });
1064
788
 
1065
789
  // src/heartbeat-final-result.ts
1066
790
  function tryParseJsonObject(text) {
@@ -1111,9 +835,14 @@ function terminalFinalResultFromHeartbeatRow(row) {
1111
835
  if (embedded) return embedded;
1112
836
  return summary;
1113
837
  }
838
+ var init_heartbeat_final_result = __esm({
839
+ "src/heartbeat-final-result.ts"() {
840
+ "use strict";
841
+ }
842
+ });
1114
843
 
1115
844
  // src/heartbeat.ts
1116
- var HEARTBEAT_FUTURE_SKEW_MS = 6e4;
845
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
1117
846
  function isTerminalHeartbeatPhase(phase) {
1118
847
  return phase === "complete";
1119
848
  }
@@ -1176,29 +905,17 @@ function parseHeartbeat(file) {
1176
905
  }
1177
906
  return result;
1178
907
  }
1179
-
1180
- // src/stream.ts
1181
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
908
+ var HEARTBEAT_FUTURE_SKEW_MS;
909
+ var init_heartbeat = __esm({
910
+ "src/heartbeat.ts"() {
911
+ "use strict";
912
+ init_heartbeat_final_result();
913
+ init_util();
914
+ HEARTBEAT_FUTURE_SKEW_MS = 6e4;
915
+ }
916
+ });
1182
917
 
1183
918
  // src/repo-search.ts
1184
- var RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
1185
- var RG_OPTS_WITH_VALUE = /* @__PURE__ */ new Set([
1186
- "-e",
1187
- "--regexp",
1188
- "-f",
1189
- "--file",
1190
- "-m",
1191
- "--max-count",
1192
- "-A",
1193
- "--after-context",
1194
- "-B",
1195
- "--before-context",
1196
- "-C",
1197
- "--context",
1198
- "-g",
1199
- "--glob",
1200
- "--iglob"
1201
- ]);
1202
919
  function binaryName(token) {
1203
920
  if (!token) return null;
1204
921
  const base = token.split("/").pop() ?? token;
@@ -1397,11 +1114,32 @@ function diagnoseRepoSearchFailure(input) {
1397
1114
  }
1398
1115
  return null;
1399
1116
  }
1117
+ var RG_BINARIES, RG_OPTS_WITH_VALUE;
1118
+ var init_repo_search = __esm({
1119
+ "src/repo-search.ts"() {
1120
+ "use strict";
1121
+ RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
1122
+ RG_OPTS_WITH_VALUE = /* @__PURE__ */ new Set([
1123
+ "-e",
1124
+ "--regexp",
1125
+ "-f",
1126
+ "--file",
1127
+ "-m",
1128
+ "--max-count",
1129
+ "-A",
1130
+ "--after-context",
1131
+ "-B",
1132
+ "--before-context",
1133
+ "-C",
1134
+ "--context",
1135
+ "-g",
1136
+ "--glob",
1137
+ "--iglob"
1138
+ ]);
1139
+ }
1140
+ });
1400
1141
 
1401
1142
  // src/shell-command-outcome.ts
1402
- var NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
1403
- var RG_CMD_RE = /\b(rg|ripgrep)\b/i;
1404
- var RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
1405
1143
  function tidy(text, max = 200) {
1406
1144
  const one = text.replace(/\s+/g, " ").trim();
1407
1145
  return one.length > max ? `${one.slice(0, max - 1)}\u2026` : one;
@@ -1605,8 +1343,19 @@ function classifyShellCommandOutcome(input) {
1605
1343
  summary: `command failed (exit ${input.exitCode}): ${tail}`
1606
1344
  };
1607
1345
  }
1346
+ var NPM_AUDIT_RE, RG_CMD_RE, RG_REAL_ERROR_RE;
1347
+ var init_shell_command_outcome = __esm({
1348
+ "src/shell-command-outcome.ts"() {
1349
+ "use strict";
1350
+ init_repo_search();
1351
+ NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
1352
+ RG_CMD_RE = /\b(rg|ripgrep)\b/i;
1353
+ RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
1354
+ }
1355
+ });
1608
1356
 
1609
1357
  // src/stream.ts
1358
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
1610
1359
  function eventTimestampIso(event) {
1611
1360
  const tsMs = event.timestamp_ms;
1612
1361
  return event.timestamp || event.ts || (tsMs ? new Date(tsMs).toISOString() : void 0);
@@ -1775,38 +1524,15 @@ function summarizeEvent(event) {
1775
1524
  }
1776
1525
  return void 0;
1777
1526
  }
1527
+ var init_stream = __esm({
1528
+ "src/stream.ts"() {
1529
+ "use strict";
1530
+ init_shell_command_outcome();
1531
+ init_util();
1532
+ }
1533
+ });
1778
1534
 
1779
1535
  // src/exit-classify.ts
1780
- var FAILURE_PATTERNS = [
1781
- {
1782
- test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
1783
- label: "provider rejected the requested model"
1784
- },
1785
- {
1786
- test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
1787
- label: "provider rejected the requested model"
1788
- },
1789
- {
1790
- test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
1791
- label: "provider rejected the requested model"
1792
- },
1793
- {
1794
- test: /model preflight failed/i,
1795
- label: "model/provider preflight failed"
1796
- },
1797
- {
1798
- test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
1799
- label: "provider CLI is missing or not on PATH"
1800
- },
1801
- {
1802
- test: /\bfailed to spawn\b/i,
1803
- label: "provider failed to spawn the worker process"
1804
- },
1805
- {
1806
- test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
1807
- label: "provider authentication failed"
1808
- }
1809
- ];
1810
1536
  function tidy2(errorText, max = 240) {
1811
1537
  const oneLine2 = errorText.replace(/\s+/g, " ").trim();
1812
1538
  return oneLine2.length > max ? `${oneLine2.slice(0, max - 1)}\u2026` : oneLine2;
@@ -1819,8 +1545,44 @@ function classifyExitFailure(errorText) {
1819
1545
  return { blocked: true, reason: `${pattern.label}: ${tidy2(text)}` };
1820
1546
  }
1821
1547
  }
1822
- return null;
1823
- }
1548
+ return null;
1549
+ }
1550
+ var FAILURE_PATTERNS;
1551
+ var init_exit_classify = __esm({
1552
+ "src/exit-classify.ts"() {
1553
+ "use strict";
1554
+ FAILURE_PATTERNS = [
1555
+ {
1556
+ test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
1557
+ label: "provider rejected the requested model"
1558
+ },
1559
+ {
1560
+ test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
1561
+ label: "provider rejected the requested model"
1562
+ },
1563
+ {
1564
+ test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
1565
+ label: "provider rejected the requested model"
1566
+ },
1567
+ {
1568
+ test: /model preflight failed/i,
1569
+ label: "model/provider preflight failed"
1570
+ },
1571
+ {
1572
+ test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
1573
+ label: "provider CLI is missing or not on PATH"
1574
+ },
1575
+ {
1576
+ test: /\bfailed to spawn\b/i,
1577
+ label: "provider failed to spawn the worker process"
1578
+ },
1579
+ {
1580
+ test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
1581
+ label: "provider authentication failed"
1582
+ }
1583
+ ];
1584
+ }
1585
+ });
1824
1586
 
1825
1587
  // src/exited-salvage.ts
1826
1588
  function trimOrNull(value) {
@@ -1879,6 +1641,11 @@ function assessExitedWorkerSalvage(input) {
1879
1641
  attentionReason: buildAttentionReason(kind, uncommittedCount, headCommit)
1880
1642
  };
1881
1643
  }
1644
+ var init_exited_salvage = __esm({
1645
+ "src/exited-salvage.ts"() {
1646
+ "use strict";
1647
+ }
1648
+ });
1882
1649
 
1883
1650
  // src/landing-gate.ts
1884
1651
  function trimOrNull2(value) {
@@ -1924,6 +1691,11 @@ function landingAttentionReason(verdict) {
1924
1691
  if (!verdict.blocked) return void 0;
1925
1692
  return verdict.detail ?? verdict.reason ?? "dirty_worktree_no_pr";
1926
1693
  }
1694
+ var init_landing_gate = __esm({
1695
+ "src/landing-gate.ts"() {
1696
+ "use strict";
1697
+ }
1698
+ });
1927
1699
 
1928
1700
  // src/worker-final-result-embed.ts
1929
1701
  function tryParseJsonObject2(text) {
@@ -1973,6 +1745,11 @@ function extractEmbeddedWorkerFinalResultRecord(value) {
1973
1745
  }
1974
1746
  return best;
1975
1747
  }
1748
+ var init_worker_final_result_embed = __esm({
1749
+ "src/worker-final-result-embed.ts"() {
1750
+ "use strict";
1751
+ }
1752
+ });
1976
1753
 
1977
1754
  // src/landing-contract-gate.ts
1978
1755
  function trimOrNull3(value) {
@@ -2132,10 +1909,14 @@ function landingContractAttentionReason(verdict) {
2132
1909
  if (!verdict.blocked) return void 0;
2133
1910
  return verdict.detail ?? verdict.reason;
2134
1911
  }
1912
+ var init_landing_contract_gate = __esm({
1913
+ "src/landing-contract-gate.ts"() {
1914
+ "use strict";
1915
+ init_worker_final_result_embed();
1916
+ }
1917
+ });
2135
1918
 
2136
1919
  // src/status.ts
2137
- var NO_START_MS = 18e4;
2138
- var STALE_MS = 6e5;
2139
1920
  function computeAttention(input) {
2140
1921
  const now = Date.now();
2141
1922
  if (input.completionBlocker && !isSkippedTerminalCompletionBlocker(input.completionBlocker)) {
@@ -2327,7 +2108,15 @@ function computeWorkerStatus(worker, options = {}) {
2327
2108
  changedFiles,
2328
2109
  gitAncestry,
2329
2110
  instructionPolicyFingerprint: worker.instructionPolicyFingerprint ?? null,
2330
- instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null
2111
+ instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null,
2112
+ model: worker.model ?? worker.orchestrationAudit?.model ?? null,
2113
+ provider: worker.orchestrationAudit?.provider ?? null,
2114
+ boxKind: worker.boxKind ?? null,
2115
+ boxId: worker.boxId ?? null,
2116
+ runtimeId: worker.runtimeId ?? null,
2117
+ personaSlug: worker.personaSlug ?? null,
2118
+ dispatched: worker.dispatched ?? null,
2119
+ localOnly: worker.localOnly ?? null
2331
2120
  };
2332
2121
  }
2333
2122
  function isFinishedWorkerStatus(status) {
@@ -2349,8 +2138,26 @@ function deriveRunStatus(fallback, workers) {
2349
2138
  if (workers.some((w) => w.status === "running")) return "running";
2350
2139
  return fallback;
2351
2140
  }
2141
+ var NO_START_MS, STALE_MS;
2142
+ var init_status = __esm({
2143
+ "src/status.ts"() {
2144
+ "use strict";
2145
+ init_heartbeat();
2146
+ init_stream();
2147
+ init_exit_classify();
2148
+ init_exited_salvage();
2149
+ init_git();
2150
+ init_landing_gate();
2151
+ init_landing_contract_gate();
2152
+ init_worker_final_result_embed();
2153
+ init_util();
2154
+ NO_START_MS = 18e4;
2155
+ STALE_MS = 6e5;
2156
+ }
2157
+ });
2352
2158
 
2353
2159
  // src/harness-worker-active.ts
2160
+ import { readFileSync as readFileSync9 } from "node:fs";
2354
2161
  function pidCommandLine(pid) {
2355
2162
  if (!pid || process.platform !== "linux") return null;
2356
2163
  try {
@@ -2376,12 +2183,16 @@ function isActiveHarnessWorker(worker) {
2376
2183
  if (status.alive && !workerProcessMatchesRecord(worker)) return false;
2377
2184
  return status.alive && !status.finalResult && status.attention.state !== "done";
2378
2185
  }
2186
+ var init_harness_worker_active = __esm({
2187
+ "src/harness-worker-active.ts"() {
2188
+ "use strict";
2189
+ init_status();
2190
+ }
2191
+ });
2379
2192
 
2380
2193
  // src/resource-gate.ts
2381
- var DEFAULT_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
2382
- var DEFAULT_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
2383
- var DEFAULT_MEM_UTILIZATION = 0.85;
2384
- var AUTO_MAX_WORKERS_CEILING = 64;
2194
+ import os2 from "node:os";
2195
+ import path9 from "node:path";
2385
2196
  function positiveInt(value, fallback) {
2386
2197
  const n = Number(value);
2387
2198
  if (!Number.isFinite(n) || n <= 0) return fallback;
@@ -2487,6 +2298,25 @@ function observeRunnerResourceGate(input) {
2487
2298
  ...diskGate ? { diskGate } : {}
2488
2299
  };
2489
2300
  }
2301
+ var DEFAULT_PER_WORKER_MEM_BYTES, DEFAULT_MEM_RESERVE_BYTES, DEFAULT_MEM_UTILIZATION, AUTO_MAX_WORKERS_CEILING;
2302
+ var init_resource_gate = __esm({
2303
+ "src/resource-gate.ts"() {
2304
+ "use strict";
2305
+ init_meminfo();
2306
+ init_config();
2307
+ init_box_identity();
2308
+ init_worker_cap_source();
2309
+ init_disk_gate();
2310
+ init_run_store();
2311
+ init_run_worker_index();
2312
+ init_harness_worker_active();
2313
+ init_util();
2314
+ DEFAULT_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
2315
+ DEFAULT_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
2316
+ DEFAULT_MEM_UTILIZATION = 0.85;
2317
+ AUTO_MAX_WORKERS_CEILING = 64;
2318
+ }
2319
+ });
2490
2320
 
2491
2321
  // src/worker-cap-source.ts
2492
2322
  function positiveInt2(value, fallback) {
@@ -2534,357 +2364,819 @@ function resolveWorkerCap(input) {
2534
2364
  workerCapSource: "env"
2535
2365
  };
2536
2366
  }
2537
- return {
2538
- configuredMaxWorkers: null,
2539
- autoCap,
2540
- workerCapSource: "auto"
2541
- };
2367
+ return {
2368
+ configuredMaxWorkers: null,
2369
+ autoCap,
2370
+ workerCapSource: "auto"
2371
+ };
2372
+ }
2373
+ function recommendSetupWorkerCap(input = {}) {
2374
+ const totalMemBytes = input.totalMemBytes ?? 0;
2375
+ const autoCap = computeAutoMaxWorkers(totalMemBytes, {
2376
+ perWorkerMemBytes: positiveInt2(input.config?.perWorkerMemBytes, DEFAULT_PER_WORKER_MEM_BYTES),
2377
+ memReserveBytes: positiveInt2(input.config?.memReserveBytes, DEFAULT_MEM_RESERVE_BYTES),
2378
+ memUtilization: input.config?.memUtilization && Number(input.config.memUtilization) > 0 ? Number(input.config.memUtilization) : DEFAULT_MEM_UTILIZATION
2379
+ });
2380
+ const diskGateOk = input.diskGateOk ?? true;
2381
+ const recommendedMaxWorkers = diskGateOk ? autoCap : Math.max(1, Math.min(autoCap, 4));
2382
+ return {
2383
+ totalMemBytes,
2384
+ autoCap,
2385
+ recommendedMaxWorkers,
2386
+ diskPath: input.diskPath ?? "/",
2387
+ diskGateOk,
2388
+ diskFreeBytes: input.diskFreeBytes ?? null
2389
+ };
2390
+ }
2391
+ var init_worker_cap_source = __esm({
2392
+ "src/worker-cap-source.ts"() {
2393
+ "use strict";
2394
+ init_resource_gate();
2395
+ }
2396
+ });
2397
+
2398
+ // src/device-login.ts
2399
+ var device_login_exports = {};
2400
+ __export(device_login_exports, {
2401
+ runDeviceLogin: () => runDeviceLogin
2402
+ });
2403
+ import os3 from "node:os";
2404
+ function resolveDeviceBaseUrl(args) {
2405
+ const raw = (typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : void 0) || (typeof args.baseUrl === "string" ? args.baseUrl : void 0) || process.env.KYNVER_API_URL || loadUserConfig().apiBaseUrl;
2406
+ return raw ? trimTrailingSlash(String(raw)) : void 0;
2407
+ }
2408
+ async function sleep(ms) {
2409
+ await new Promise((resolve2) => setTimeout(resolve2, ms));
2410
+ }
2411
+ async function runDeviceLogin(args) {
2412
+ const base = resolveDeviceBaseUrl(args);
2413
+ if (!base) {
2414
+ console.error(
2415
+ "kynver login (device flow) requires a Kynver URL \u2014 pass --api-base-url https://your-kynver-site, set KYNVER_API_URL, or run `kynver setup` first."
2416
+ );
2417
+ return { ok: false };
2418
+ }
2419
+ const clientName = `${os3.hostname()} (${os3.platform()})`;
2420
+ let start;
2421
+ try {
2422
+ const res = await fetch(`${base}/api/auth/device/code`, {
2423
+ method: "POST",
2424
+ headers: { "Content-Type": "application/json" },
2425
+ body: JSON.stringify({ clientName })
2426
+ });
2427
+ if (!res.ok) {
2428
+ console.error(`Could not start device authorization (${res.status}).`);
2429
+ return { ok: false };
2430
+ }
2431
+ start = await res.json();
2432
+ } catch (err) {
2433
+ console.error(`Could not reach ${base}: ${err.message}`);
2434
+ return { ok: false };
2435
+ }
2436
+ const verifyUrl = start.verification_uri_complete || start.verification_uri;
2437
+ console.log("");
2438
+ console.log(" Authorize this machine:");
2439
+ console.log(` 1. Open: ${verifyUrl}`);
2440
+ console.log(` 2. Confirm the code: ${start.user_code}`);
2441
+ console.log("");
2442
+ console.log(" Waiting for approval\u2026");
2443
+ const deadline = Date.now() + start.expires_in * 1e3;
2444
+ let intervalMs = Math.max(1, start.interval) * 1e3;
2445
+ while (Date.now() < deadline) {
2446
+ await sleep(intervalMs);
2447
+ let body;
2448
+ try {
2449
+ const res = await fetch(`${base}/api/auth/device/token`, {
2450
+ method: "POST",
2451
+ headers: { "Content-Type": "application/json" },
2452
+ body: JSON.stringify({ device_code: start.device_code })
2453
+ });
2454
+ body = await res.json().catch(() => ({}));
2455
+ } catch {
2456
+ continue;
2457
+ }
2458
+ switch (body.status) {
2459
+ case "approved":
2460
+ if (body.api_key) {
2461
+ saveApiKey(body.api_key);
2462
+ console.log(" Approved \u2014 this machine is now linked to your Kynver account.");
2463
+ return { ok: true, apiKey: body.api_key };
2464
+ }
2465
+ return { ok: false };
2466
+ case "slow_down":
2467
+ intervalMs += 2e3;
2468
+ break;
2469
+ case "authorization_pending":
2470
+ if (typeof body.interval === "number") intervalMs = Math.max(intervalMs, body.interval * 1e3);
2471
+ break;
2472
+ case "access_denied":
2473
+ console.error(" Request was denied in the browser.");
2474
+ return { ok: false };
2475
+ case "expired_token":
2476
+ console.error(" The code expired before it was approved. Run `kynver login` again.");
2477
+ return { ok: false };
2478
+ default:
2479
+ break;
2480
+ }
2481
+ }
2482
+ console.error(" Timed out waiting for approval. Run `kynver login` again.");
2483
+ return { ok: false };
2484
+ }
2485
+ var init_device_login = __esm({
2486
+ "src/device-login.ts"() {
2487
+ "use strict";
2488
+ init_config();
2489
+ init_util();
2490
+ }
2491
+ });
2492
+
2493
+ // src/config.ts
2494
+ import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync2 } from "node:fs";
2495
+ import { homedir as homedir5, totalmem } from "node:os";
2496
+ import path10 from "node:path";
2497
+ import os4 from "node:os";
2498
+ function loadUserConfig() {
2499
+ if (!existsSync11(CONFIG_FILE)) return {};
2500
+ try {
2501
+ return JSON.parse(readFileSync10(CONFIG_FILE, "utf8"));
2502
+ } catch {
2503
+ return {};
2504
+ }
2505
+ }
2506
+ function saveUserConfig(config) {
2507
+ mkdirSync2(CONFIG_DIR, { recursive: true });
2508
+ writeFileSync2(CONFIG_FILE, `${JSON.stringify(normalizeConfigPaths(config), null, 2)}
2509
+ `, { mode: 384 });
2510
+ }
2511
+ function normalizeConfigPaths(config) {
2512
+ return {
2513
+ ...config,
2514
+ ...config.harnessRoot?.trim() ? { harnessRoot: redactHomePath(config.harnessRoot.trim()) } : {},
2515
+ ...config.defaultRepo?.trim() ? { defaultRepo: redactHomePath(config.defaultRepo.trim()) } : {}
2516
+ };
2517
+ }
2518
+ function presentUserConfig(config) {
2519
+ return normalizeConfigPaths(config);
2520
+ }
2521
+ function inferSetupFields(existing, args) {
2522
+ const creds = loadCredentialsFile();
2523
+ const apiBaseUrl = (typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : void 0) || existing.apiBaseUrl?.trim() || process.env.KYNVER_API_URL?.trim() || process.env.KYNVER_CRON_FIRE_BASE_URL?.trim() || process.env.OPENCLAW_CRON_FIRE_BASE_URL?.trim();
2524
+ const agentOsId = (typeof args.agentOsId === "string" ? args.agentOsId : void 0) || existing.agentOsId?.trim() || process.env.KYNVER_AGENT_OS_ID?.trim() || (creds.runnerToken?.trim().startsWith("krc1.") ? creds.runnerTokenAgentOsId?.trim() : void 0);
2525
+ const explicitRepo = typeof args.repo === "string" ? args.repo : args.discoverRepo === true || args.discoverRepo === "true" ? discoverDefaultRepo()?.repo : void 0;
2526
+ const defaultRepo = explicitRepo || existing.defaultRepo?.trim() || process.env.KYNVER_DEFAULT_REPO?.trim() || process.env.KYNVER_HARNESS_REPO?.trim() || discoverDefaultRepo()?.repo;
2527
+ const harnessRoot = (typeof args.harnessRoot === "string" ? args.harnessRoot : void 0) || existing.harnessRoot?.trim() || process.env.KYNVER_HARNESS_ROOT?.trim() || process.env.OPUS_HARNESS_ROOT?.trim();
2528
+ return {
2529
+ ...apiBaseUrl ? { apiBaseUrl: trimTrailingSlash(apiBaseUrl) } : {},
2530
+ ...agentOsId ? { agentOsId } : {},
2531
+ ...defaultRepo ? { defaultRepo } : {},
2532
+ ...harnessRoot ? { harnessRoot } : {},
2533
+ ...typeof args.agentOsSlug === "string" ? { agentOsSlug: args.agentOsSlug } : existing.agentOsSlug ? { agentOsSlug: existing.agentOsSlug } : {}
2534
+ };
2535
+ }
2536
+ function resolveSetupWorkerConfig(existing, args, totalMemBytes = totalmem()) {
2537
+ const maxWorkersRaw = typeof args.maxWorkers === "string" ? args.maxWorkers : typeof args.maxConcurrentWorkers === "string" ? args.maxConcurrentWorkers : void 0;
2538
+ const explicitBoxKindArg = typeof args.boxKind === "string" ? args.boxKind : typeof args["box-kind"] === "string" ? String(args["box-kind"]) : void 0;
2539
+ const boxKind = resolveBoxIdentity(process.env, {
2540
+ ...existing,
2541
+ ...explicitBoxKindArg ? { boxKind: normalizeWorkerPoolBoxKind(explicitBoxKindArg) } : {}
2542
+ }).boxKind;
2543
+ const diskGate = observeRunnerDiskGate({
2544
+ diskPath: typeof args.diskPath === "string" ? args.diskPath : "/"
2545
+ });
2546
+ const capRecommendation = recommendSetupWorkerCap({
2547
+ totalMemBytes,
2548
+ diskPath: diskGate.path,
2549
+ diskGateOk: diskGate.ok,
2550
+ diskFreeBytes: diskGate.freeBytes,
2551
+ config: existing
2552
+ });
2553
+ if (maxWorkersRaw) {
2554
+ return {
2555
+ maxConcurrentWorkers: Math.max(1, Math.floor(Number(maxWorkersRaw))),
2556
+ maxConcurrentWorkersSource: "setup-flag",
2557
+ boxKind
2558
+ };
2559
+ }
2560
+ if (existing.maxConcurrentWorkers !== void 0 && existing.maxConcurrentWorkers !== null) {
2561
+ return {
2562
+ maxConcurrentWorkers: Math.max(1, Math.floor(Number(existing.maxConcurrentWorkers))),
2563
+ maxConcurrentWorkersSource: existing.maxConcurrentWorkersSource ?? "operator",
2564
+ boxKind
2565
+ };
2566
+ }
2567
+ return {
2568
+ maxConcurrentWorkers: capRecommendation.recommendedMaxWorkers,
2569
+ maxConcurrentWorkersSource: "setup-auto",
2570
+ boxKind
2571
+ };
2572
+ }
2573
+ function loadCredentialsFile() {
2574
+ if (!existsSync11(CREDENTIALS_FILE)) return {};
2575
+ try {
2576
+ return JSON.parse(readFileSync10(CREDENTIALS_FILE, "utf8"));
2577
+ } catch {
2578
+ return {};
2579
+ }
2580
+ }
2581
+ function saveCredentialsFile(parsed) {
2582
+ mkdirSync2(CONFIG_DIR, { recursive: true });
2583
+ writeFileSync2(CREDENTIALS_FILE, `${JSON.stringify(parsed, null, 2)}
2584
+ `, { mode: 384 });
2585
+ }
2586
+ function loadApiKey() {
2587
+ if (process.env.KYNVER_API_KEY) return process.env.KYNVER_API_KEY;
2588
+ return loadCredentialsFile().apiKey;
2589
+ }
2590
+ function saveApiKey(apiKey) {
2591
+ saveCredentialsFile({ ...loadCredentialsFile(), apiKey });
2592
+ }
2593
+ function loadRunnerToken(agentOsId) {
2594
+ const envToken = process.env.KYNVER_RUNNER_TOKEN?.trim();
2595
+ if (envToken) return envToken;
2596
+ const creds = loadCredentialsFile();
2597
+ if (!creds.runnerToken) return void 0;
2598
+ if (agentOsId && creds.runnerTokenAgentOsId && creds.runnerTokenAgentOsId !== agentOsId) {
2599
+ return void 0;
2600
+ }
2601
+ return creds.runnerToken;
2602
+ }
2603
+ function saveRunnerToken(agentOsId, token) {
2604
+ saveCredentialsFile({
2605
+ ...loadCredentialsFile(),
2606
+ runnerToken: token,
2607
+ runnerTokenAgentOsId: agentOsId
2608
+ });
2609
+ }
2610
+ function resolveBaseUrl(argsBaseUrl) {
2611
+ const baseUrl = resolveConfiguredBaseUrl(argsBaseUrl);
2612
+ if (!baseUrl) failConfig("requires --base-url, KYNVER_API_URL, KYNVER_CRON_FIRE_BASE_URL, or ~/.kynver/config.json apiBaseUrl");
2613
+ return baseUrl;
2614
+ }
2615
+ function resolveConfiguredBaseUrl(argsBaseUrl) {
2616
+ const baseUrl = argsBaseUrl || process.env.KYNVER_API_URL || process.env.KYNVER_CRON_FIRE_BASE_URL || process.env.OPENCLAW_CRON_FIRE_BASE_URL || loadUserConfig().apiBaseUrl;
2617
+ return baseUrl ? trimTrailingSlash(String(baseUrl)) : void 0;
2618
+ }
2619
+ function resolveConfiguredCallbackSecret(argsSecret, agentOsId) {
2620
+ const scoped = argsSecret || loadRunnerToken(agentOsId) || (agentOsId ? void 0 : loadRunnerToken(loadUserConfig().agentOsId));
2621
+ if (scoped) return String(scoped);
2622
+ const globalSecret = process.env.KYNVER_RUNTIME_SECRET || process.env.KYNVER_CRON_SECRET || process.env.OPENCLAW_CRON_SECRET;
2623
+ if (globalSecret) {
2624
+ console.warn(
2625
+ "[kynver] using deployment-level callback secret; run `kynver runner credential --agent-os-id <id>` for a scoped token"
2626
+ );
2627
+ return String(globalSecret);
2628
+ }
2629
+ return void 0;
2630
+ }
2631
+ function resolveCallbackSecret(argsSecret, agentOsId) {
2632
+ const configured = resolveConfiguredCallbackSecret(argsSecret, agentOsId);
2633
+ if (configured) return configured;
2634
+ failConfig(
2635
+ "requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
2636
+ );
2637
+ }
2638
+ async function resolveCallbackSecretWithMint(argsSecret, agentOsId, opts) {
2639
+ const configured = resolveConfiguredCallbackSecret(argsSecret, agentOsId);
2640
+ if (configured) return configured;
2641
+ const apiKey = loadApiKey();
2642
+ const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
2643
+ if (apiKey && agentOsId && baseUrl) {
2644
+ try {
2645
+ const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
2646
+ saveRunnerToken(agentOsId, token);
2647
+ return token;
2648
+ } catch (error) {
2649
+ failConfig(`runner credential mint failed: ${error.message}`);
2650
+ }
2651
+ }
2652
+ failConfig(
2653
+ "requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
2654
+ );
2655
+ }
2656
+ async function refreshRunnerToken(agentOsId, opts) {
2657
+ const apiKey = loadApiKey();
2658
+ const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
2659
+ if (!apiKey || !agentOsId || !baseUrl) return null;
2660
+ try {
2661
+ const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
2662
+ saveRunnerToken(agentOsId, token);
2663
+ return token;
2664
+ } catch {
2665
+ return null;
2666
+ }
2667
+ }
2668
+ async function refreshRunnerTokenForAuthFailure(rejectedSecret, agentOsId, opts) {
2669
+ const apiKey = loadApiKey();
2670
+ const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
2671
+ if (!apiKey) return { ok: false, reason: "KYNVER_API_KEY is required to refresh a rejected runner token" };
2672
+ if (!agentOsId) return { ok: false, reason: "agentOsId is required to refresh a rejected runner token" };
2673
+ if (!baseUrl) return { ok: false, reason: "KYNVER_API_URL or --base-url is required to refresh a rejected runner token" };
2674
+ try {
2675
+ const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
2676
+ if (token && token !== rejectedSecret) {
2677
+ saveRunnerToken(agentOsId, token);
2678
+ return { ok: true, token };
2679
+ }
2680
+ return { ok: false, reason: "runner credential refresh returned the rejected token" };
2681
+ } catch (error) {
2682
+ return { ok: false, reason: error.message };
2683
+ }
2542
2684
  }
2543
- function recommendSetupWorkerCap(input = {}) {
2544
- const totalMemBytes = input.totalMemBytes ?? 0;
2545
- const autoCap = computeAutoMaxWorkers(totalMemBytes, {
2546
- perWorkerMemBytes: positiveInt2(input.config?.perWorkerMemBytes, DEFAULT_PER_WORKER_MEM_BYTES),
2547
- memReserveBytes: positiveInt2(input.config?.memReserveBytes, DEFAULT_MEM_RESERVE_BYTES),
2548
- memUtilization: input.config?.memUtilization && Number(input.config.memUtilization) > 0 ? Number(input.config.memUtilization) : DEFAULT_MEM_UTILIZATION
2685
+ async function fetchRunnerCredential(agentOsId, opts) {
2686
+ const apiKey = opts?.apiKey || loadApiKey();
2687
+ if (!apiKey) throw new Error("API key required \u2014 run `kynver login` first");
2688
+ const base = resolveBaseUrl(opts?.baseUrl);
2689
+ const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/runner-credentials`;
2690
+ const res = await fetch(url, {
2691
+ method: "POST",
2692
+ headers: {
2693
+ "Content-Type": "application/json",
2694
+ Authorization: `Bearer ${apiKey}`
2695
+ },
2696
+ body: JSON.stringify({})
2549
2697
  });
2550
- const diskGateOk = input.diskGateOk ?? true;
2551
- const recommendedMaxWorkers = diskGateOk ? autoCap : Math.max(1, Math.min(autoCap, 4));
2552
- return {
2553
- totalMemBytes,
2554
- autoCap,
2555
- recommendedMaxWorkers,
2556
- diskPath: input.diskPath ?? "/",
2557
- diskGateOk,
2558
- diskFreeBytes: input.diskFreeBytes ?? null
2559
- };
2560
- }
2561
-
2562
- // src/config.ts
2563
- import os3 from "node:os";
2564
- var CONFIG_DIR = path10.join(homedir5(), ".kynver");
2565
- var CONFIG_FILE = path10.join(CONFIG_DIR, "config.json");
2566
- var CREDENTIALS_FILE = path10.join(CONFIG_DIR, "credentials");
2567
- function loadUserConfig() {
2568
- if (!existsSync11(CONFIG_FILE)) return {};
2698
+ const text = await res.text();
2699
+ let parsed = null;
2569
2700
  try {
2570
- return JSON.parse(readFileSync10(CONFIG_FILE, "utf8"));
2701
+ parsed = JSON.parse(text);
2571
2702
  } catch {
2572
- return {};
2703
+ parsed = null;
2573
2704
  }
2705
+ if (!res.ok || !parsed?.token) {
2706
+ throw new Error(
2707
+ `runner credential mint failed (${res.status}): ${parsed?.error ?? text.slice(0, 200)}`
2708
+ );
2709
+ }
2710
+ return parsed.token;
2574
2711
  }
2575
- function saveUserConfig(config) {
2576
- mkdirSync2(CONFIG_DIR, { recursive: true });
2577
- writeFileSync2(CONFIG_FILE, `${JSON.stringify(normalizeConfigPaths(config), null, 2)}
2578
- `, { mode: 384 });
2579
- }
2580
- function normalizeConfigPaths(config) {
2581
- return {
2582
- ...config,
2583
- ...config.harnessRoot?.trim() ? { harnessRoot: redactHomePath(config.harnessRoot.trim()) } : {},
2584
- ...config.defaultRepo?.trim() ? { defaultRepo: redactHomePath(config.defaultRepo.trim()) } : {}
2585
- };
2712
+ async function mintRunnerCredential(args) {
2713
+ const agentOsId = (args.agentOsId ? String(args.agentOsId) : loadUserConfig().agentOsId) || "";
2714
+ if (!agentOsId) failConfig("runner credential requires --agent-os-id or agentOsId in ~/.kynver/config.json");
2715
+ try {
2716
+ const token = await fetchRunnerCredential(agentOsId, {
2717
+ baseUrl: args.baseUrl ? String(args.baseUrl) : void 0
2718
+ });
2719
+ saveRunnerToken(agentOsId, token);
2720
+ console.log(
2721
+ JSON.stringify(
2722
+ {
2723
+ ok: true,
2724
+ agentOsId,
2725
+ credentialsPath: displayUserPath(CREDENTIALS_FILE),
2726
+ tokenPrefix: `${token.slice(0, 12)}\u2026`,
2727
+ note: "Scoped runner token saved; callbacks use X-Kynver-Runner-Token."
2728
+ },
2729
+ null,
2730
+ 2
2731
+ )
2732
+ );
2733
+ } catch (err) {
2734
+ console.error(err instanceof Error ? err.message : String(err));
2735
+ process.exit(1);
2736
+ }
2586
2737
  }
2587
- function presentUserConfig(config) {
2588
- return normalizeConfigPaths(config);
2738
+ function failConfig(message) {
2739
+ console.error(message);
2740
+ process.exit(1);
2589
2741
  }
2590
- function inferSetupFields(existing, args) {
2591
- const creds = loadCredentialsFile();
2592
- const apiBaseUrl = (typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : void 0) || existing.apiBaseUrl?.trim() || process.env.KYNVER_API_URL?.trim() || process.env.KYNVER_CRON_FIRE_BASE_URL?.trim() || process.env.OPENCLAW_CRON_FIRE_BASE_URL?.trim();
2593
- const agentOsId = (typeof args.agentOsId === "string" ? args.agentOsId : void 0) || existing.agentOsId?.trim() || process.env.KYNVER_AGENT_OS_ID?.trim() || (creds.runnerToken?.trim().startsWith("krc1.") ? creds.runnerTokenAgentOsId?.trim() : void 0);
2594
- const explicitRepo = typeof args.repo === "string" ? args.repo : args.discoverRepo === true || args.discoverRepo === "true" ? discoverDefaultRepo()?.repo : void 0;
2595
- const defaultRepo = explicitRepo || existing.defaultRepo?.trim() || process.env.KYNVER_DEFAULT_REPO?.trim() || process.env.KYNVER_HARNESS_REPO?.trim() || discoverDefaultRepo()?.repo;
2596
- const harnessRoot = (typeof args.harnessRoot === "string" ? args.harnessRoot : void 0) || existing.harnessRoot?.trim() || process.env.KYNVER_HARNESS_ROOT?.trim() || process.env.OPUS_HARNESS_ROOT?.trim();
2597
- return {
2598
- ...apiBaseUrl ? { apiBaseUrl: trimTrailingSlash(apiBaseUrl) } : {},
2599
- ...agentOsId ? { agentOsId } : {},
2600
- ...defaultRepo ? { defaultRepo } : {},
2601
- ...harnessRoot ? { harnessRoot } : {},
2602
- ...typeof args.agentOsSlug === "string" ? { agentOsSlug: args.agentOsSlug } : existing.agentOsSlug ? { agentOsSlug: existing.agentOsSlug } : {}
2603
- };
2742
+ function parseArgs(argv) {
2743
+ const args = {};
2744
+ for (let i = 0; i < argv.length; i++) {
2745
+ const item = argv[i];
2746
+ if (!item.startsWith("--")) continue;
2747
+ const key = item.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
2748
+ const next = argv[i + 1];
2749
+ if (!next || next.startsWith("--")) args[key] = true;
2750
+ else {
2751
+ args[key] = next;
2752
+ i++;
2753
+ }
2754
+ }
2755
+ return args;
2604
2756
  }
2605
- var SETUP_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
2606
- var SETUP_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
2607
- function resolveSetupWorkerConfig(existing, args, totalMemBytes = totalmem()) {
2608
- const maxWorkersRaw = typeof args.maxWorkers === "string" ? args.maxWorkers : typeof args.maxConcurrentWorkers === "string" ? args.maxConcurrentWorkers : void 0;
2609
- const explicitBoxKindArg = typeof args.boxKind === "string" ? args.boxKind : typeof args["box-kind"] === "string" ? String(args["box-kind"]) : void 0;
2610
- const boxKind = resolveBoxIdentity(process.env, {
2611
- ...existing,
2612
- ...explicitBoxKindArg ? { boxKind: normalizeWorkerPoolBoxKind(explicitBoxKindArg) } : {}
2613
- }).boxKind;
2757
+ async function runSetup(args) {
2758
+ const existing = loadUserConfig();
2614
2759
  const diskGate = observeRunnerDiskGate({
2615
2760
  diskPath: typeof args.diskPath === "string" ? args.diskPath : "/"
2616
2761
  });
2617
2762
  const capRecommendation = recommendSetupWorkerCap({
2618
- totalMemBytes,
2763
+ totalMemBytes: os4.totalmem(),
2619
2764
  diskPath: diskGate.path,
2620
2765
  diskGateOk: diskGate.ok,
2621
2766
  diskFreeBytes: diskGate.freeBytes,
2622
2767
  config: existing
2623
2768
  });
2624
- if (maxWorkersRaw) {
2625
- return {
2626
- maxConcurrentWorkers: Math.max(1, Math.floor(Number(maxWorkersRaw))),
2627
- maxConcurrentWorkersSource: "setup-flag",
2628
- boxKind
2629
- };
2769
+ const workerConfig = resolveSetupWorkerConfig(existing, args);
2770
+ const config = normalizeConfigPaths({
2771
+ ...existing,
2772
+ ...inferSetupFields(existing, args),
2773
+ ...workerConfig,
2774
+ workerProvider: typeof args.provider === "string" ? args.provider : existing.workerProvider || "cursor"
2775
+ });
2776
+ saveUserConfig(config);
2777
+ const boxIdentity = resolveBoxIdentity(process.env, config);
2778
+ let runnerCredentialNote;
2779
+ const apiKey = loadApiKey();
2780
+ const agentOsId = config.agentOsId;
2781
+ if (apiKey && agentOsId) {
2782
+ try {
2783
+ const token = await fetchRunnerCredential(agentOsId, {
2784
+ baseUrl: typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : config.apiBaseUrl,
2785
+ apiKey
2786
+ });
2787
+ saveRunnerToken(agentOsId, token);
2788
+ runnerCredentialNote = "Scoped runner token minted and saved to ~/.kynver/credentials.";
2789
+ } catch {
2790
+ runnerCredentialNote = "Runner token not minted (server offline or master secret unset). Run `kynver runner credential` after deploy.";
2791
+ }
2792
+ }
2793
+ console.log(
2794
+ JSON.stringify(
2795
+ {
2796
+ ok: true,
2797
+ configPath: displayUserPath(CONFIG_FILE),
2798
+ config: presentUserConfig(config),
2799
+ boxKind: config.boxKind,
2800
+ boxKindSource: boxIdentity.source,
2801
+ workerCapRecommendation: capRecommendation,
2802
+ ...boxIdentity.warnings.length ? { boxIdentityWarnings: boxIdentity.warnings } : {},
2803
+ note: runnerCredentialNote ?? "boxKind and maxConcurrentWorkers persisted; override with --box-kind and --max-workers. Run `kynver login` + `kynver runner credential` for scoped callbacks."
2804
+ },
2805
+ null,
2806
+ 2
2807
+ )
2808
+ );
2809
+ }
2810
+ async function runLogin(args) {
2811
+ const apiKey = typeof args.apiKey === "string" ? args.apiKey : process.env.KYNVER_API_KEY;
2812
+ if (apiKey) {
2813
+ saveApiKey(apiKey);
2814
+ console.log(JSON.stringify({ ok: true, credentialsPath: displayUserPath(CREDENTIALS_FILE) }, null, 2));
2815
+ return;
2816
+ }
2817
+ const { runDeviceLogin: runDeviceLogin2 } = await Promise.resolve().then(() => (init_device_login(), device_login_exports));
2818
+ const result = await runDeviceLogin2(args);
2819
+ if (!result.ok) process.exit(1);
2820
+ console.log(JSON.stringify({ ok: true, credentialsPath: displayUserPath(CREDENTIALS_FILE) }, null, 2));
2821
+ }
2822
+ var CONFIG_DIR, CONFIG_FILE, CREDENTIALS_FILE, SETUP_PER_WORKER_MEM_BYTES, SETUP_MEM_RESERVE_BYTES;
2823
+ var init_config = __esm({
2824
+ "src/config.ts"() {
2825
+ "use strict";
2826
+ init_default_repo_discovery();
2827
+ init_path_values();
2828
+ init_util();
2829
+ init_box_identity();
2830
+ init_worker_cap_source();
2831
+ init_disk_gate();
2832
+ CONFIG_DIR = path10.join(homedir5(), ".kynver");
2833
+ CONFIG_FILE = path10.join(CONFIG_DIR, "config.json");
2834
+ CREDENTIALS_FILE = path10.join(CONFIG_DIR, "credentials");
2835
+ SETUP_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
2836
+ SETUP_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
2837
+ }
2838
+ });
2839
+
2840
+ // src/package-version.ts
2841
+ import { existsSync, readFileSync } from "node:fs";
2842
+ import { dirname, join } from "node:path";
2843
+ import { fileURLToPath } from "node:url";
2844
+ function resolvePackageRoot(moduleUrl) {
2845
+ let dir = dirname(fileURLToPath(moduleUrl));
2846
+ for (let depth = 0; depth < 6; depth += 1) {
2847
+ if (existsSync(join(dir, "package.json"))) return dir;
2848
+ const parent = dirname(dir);
2849
+ if (parent === dir) break;
2850
+ dir = parent;
2851
+ }
2852
+ throw new Error(`package.json not found above ${dirname(fileURLToPath(moduleUrl))}`);
2853
+ }
2854
+ function readOwnPackageVersion(moduleUrl = import.meta.url) {
2855
+ const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
2856
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
2857
+ if (typeof pkg.version !== "string" || !pkg.version.trim()) {
2858
+ throw new Error(`Missing package.json version at ${pkgPath}`);
2859
+ }
2860
+ return pkg.version;
2861
+ }
2862
+ var PACKAGE_VERSION = readOwnPackageVersion();
2863
+ function wantsCliVersion(argv) {
2864
+ return argv.some((arg) => arg === "--version" || arg === "-v");
2865
+ }
2866
+ function printCliVersionAndExit(version, binName) {
2867
+ console.log(binName ? `${binName} ${version}` : version);
2868
+ process.exit(0);
2869
+ }
2870
+ function handleCliVersionFlag(argv, moduleUrl = import.meta.url, binName) {
2871
+ if (!wantsCliVersion(argv)) return false;
2872
+ printCliVersionAndExit(readOwnPackageVersion(moduleUrl), binName);
2873
+ return true;
2874
+ }
2875
+
2876
+ // src/memory-cost-package-version-guard.ts
2877
+ init_default_repo_discovery();
2878
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
2879
+ import path4 from "node:path";
2880
+ var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
2881
+ "@kynver-app/runtime": "0.1.83",
2882
+ "@kynver-app/openclaw-agent-os": "0.1.43",
2883
+ "@kynver-app/mcp-agent-os": "0.3.34"
2884
+ };
2885
+ var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
2886
+ MEMORY_COST_PACKAGE_MIN_VERSIONS
2887
+ );
2888
+ var DISPLAY_NAMES = {
2889
+ "@kynver-app/runtime": "Kynver runtime",
2890
+ "@kynver-app/openclaw-agent-os": "OpenClaw AgentOS plugin",
2891
+ "@kynver-app/mcp-agent-os": "AgentOS MCP server"
2892
+ };
2893
+ var REPO_PACKAGE_JSON_RELATIVE = {
2894
+ "@kynver-app/runtime": "packages/kynver-runtime/package.json",
2895
+ "@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
2896
+ "@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
2897
+ };
2898
+ function parseSemverParts(version) {
2899
+ const core = version.trim().split("-")[0]?.split("+")[0];
2900
+ if (!core) return null;
2901
+ const parts = core.split(".");
2902
+ if (parts.length < 1 || parts.length > 3) return null;
2903
+ const nums = parts.map((p) => Number.parseInt(p, 10));
2904
+ if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
2905
+ while (nums.length < 3) nums.push(0);
2906
+ return [nums[0], nums[1], nums[2]];
2907
+ }
2908
+ function compareSemver(a, b) {
2909
+ const pa = parseSemverParts(a);
2910
+ const pb = parseSemverParts(b);
2911
+ if (!pa || !pb) return 0;
2912
+ for (let i = 0; i < 3; i += 1) {
2913
+ if (pa[i] > pb[i]) return 1;
2914
+ if (pa[i] < pb[i]) return -1;
2630
2915
  }
2631
- if (existing.maxConcurrentWorkers !== void 0 && existing.maxConcurrentWorkers !== null) {
2632
- return {
2633
- maxConcurrentWorkers: Math.max(1, Math.floor(Number(existing.maxConcurrentWorkers))),
2634
- maxConcurrentWorkersSource: existing.maxConcurrentWorkersSource ?? "operator",
2635
- boxKind
2636
- };
2916
+ return 0;
2917
+ }
2918
+ function semverAtLeast(version, minimum) {
2919
+ return compareSemver(version, minimum) >= 0;
2920
+ }
2921
+ function maxSemver(versions) {
2922
+ let best = null;
2923
+ for (const version of versions) {
2924
+ if (!best || compareSemver(version, best) > 0) best = version;
2637
2925
  }
2638
- return {
2639
- maxConcurrentWorkers: capRecommendation.recommendedMaxWorkers,
2640
- maxConcurrentWorkersSource: "setup-auto",
2641
- boxKind
2642
- };
2926
+ return best;
2643
2927
  }
2644
- function loadCredentialsFile() {
2645
- if (!existsSync11(CREDENTIALS_FILE)) return {};
2928
+ function readPackageJsonVersion(packageJsonPath) {
2646
2929
  try {
2647
- return JSON.parse(readFileSync10(CREDENTIALS_FILE, "utf8"));
2930
+ const parsed = JSON.parse(readFileSync4(packageJsonPath, "utf8"));
2931
+ return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
2648
2932
  } catch {
2649
- return {};
2933
+ return null;
2650
2934
  }
2651
2935
  }
2652
- function saveCredentialsFile(parsed) {
2653
- mkdirSync2(CONFIG_DIR, { recursive: true });
2654
- writeFileSync2(CREDENTIALS_FILE, `${JSON.stringify(parsed, null, 2)}
2655
- `, { mode: 384 });
2656
- }
2657
- function loadApiKey() {
2658
- if (process.env.KYNVER_API_KEY) return process.env.KYNVER_API_KEY;
2659
- return loadCredentialsFile().apiKey;
2936
+ function resolveRepoRoot(cwd, explicitRepoRoot) {
2937
+ const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(
2938
+ (value) => Boolean(value?.trim())
2939
+ );
2940
+ for (const candidate of candidates) {
2941
+ const resolved = path4.resolve(candidate);
2942
+ if (existsSync4(path4.join(resolved, "packages/kynver-runtime/package.json")) && existsSync4(path4.join(resolved, "package.json"))) {
2943
+ return resolved;
2944
+ }
2945
+ }
2946
+ const discovered = discoverDefaultRepo({ cwd });
2947
+ return discovered?.repo ?? null;
2660
2948
  }
2661
- function saveApiKey(apiKey) {
2662
- saveCredentialsFile({ ...loadCredentialsFile(), apiKey });
2949
+ function probeRepoPackageVersions(input = {}) {
2950
+ const cwd = input.cwd ?? process.cwd();
2951
+ const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
2952
+ if (!repoRoot) return {};
2953
+ const out = {};
2954
+ for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
2955
+ const packageJsonPath = path4.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
2956
+ const version = readPackageJsonVersion(packageJsonPath);
2957
+ if (!version) continue;
2958
+ out[packageName] = { version, source: "repo", path: packageJsonPath };
2959
+ }
2960
+ return out;
2663
2961
  }
2664
- function loadRunnerToken(agentOsId) {
2665
- const envToken = process.env.KYNVER_RUNNER_TOKEN?.trim();
2666
- if (envToken) return envToken;
2667
- const creds = loadCredentialsFile();
2668
- if (!creds.runnerToken) return void 0;
2669
- if (agentOsId && creds.runnerTokenAgentOsId && creds.runnerTokenAgentOsId !== agentOsId) {
2670
- return void 0;
2962
+ function repoSourceCommands(packageName) {
2963
+ if (packageName === "@kynver-app/runtime") {
2964
+ return ["npm run kynver:build", "npm run kynver"];
2671
2965
  }
2672
- return creds.runnerToken;
2966
+ return [`npm run build -w ${packageName}`];
2673
2967
  }
2674
- function saveRunnerToken(agentOsId, token) {
2675
- saveCredentialsFile({
2676
- ...loadCredentialsFile(),
2677
- runnerToken: token,
2678
- runnerTokenAgentOsId: agentOsId
2679
- });
2968
+ function buildRemediation(input) {
2969
+ const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;
2970
+ const lines = [];
2971
+ if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {
2972
+ lines.push(
2973
+ `Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join("; ")}.`
2974
+ );
2975
+ lines.push("Do not publish npm packages or wait on an operator release.");
2976
+ return lines;
2977
+ }
2978
+ if (effectiveVersion) {
2979
+ lines.push(
2980
+ `Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`
2981
+ );
2982
+ } else {
2983
+ lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);
2984
+ }
2985
+ if (packageName === "@kynver-app/runtime") {
2986
+ lines.push("Repo-source alternative: npm run kynver:build && npm run kynver");
2987
+ }
2988
+ if (effectiveSource === "installed" && repoVersion) {
2989
+ lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);
2990
+ }
2991
+ return lines;
2680
2992
  }
2681
- function resolveBaseUrl(argsBaseUrl) {
2682
- const baseUrl = resolveConfiguredBaseUrl(argsBaseUrl);
2683
- if (!baseUrl) failConfig("requires --base-url, KYNVER_API_URL, KYNVER_CRON_FIRE_BASE_URL, or ~/.kynver/config.json apiBaseUrl");
2684
- return baseUrl;
2993
+ function pickEffectiveCandidate(candidates) {
2994
+ if (candidates.length === 0) return { version: null, source: "unknown" };
2995
+ const best = maxSemver(candidates.map((candidate) => candidate.version));
2996
+ if (!best) return { version: null, source: "unknown" };
2997
+ const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
2998
+ return { version: winner.version, source: winner.source };
2685
2999
  }
2686
- function resolveConfiguredBaseUrl(argsBaseUrl) {
2687
- const baseUrl = argsBaseUrl || process.env.KYNVER_API_URL || process.env.KYNVER_CRON_FIRE_BASE_URL || process.env.OPENCLAW_CRON_FIRE_BASE_URL || loadUserConfig().apiBaseUrl;
2688
- return baseUrl ? trimTrailingSlash(String(baseUrl)) : void 0;
3000
+ function evaluateMemoryCostPackageVersionGuard(input = {}) {
3001
+ const normalize2 = (value, fallbackSource) => {
3002
+ if (!value) return null;
3003
+ if (typeof value === "string") return { version: value, source: fallbackSource };
3004
+ return value;
3005
+ };
3006
+ const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
3007
+ const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
3008
+ const candidates = [];
3009
+ const installed = normalize2(input.installed?.[packageName], "installed");
3010
+ const repo = normalize2(input.repo?.[packageName], "repo");
3011
+ const self = normalize2(input.self?.[packageName], "self");
3012
+ if (installed) candidates.push(installed);
3013
+ if (repo) candidates.push(repo);
3014
+ if (self) candidates.push(self);
3015
+ const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
3016
+ const repoVersion = repo?.version ?? null;
3017
+ const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
3018
+ const remediation = ok2 ? [] : buildRemediation({
3019
+ packageName,
3020
+ minimumVersion,
3021
+ effectiveVersion,
3022
+ effectiveSource,
3023
+ repoVersion
3024
+ });
3025
+ 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)") + ".";
3026
+ return {
3027
+ packageName,
3028
+ displayName: DISPLAY_NAMES[packageName],
3029
+ minimumVersion,
3030
+ effectiveVersion,
3031
+ effectiveSource,
3032
+ ok: ok2,
3033
+ summary: summary2,
3034
+ remediation
3035
+ };
3036
+ });
3037
+ const violations = packages.filter((row) => !row.ok);
3038
+ const ok = violations.length === 0;
3039
+ 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("; ")}.`;
3040
+ return { ok, summary, packages };
2689
3041
  }
2690
- function resolveConfiguredCallbackSecret(argsSecret, agentOsId) {
2691
- const scoped = argsSecret || loadRunnerToken(agentOsId) || (agentOsId ? void 0 : loadRunnerToken(loadUserConfig().agentOsId));
2692
- if (scoped) return String(scoped);
2693
- const globalSecret = process.env.KYNVER_RUNTIME_SECRET || process.env.KYNVER_CRON_SECRET || process.env.OPENCLAW_CRON_SECRET;
2694
- if (globalSecret) {
2695
- console.warn(
2696
- "[kynver] using deployment-level callback secret; run `kynver runner credential --agent-os-id <id>` for a scoped token"
2697
- );
2698
- return String(globalSecret);
3042
+ var MemoryCostPackageVersionGuardError = class extends Error {
3043
+ result;
3044
+ constructor(result) {
3045
+ const lines = [
3046
+ result.summary,
3047
+ ...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
3048
+ ];
3049
+ super(lines.join("\n"));
3050
+ this.name = "MemoryCostPackageVersionGuardError";
3051
+ this.result = result;
2699
3052
  }
2700
- return void 0;
3053
+ };
3054
+ function assertMemoryCostPackageVersionGuard(input = {}) {
3055
+ const result = evaluateMemoryCostPackageVersionGuard(input);
3056
+ if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
3057
+ return result;
2701
3058
  }
2702
- function resolveCallbackSecret(argsSecret, agentOsId) {
2703
- const configured = resolveConfiguredCallbackSecret(argsSecret, agentOsId);
2704
- if (configured) return configured;
2705
- failConfig(
2706
- "requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
2707
- );
3059
+ function formatMemoryCostPackageGuardError(result) {
3060
+ return new MemoryCostPackageVersionGuardError(result).message;
2708
3061
  }
2709
- async function resolveCallbackSecretWithMint(argsSecret, agentOsId, opts) {
2710
- const configured = resolveConfiguredCallbackSecret(argsSecret, agentOsId);
2711
- if (configured) return configured;
2712
- const apiKey = loadApiKey();
2713
- const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
2714
- if (apiKey && agentOsId && baseUrl) {
2715
- try {
2716
- const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
2717
- saveRunnerToken(agentOsId, token);
2718
- return token;
2719
- } catch (error) {
2720
- failConfig(`runner credential mint failed: ${error.message}`);
2721
- }
2722
- }
2723
- failConfig(
2724
- "requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
2725
- );
3062
+
3063
+ // src/installed-package-versions.ts
3064
+ import { readFile } from "node:fs/promises";
3065
+ import { homedir as homedir3 } from "node:os";
3066
+ import path5 from "node:path";
3067
+ var MANAGED_PACKAGES = [
3068
+ "@kynver-app/runtime",
3069
+ "@kynver-app/openclaw-agent-os",
3070
+ "@kynver-app/mcp-agent-os"
3071
+ ];
3072
+ function trim(value) {
3073
+ const out = value?.trim();
3074
+ return out ? out : null;
2726
3075
  }
2727
- async function refreshRunnerToken(agentOsId, opts) {
2728
- const apiKey = loadApiKey();
2729
- const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
2730
- if (!apiKey || !agentOsId || !baseUrl) return null;
2731
- try {
2732
- const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
2733
- saveRunnerToken(agentOsId, token);
2734
- return token;
2735
- } catch {
2736
- return null;
2737
- }
3076
+ function unique(values) {
3077
+ return [...new Set(values.filter((value) => Boolean(value)))];
2738
3078
  }
2739
- async function refreshRunnerTokenForAuthFailure(rejectedSecret, agentOsId, opts) {
2740
- const apiKey = loadApiKey();
2741
- const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
2742
- if (!apiKey) return { ok: false, reason: "KYNVER_API_KEY is required to refresh a rejected runner token" };
2743
- if (!agentOsId) return { ok: false, reason: "agentOsId is required to refresh a rejected runner token" };
2744
- if (!baseUrl) return { ok: false, reason: "KYNVER_API_URL or --base-url is required to refresh a rejected runner token" };
2745
- try {
2746
- const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
2747
- if (token && token !== rejectedSecret) {
2748
- saveRunnerToken(agentOsId, token);
2749
- return { ok: true, token };
2750
- }
2751
- return { ok: false, reason: "runner credential refresh returned the rejected token" };
2752
- } catch (error) {
2753
- return { ok: false, reason: error.message };
2754
- }
3079
+ function moduleRoots() {
3080
+ const home = homedir3();
3081
+ const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path5.join(home, ".openclaw", "npm");
3082
+ const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path5.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path5.join(home, ".npm-global", "lib", "node_modules"));
3083
+ return unique([
3084
+ path5.join(openClawPrefix, "lib", "node_modules"),
3085
+ path5.join(openClawPrefix, "node_modules"),
3086
+ npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path5.join(npmGlobalRoot, "lib", "node_modules")
3087
+ ]);
2755
3088
  }
2756
- async function fetchRunnerCredential(agentOsId, opts) {
2757
- const apiKey = opts?.apiKey || loadApiKey();
2758
- if (!apiKey) throw new Error("API key required \u2014 run `kynver login` first");
2759
- const base = resolveBaseUrl(opts?.baseUrl);
2760
- const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/runner-credentials`;
2761
- const res = await fetch(url, {
2762
- method: "POST",
2763
- headers: {
2764
- "Content-Type": "application/json",
2765
- Authorization: `Bearer ${apiKey}`
2766
- },
2767
- body: JSON.stringify({})
2768
- });
2769
- const text = await res.text();
2770
- let parsed = null;
3089
+ async function readVersion(packageJsonPath) {
2771
3090
  try {
2772
- parsed = JSON.parse(text);
3091
+ const parsed = JSON.parse(await readFile(packageJsonPath, "utf8"));
3092
+ return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
2773
3093
  } catch {
2774
- parsed = null;
2775
- }
2776
- if (!res.ok || !parsed?.token) {
2777
- throw new Error(
2778
- `runner credential mint failed (${res.status}): ${parsed?.error ?? text.slice(0, 200)}`
2779
- );
3094
+ return null;
2780
3095
  }
2781
- return parsed.token;
2782
3096
  }
2783
- async function mintRunnerCredential(args) {
2784
- const agentOsId = (args.agentOsId ? String(args.agentOsId) : loadUserConfig().agentOsId) || "";
2785
- if (!agentOsId) failConfig("runner credential requires --agent-os-id or agentOsId in ~/.kynver/config.json");
2786
- try {
2787
- const token = await fetchRunnerCredential(agentOsId, {
2788
- baseUrl: args.baseUrl ? String(args.baseUrl) : void 0
2789
- });
2790
- saveRunnerToken(agentOsId, token);
2791
- console.log(
2792
- JSON.stringify(
2793
- {
2794
- ok: true,
2795
- agentOsId,
2796
- credentialsPath: displayUserPath(CREDENTIALS_FILE),
2797
- tokenPrefix: `${token.slice(0, 12)}\u2026`,
2798
- note: "Scoped runner token saved; callbacks use X-Kynver-Runner-Token."
2799
- },
2800
- null,
2801
- 2
2802
- )
2803
- );
2804
- } catch (err) {
2805
- console.error(err instanceof Error ? err.message : String(err));
2806
- process.exit(1);
3097
+ function installedPackageJsonCandidates(packageName) {
3098
+ const roots = moduleRoots();
3099
+ const seen = /* @__PURE__ */ new Set();
3100
+ const out = [];
3101
+ for (const root of roots) {
3102
+ const candidate = path5.join(root, packageName, "package.json");
3103
+ if (seen.has(candidate)) continue;
3104
+ seen.add(candidate);
3105
+ out.push(candidate);
2807
3106
  }
3107
+ return out;
2808
3108
  }
2809
- function failConfig(message) {
2810
- console.error(message);
2811
- process.exit(1);
2812
- }
2813
- function parseArgs(argv) {
2814
- const args = {};
2815
- for (let i = 0; i < argv.length; i++) {
2816
- const item = argv[i];
2817
- if (!item.startsWith("--")) continue;
2818
- const key = item.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
2819
- const next = argv[i + 1];
2820
- if (!next || next.startsWith("--")) args[key] = true;
2821
- else {
2822
- args[key] = next;
2823
- i++;
3109
+ async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
3110
+ const out = {};
3111
+ for (const packageName of MANAGED_PACKAGES) {
3112
+ let best = null;
3113
+ for (const packageJsonPath of installedPackageJsonCandidates(packageName)) {
3114
+ const version = await readVersion(packageJsonPath);
3115
+ if (!version) continue;
3116
+ if (!best || compareSemver(version, best.version) > 0) {
3117
+ best = { version, path: packageJsonPath };
3118
+ }
3119
+ }
3120
+ if (best) {
3121
+ out[packageName] = { version: best.version, observedAt, path: best.path };
2824
3122
  }
2825
3123
  }
2826
- return args;
3124
+ return out;
2827
3125
  }
2828
- async function runSetup(args) {
2829
- const existing = loadUserConfig();
2830
- const diskGate = observeRunnerDiskGate({
2831
- diskPath: typeof args.diskPath === "string" ? args.diskPath : "/"
2832
- });
2833
- const capRecommendation = recommendSetupWorkerCap({
2834
- totalMemBytes: os3.totalmem(),
2835
- diskPath: diskGate.path,
2836
- diskGateOk: diskGate.ok,
2837
- diskFreeBytes: diskGate.freeBytes,
2838
- config: existing
2839
- });
2840
- const workerConfig = resolveSetupWorkerConfig(existing, args);
2841
- const config = normalizeConfigPaths({
2842
- ...existing,
2843
- ...inferSetupFields(existing, args),
2844
- ...workerConfig,
2845
- workerProvider: typeof args.provider === "string" ? args.provider : existing.workerProvider || "cursor"
2846
- });
2847
- saveUserConfig(config);
2848
- const boxIdentity = resolveBoxIdentity(process.env, config);
2849
- let runnerCredentialNote;
2850
- const apiKey = loadApiKey();
2851
- const agentOsId = config.agentOsId;
2852
- if (apiKey && agentOsId) {
2853
- try {
2854
- const token = await fetchRunnerCredential(agentOsId, {
2855
- baseUrl: typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : config.apiBaseUrl,
2856
- apiKey
2857
- });
2858
- saveRunnerToken(agentOsId, token);
2859
- runnerCredentialNote = "Scoped runner token minted and saved to ~/.kynver/credentials.";
2860
- } catch {
2861
- runnerCredentialNote = "Runner token not minted (server offline or master secret unset). Run `kynver runner credential` after deploy.";
2862
- }
3126
+
3127
+ // src/memory-cost-package-version-guard-enforce.ts
3128
+ function installedVersionMap(observed) {
3129
+ const out = {};
3130
+ for (const [packageName, row] of Object.entries(observed)) {
3131
+ if (!row?.version) continue;
3132
+ out[packageName] = {
3133
+ version: row.version,
3134
+ source: "installed",
3135
+ path: row.path
3136
+ };
2863
3137
  }
2864
- console.log(
2865
- JSON.stringify(
2866
- {
2867
- ok: true,
2868
- configPath: displayUserPath(CONFIG_FILE),
2869
- config: presentUserConfig(config),
2870
- boxKind: config.boxKind,
2871
- boxKindSource: boxIdentity.source,
2872
- workerCapRecommendation: capRecommendation,
2873
- ...boxIdentity.warnings.length ? { boxIdentityWarnings: boxIdentity.warnings } : {},
2874
- note: runnerCredentialNote ?? "boxKind and maxConcurrentWorkers persisted; override with --box-kind and --max-workers. Run `kynver login` + `kynver runner credential` for scoped callbacks."
2875
- },
2876
- null,
2877
- 2
2878
- )
2879
- );
3138
+ return out;
2880
3139
  }
2881
- async function runLogin(args) {
2882
- const apiKey = typeof args.apiKey === "string" ? args.apiKey : process.env.KYNVER_API_KEY;
2883
- if (!apiKey) failConfig("kynver login requires --api-key or KYNVER_API_KEY");
2884
- saveApiKey(apiKey);
2885
- console.log(JSON.stringify({ ok: true, credentialsPath: displayUserPath(CREDENTIALS_FILE) }, null, 2));
3140
+ async function buildMemoryCostPackageGuardInput(input = {}) {
3141
+ const [installed, repo] = await Promise.all([
3142
+ collectInstalledPackageVersions(),
3143
+ Promise.resolve(probeRepoPackageVersions({ cwd: input.cwd, repoRoot: input.repoRoot }))
3144
+ ]);
3145
+ const self = {};
3146
+ const runtimeSelfVersion = input.selfPackageName === "@kynver-app/runtime" && input.selfVersion ? input.selfVersion : PACKAGE_VERSION;
3147
+ self["@kynver-app/runtime"] = { version: runtimeSelfVersion, source: "self" };
3148
+ if (input.selfPackageName && input.selfVersion && input.selfPackageName !== "@kynver-app/runtime") {
3149
+ self[input.selfPackageName] = { version: input.selfVersion, source: "self" };
3150
+ }
3151
+ return {
3152
+ installed: installedVersionMap(installed),
3153
+ repo,
3154
+ self
3155
+ };
3156
+ }
3157
+ async function evaluateMemoryCostPackageGuardAtStartup(input = {}) {
3158
+ const guardInput = await buildMemoryCostPackageGuardInput(input);
3159
+ return evaluateMemoryCostPackageVersionGuard(guardInput);
3160
+ }
3161
+ async function enforceMemoryCostPackageGuardAtStartup(input = {}) {
3162
+ const guardInput = await buildMemoryCostPackageGuardInput(input);
3163
+ return assertMemoryCostPackageVersionGuard(guardInput);
3164
+ }
3165
+ function shouldEnforceMemoryCostPackageGuardCli(scope, action) {
3166
+ if (!scope) return false;
3167
+ if (scope === "daemon") return true;
3168
+ if (scope === "worker") return true;
3169
+ if (scope === "monitor") return true;
3170
+ if (scope === "run" && (action === "dispatch" || action === "sweep" || action === "reconcile" || action === "unblock")) {
3171
+ return true;
3172
+ }
3173
+ if (scope === "cron" && action === "tick") return true;
3174
+ return false;
2886
3175
  }
2887
3176
 
3177
+ // src/dispatch.ts
3178
+ init_config();
3179
+
2888
3180
  // src/callback-headers.ts
2889
3181
  function buildHarnessCallbackHeaders(secret) {
2890
3182
  const trimmed = String(secret).trim();
@@ -2907,6 +3199,7 @@ function buildHarnessCallbackHeaders(secret) {
2907
3199
  }
2908
3200
 
2909
3201
  // src/callbacks.ts
3202
+ init_config();
2910
3203
  function callbackTimeoutMs() {
2911
3204
  const parsed = Number(process.env.KYNVER_CALLBACK_TIMEOUT_MS);
2912
3205
  if (Number.isFinite(parsed) && parsed > 0) return Math.floor(parsed);
@@ -3132,6 +3425,12 @@ function resolveDispatchNextLaneFilter(raw) {
3132
3425
  return normalizeDispatchNextLaneFilter(raw) ?? "any";
3133
3426
  }
3134
3427
 
3428
+ // src/dispatch.ts
3429
+ init_disk_gate();
3430
+ init_resource_gate();
3431
+ init_run_store();
3432
+ init_run_store();
3433
+
3135
3434
  // src/model-routing-task-enrich.ts
3136
3435
  function taskString(task, key) {
3137
3436
  const v = task[key];
@@ -3181,6 +3480,9 @@ function enrichTaskForModelRouting(task) {
3181
3480
  return { ...task, roleLane };
3182
3481
  }
3183
3482
 
3483
+ // src/model-routing.ts
3484
+ init_config();
3485
+
3184
3486
  // src/worker-provider-policy.ts
3185
3487
  var DEFAULT_WORKER_PROVIDER = "cursor";
3186
3488
  var CLAUDE_FAMILY = /* @__PURE__ */ new Set(["claude", "opus", "anthropic"]);
@@ -3864,6 +4166,8 @@ function resolveOrchestrationRouting(input) {
3864
4166
  }
3865
4167
 
3866
4168
  // src/providers/claude.ts
4169
+ init_worker_env();
4170
+ init_util();
3867
4171
  import { closeSync, openSync } from "node:fs";
3868
4172
  import { spawn } from "node:child_process";
3869
4173
 
@@ -4001,13 +4305,17 @@ var claudeProvider = {
4001
4305
  };
4002
4306
 
4003
4307
  // src/providers/codex.ts
4308
+ init_worker_env();
4309
+ init_util();
4004
4310
  import { closeSync as closeSync3, existsSync as existsSync17, openSync as openSync3 } from "node:fs";
4005
4311
  import { spawn as spawn3 } from "node:child_process";
4006
4312
 
4007
4313
  // src/providers/hermes-codex.ts
4314
+ init_worker_env();
4315
+ init_util();
4008
4316
  import { closeSync as closeSync2, openSync as openSync2 } from "node:fs";
4009
4317
  import { spawn as spawn2 } from "node:child_process";
4010
- var HERMES_OPENAI_CODEX_DEFAULT_MODEL = "gpt-5.4";
4318
+ var HERMES_OPENAI_CODEX_DEFAULT_MODEL = process.env.KYNVER_CODEX_DEFAULT_MODEL?.trim() || "gpt-5.4";
4011
4319
  function hermesWorkerEnv() {
4012
4320
  return scrubWorkerEnv({
4013
4321
  ...process.env,
@@ -4075,7 +4383,10 @@ var hermesCodexProvider = {
4075
4383
  };
4076
4384
 
4077
4385
  // src/providers/codex.ts
4078
- var CODEX_DEFAULT_MODEL = "gpt-5.4";
4386
+ function resolveCodexDefaultModel() {
4387
+ return process.env.KYNVER_CODEX_DEFAULT_MODEL?.trim() || "gpt-5.4";
4388
+ }
4389
+ var CODEX_DEFAULT_MODEL = resolveCodexDefaultModel();
4079
4390
  function resolveCodexBin() {
4080
4391
  return process.env.KYNVER_CODEX_BIN?.trim() || process.env.CODEX_BIN?.trim() || "codex";
4081
4392
  }
@@ -4327,7 +4638,11 @@ function readHarnessRetryLimits() {
4327
4638
  }
4328
4639
 
4329
4640
  // src/lease-renewal.ts
4641
+ init_config();
4330
4642
  import path16 from "node:path";
4643
+ init_run_store();
4644
+ init_status();
4645
+ init_util();
4331
4646
 
4332
4647
  // src/harness-lease-owner.ts
4333
4648
  var HARNESS_LEASE_PREFIX = "kynver-harness:";
@@ -4363,15 +4678,17 @@ function resolveHarnessLeaseOwnerForRenewal(input) {
4363
4678
  }
4364
4679
 
4365
4680
  // src/runner-identity.ts
4366
- import os5 from "node:os";
4681
+ import os6 from "node:os";
4367
4682
 
4368
4683
  // src/box-resource-snapshot-shared.ts
4369
- import os4 from "node:os";
4684
+ init_box_identity();
4685
+ init_box_identity();
4686
+ import os5 from "node:os";
4370
4687
  function resolveBoxKindFromEnv(env = process.env) {
4371
4688
  return resolveBoxIdentity(env).boxKind;
4372
4689
  }
4373
4690
  function defaultBoxId(boxKind, hostLabel) {
4374
- const host = (hostLabel ?? os4.hostname()).trim().toLowerCase().replace(/\s+/g, "-") || "unknown-host";
4691
+ const host = (hostLabel ?? os5.hostname()).trim().toLowerCase().replace(/\s+/g, "-") || "unknown-host";
4375
4692
  return `${boxKind}:${host}`;
4376
4693
  }
4377
4694
 
@@ -4382,10 +4699,10 @@ function trimOrNull5(value) {
4382
4699
  }
4383
4700
  function resolveRunnerPresencePayload(input = {}) {
4384
4701
  const env = input.env ?? process.env;
4385
- const runnerId = trimOrNull5(env.KYNVER_RUNTIME_ID) ?? trimOrNull5(env.OPENCLAW_RUNTIME_ID) ?? trimOrNull5(env.HOSTNAME) ?? os5.hostname();
4702
+ const runnerId = trimOrNull5(env.KYNVER_RUNTIME_ID) ?? trimOrNull5(env.OPENCLAW_RUNTIME_ID) ?? trimOrNull5(env.HOSTNAME) ?? os6.hostname();
4386
4703
  return {
4387
4704
  runnerId,
4388
- hostname: trimOrNull5(env.HOSTNAME) ?? os5.hostname(),
4705
+ hostname: trimOrNull5(env.HOSTNAME) ?? os6.hostname(),
4389
4706
  profile: trimOrNull5(env.KYNVER_RUNNER_PROFILE) ?? trimOrNull5(env.OPENCLAW_RUNNER_PROFILE),
4390
4707
  harnessRepo: trimOrNull5(env.KYNVER_HARNESS_REPO) ?? trimOrNull5(env.KYNVER_DEFAULT_REPO),
4391
4708
  runId: input.runId ?? null
@@ -4470,6 +4787,9 @@ function hasLiveWorkerForTask(runId, taskId) {
4470
4787
  }
4471
4788
 
4472
4789
  // src/supervisor.ts
4790
+ init_git();
4791
+ init_run_store();
4792
+ init_run_store();
4473
4793
  import { existsSync as existsSync21, mkdirSync as mkdirSync4 } from "node:fs";
4474
4794
  import path23 from "node:path";
4475
4795
 
@@ -4619,10 +4939,18 @@ function buildPrompt(input) {
4619
4939
  ].join("\n");
4620
4940
  }
4621
4941
 
4942
+ // src/supervisor.ts
4943
+ init_util();
4944
+
4945
+ // src/providers/registry.ts
4946
+ init_config();
4947
+
4622
4948
  // src/providers/cursor.ts
4949
+ init_util();
4950
+ init_worker_env();
4623
4951
  import { closeSync as closeSync4, existsSync as existsSync19, mkdirSync as mkdirSync3, openSync as openSync4, statSync as statSync4, unlinkSync } from "node:fs";
4624
4952
  import { spawn as spawn4 } from "node:child_process";
4625
- import os6 from "node:os";
4953
+ import os7 from "node:os";
4626
4954
  import path18 from "node:path";
4627
4955
 
4628
4956
  // src/providers/cursor-windows.ts
@@ -4733,7 +5061,7 @@ function positiveIntEnv(name, fallback) {
4733
5061
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : fallback;
4734
5062
  }
4735
5063
  function cursorStartLockPath() {
4736
- const root = process.env.KYNVER_CURSOR_START_LOCK_DIR?.trim() || path18.join(os6.homedir(), ".kynver", "locks");
5064
+ const root = process.env.KYNVER_CURSOR_START_LOCK_DIR?.trim() || path18.join(os7.homedir(), ".kynver", "locks");
4737
5065
  mkdirSync3(root, { recursive: true });
4738
5066
  return path18.join(root, "cursor-agent-start.lock");
4739
5067
  }
@@ -4859,12 +5187,14 @@ function resolveWorkerProvider(name) {
4859
5187
  }
4860
5188
 
4861
5189
  // src/auto-complete.ts
5190
+ init_util();
4862
5191
  import { spawn as spawn5 } from "node:child_process";
4863
5192
  import { existsSync as existsSync20, openSync as openSync5, closeSync as closeSync5 } from "node:fs";
4864
5193
  import path22 from "node:path";
4865
5194
  import { fileURLToPath as fileURLToPath3 } from "node:url";
4866
5195
 
4867
5196
  // src/completion-ack.ts
5197
+ init_run_store();
4868
5198
  function hasCompletionAck(worker) {
4869
5199
  return Boolean(worker.completionReportedAt?.trim());
4870
5200
  }
@@ -4892,7 +5222,12 @@ function hasTerminalCompletionAck(worker) {
4892
5222
  return hasCompletionAck(worker) && !shouldReplayHarnessCompletion(worker);
4893
5223
  }
4894
5224
 
5225
+ // src/auto-complete.ts
5226
+ init_run_store();
5227
+ init_status();
5228
+
4895
5229
  // src/worker-ops.ts
5230
+ init_config();
4896
5231
  import path21 from "node:path";
4897
5232
 
4898
5233
  // src/completion-response.ts
@@ -4934,6 +5269,10 @@ function completionPostSucceeded(summary) {
4934
5269
  return summary.taskAdvanced;
4935
5270
  }
4936
5271
 
5272
+ // src/worker-ops.ts
5273
+ init_run_store();
5274
+ init_exited_salvage();
5275
+
4937
5276
  // src/harness-expert-review.ts
4938
5277
  var EXPERT_LANE_REVIEW_REF = "expert-lane-pr-review:";
4939
5278
  var PLAN_REVIEW_EXECUTOR_REF = "plan-review-task";
@@ -5101,6 +5440,7 @@ function normalizeOwnerRepo(value) {
5101
5440
  }
5102
5441
 
5103
5442
  // src/pr-handoff/pr-handoff-gh.ts
5443
+ init_git();
5104
5444
  function capture(bin, cwd, args) {
5105
5445
  try {
5106
5446
  const res = spawnSync3(bin, args, { cwd, encoding: "utf8" });
@@ -5471,6 +5811,10 @@ function ensurePrReadyHandoff(input, exec = defaultPrHandoffExec) {
5471
5811
  };
5472
5812
  }
5473
5813
 
5814
+ // src/worker-ops.ts
5815
+ init_status();
5816
+ init_stream();
5817
+
5474
5818
  // src/material-worktree-changes.ts
5475
5819
  function materialWorktreeChanges(changedFiles) {
5476
5820
  return changedFiles.filter((line) => {
@@ -5513,8 +5857,8 @@ function dirtyPathsCoveredByDisposableRemoval(changedFiles, removed) {
5513
5857
  if (removed.length === 0) return false;
5514
5858
  const removedSet = new Set(removed.map((p) => normalizeRelativePath(p)));
5515
5859
  return material.every((line) => {
5516
- const path73 = normalizeRelativePath(pathFromGitStatusLine(line));
5517
- return removedSet.has(path73);
5860
+ const path75 = normalizeRelativePath(pathFromGitStatusLine(line));
5861
+ return removedSet.has(path75);
5518
5862
  });
5519
5863
  }
5520
5864
 
@@ -5599,6 +5943,9 @@ function assessWorktreeCompletionHandoff(input) {
5599
5943
  }
5600
5944
 
5601
5945
  // src/worker-lifecycle.ts
5946
+ init_run_store();
5947
+ init_status();
5948
+ init_util();
5602
5949
  import path19 from "node:path";
5603
5950
  var TASK_LEFT_RUNNING = /* @__PURE__ */ new Set([
5604
5951
  "awaiting_review",
@@ -5690,7 +6037,11 @@ function syncCompletionAcknowledgedFromOperatorTick(runId, operatorTick) {
5690
6037
  return synced;
5691
6038
  }
5692
6039
 
6040
+ // src/worker-ops.ts
6041
+ init_util();
6042
+
5693
6043
  // src/validate.ts
6044
+ init_util();
5694
6045
  import path20 from "node:path";
5695
6046
  var RUN_ID_RE = /^[a-z0-9][a-z0-9._-]{0,127}$/i;
5696
6047
  var WORKER_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/i;
@@ -6477,6 +6828,7 @@ function stopWorker(args) {
6477
6828
  }
6478
6829
 
6479
6830
  // src/auto-complete.ts
6831
+ init_util();
6480
6832
  var DEFAULT_POLL_MS = 5e3;
6481
6833
  var DEFAULT_MAX_TOTAL_MS = 6 * 60 * 60 * 1e3;
6482
6834
  var DEFAULT_COMPLETE_ATTEMPTS = 3;
@@ -6661,6 +7013,7 @@ function spawnCompletionSidecar(opts) {
6661
7013
  }
6662
7014
 
6663
7015
  // src/repair-target-worktree.ts
7016
+ init_git();
6664
7017
  function addWorktreeForRepairBranch(repo, worktreePath, branch) {
6665
7018
  git(repo, ["fetch", "origin", branch, "--prune"], { allowFailure: true });
6666
7019
  const remoteRef = `origin/${branch}`;
@@ -6674,6 +7027,8 @@ function addWorktreeForRepairBranch(repo, worktreePath, branch) {
6674
7027
  }
6675
7028
 
6676
7029
  // src/supervisor.ts
7030
+ init_box_identity();
7031
+ init_config();
6677
7032
  function spawnWorkerProcess(run, opts) {
6678
7033
  const rawName = typeof opts.name === "string" ? opts.name.trim() : "";
6679
7034
  if (!rawName || rawName === "undefined" || rawName === "null") {
@@ -6767,6 +7122,10 @@ function spawnWorkerProcess(run, opts) {
6767
7122
  else process.env.KYNVER_HARNESS_AGENT_OS_ID = prevHarnessAgentOsId;
6768
7123
  }
6769
7124
  const model = resolveModelFallback(started.model, launchModel, provider.defaultModel);
7125
+ const config = loadUserConfig();
7126
+ const boxIdentity = resolveBoxIdentity(process.env, config);
7127
+ const runtimeId = resolveRunnerPresencePayload().runnerId;
7128
+ const boxId = defaultBoxId(boxIdentity.boxKind);
6770
7129
  const worker = {
6771
7130
  name,
6772
7131
  runId: run.id,
@@ -6802,6 +7161,9 @@ function spawnWorkerProcess(run, opts) {
6802
7161
  ...opts.taskPrUrl ? { taskPrUrl: String(opts.taskPrUrl) } : {},
6803
7162
  ...opts.repairTargetPrUrl ? { repairTargetPrUrl: String(opts.repairTargetPrUrl) } : {},
6804
7163
  ...opts.repairTargetBranch ? { repairTargetBranch: String(opts.repairTargetBranch) } : {},
7164
+ boxKind: boxIdentity.boxKind,
7165
+ boxId,
7166
+ runtimeId,
6805
7167
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
6806
7168
  };
6807
7169
  saveWorker(run.id, worker);
@@ -6900,6 +7262,9 @@ async function startWorker(args) {
6900
7262
  }
6901
7263
 
6902
7264
  // src/active-harness-workers.ts
7265
+ init_run_store();
7266
+ init_harness_worker_active();
7267
+ init_util();
6903
7268
  import path24 from "node:path";
6904
7269
  function workerWriteSetFields(worker) {
6905
7270
  const ownedPaths = Array.isArray(worker.ownedPaths) ? worker.ownedPaths.filter((p) => typeof p === "string") : [];
@@ -6932,6 +7297,9 @@ function collectRunActiveHarnessWorkers(runId) {
6932
7297
  return out;
6933
7298
  }
6934
7299
 
7300
+ // src/dispatch.ts
7301
+ init_util();
7302
+
6935
7303
  // src/plan-persist/body-hash.ts
6936
7304
  import { createHash as createHash2 } from "node:crypto";
6937
7305
  function hashPlanBody(body) {
@@ -6945,6 +7313,9 @@ function hashSummary(summary) {
6945
7313
  return createHash2("sha256").update(trimmed, "utf8").digest("hex");
6946
7314
  }
6947
7315
 
7316
+ // src/plan-persist/agentos-api.ts
7317
+ init_config();
7318
+
6948
7319
  // src/plan-persist/errors.ts
6949
7320
  var PlanPersistError = class extends Error {
6950
7321
  kind;
@@ -7609,11 +7980,11 @@ function classifyChecks(statusCheckRollup) {
7609
7980
  continue;
7610
7981
  }
7611
7982
  if (state && SUCCESSFUL_CHECK_CONCLUSIONS.has(state)) continue;
7612
- if (state && state !== "PENDING") {
7983
+ if (state && state !== "PENDING" && state !== "EXPECTED") {
7613
7984
  failed.push(`${checkName(check3)}=${state}`);
7614
7985
  continue;
7615
7986
  }
7616
- if (state === "PENDING") {
7987
+ if (state === "PENDING" || state === "EXPECTED") {
7617
7988
  pending.push(`${checkName(check3)}=${state}`);
7618
7989
  continue;
7619
7990
  }
@@ -7640,8 +8011,8 @@ var LOCAL_VERIFICATION_RE = /typecheck|npm run (test|build|typecheck)|vitest|tsc
7640
8011
  var DOCS_TITLE_RE = /^docs[(:]/i;
7641
8012
  var DOCS_BODY_RE = /docs[- ]only|documentation only|no[- ]code change|no code changes|low[- ]risk|plan tracker only|markdown only/i;
7642
8013
  function runtimeVerificationEvidenceSufficient(input) {
7643
- const title = typeof input.title === "string" ? input.title : "";
7644
- const body = typeof input.body === "string" ? input.body : "";
8014
+ const title = typeof input.title === "string" ? input.title.trim() : "";
8015
+ const body = typeof input.body === "string" ? input.body.trim() : "";
7645
8016
  const docsLowRisk = DOCS_TITLE_RE.test(title) || DOCS_BODY_RE.test(body);
7646
8017
  const structuredSection = STRUCTURED_SECTION_RE.test(body);
7647
8018
  const localVerification = LOCAL_VERIFICATION_RE.test(body);
@@ -7793,40 +8164,56 @@ async function executeLandPrMerge(input) {
7793
8164
  "--squash"
7794
8165
  ]);
7795
8166
  if (mergeRes.status !== 0) {
8167
+ const raced = viewMergedState(exec, cwd, target, input.repo);
8168
+ if (raced) {
8169
+ return {
8170
+ prUrl: raced.url || before.url || prTarget,
8171
+ outcome: "skipped",
8172
+ mergeCommit: raced.mergeCommit?.oid ?? null,
8173
+ reason: `PR #${before.number} is already merged \u2014 merged by another lane during land_pr (race)`
8174
+ };
8175
+ }
7796
8176
  return {
7797
8177
  prUrl: before.url || prTarget,
7798
8178
  outcome: "blocked",
7799
8179
  reason: mergeRes.stderr || mergeRes.stdout || "gh pr merge failed"
7800
8180
  };
7801
8181
  }
7802
- const after = ghJson(exec, cwd, [
7803
- "pr",
7804
- "view",
7805
- target,
7806
- ...repoArgs(input.repo),
7807
- "--json",
7808
- "number,url,mergedAt,mergeCommit,state"
7809
- ]);
7810
- if (after.state !== "MERGED" && !after.mergedAt) {
7811
- return {
7812
- prUrl: after.url || before.url || prTarget,
7813
- outcome: "blocked",
7814
- reason: `PR #${after.number} did not verify as merged after gh pr merge`
7815
- };
8182
+ let after = viewMergedState(exec, cwd, target, input.repo);
8183
+ if (!after) {
8184
+ after = viewMergedState(exec, cwd, target, input.repo);
8185
+ }
8186
+ try {
8187
+ const repo = resolveRepo(exec, cwd, input.repo);
8188
+ deleteRemoteBranch(exec, cwd, repo, before.headRefName);
8189
+ removeBranchWorktrees(cwd, before.headRefName);
8190
+ } catch {
7816
8191
  }
7817
- const repo = resolveRepo(exec, cwd, input.repo);
7818
- deleteRemoteBranch(exec, cwd, repo, before.headRefName);
7819
- removeBranchWorktrees(cwd, before.headRefName);
7820
- const mergeCommit = after.mergeCommit?.oid ?? null;
7821
8192
  return {
7822
- prUrl: after.url || before.url || prTarget,
8193
+ prUrl: after?.url || before.url || prTarget,
7823
8194
  outcome: "merged",
7824
- mergeCommit,
7825
- reason: `Daemon land_pr merged PR #${after.number}`
8195
+ mergeCommit: after?.mergeCommit?.oid ?? null,
8196
+ reason: `Daemon land_pr merged PR #${before.number}${after ? "" : " (post-merge view unavailable \u2014 merge verified by gh exit 0)"}`
7826
8197
  };
7827
8198
  }
8199
+ function viewMergedState(exec, cwd, target, repo) {
8200
+ try {
8201
+ const view = ghJson(exec, cwd, [
8202
+ "pr",
8203
+ "view",
8204
+ target,
8205
+ ...repoArgs(repo),
8206
+ "--json",
8207
+ "number,url,mergedAt,mergeCommit,state"
8208
+ ]);
8209
+ return view.state === "MERGED" || view.mergedAt ? view : null;
8210
+ } catch {
8211
+ return null;
8212
+ }
8213
+ }
7828
8214
 
7829
8215
  // src/landing/land-pr-completion-post.ts
8216
+ init_config();
7830
8217
  async function postLandPrHarnessCompletion(input) {
7831
8218
  const secret = await resolveCallbackSecretWithMint(input.secret, input.agentOsId, {
7832
8219
  baseUrl: input.baseUrl
@@ -8111,6 +8498,15 @@ async function dispatchRun(args) {
8111
8498
  async function runLandPrClaimed(decision) {
8112
8499
  const task = decision.task;
8113
8500
  const taskId = String(task.id);
8501
+ if (exactTargetMode && !exactTargetIds.has(taskId)) {
8502
+ return abortClaimedSpawn(
8503
+ task,
8504
+ "exact_target_mismatch: dispatch-next returned a different task than requested",
8505
+ {
8506
+ requestedTargetTaskIds: [...exactTargetIds]
8507
+ }
8508
+ );
8509
+ }
8114
8510
  const prUrl = task.prUrl ? String(task.prUrl) : "";
8115
8511
  if (!prUrl) {
8116
8512
  return abortClaimedSpawn(task, "land_pr task missing prUrl");
@@ -8372,11 +8768,21 @@ async function dispatchRun(args) {
8372
8768
  }
8373
8769
  }
8374
8770
 
8771
+ // src/index.ts
8772
+ init_disk_gate();
8773
+ init_wsl_host();
8774
+ init_stream();
8775
+ init_shell_command_outcome();
8776
+ init_repo_search();
8777
+ init_heartbeat();
8778
+
8375
8779
  // src/box-resource-snapshot.ts
8376
- import os7 from "node:os";
8780
+ init_config();
8781
+ init_box_identity();
8782
+ import os8 from "node:os";
8377
8783
  function buildBoxResourceSnapshotFromGate(gate, input = {}) {
8378
8784
  const boxKind = (input.boxKind ?? resolveBoxKindFromConfig(loadUserConfig())).trim().toLowerCase() || "forge";
8379
- const hostLabel = input.hostLabel ?? os7.hostname();
8785
+ const hostLabel = input.hostLabel ?? os8.hostname();
8380
8786
  const boxId = input.boxId ?? defaultBoxId(boxKind, hostLabel);
8381
8787
  return {
8382
8788
  boxId,
@@ -8410,6 +8816,10 @@ function formatHeartbeatLine(input) {
8410
8816
  `;
8411
8817
  }
8412
8818
 
8819
+ // src/index.ts
8820
+ init_status();
8821
+ init_landing_gate();
8822
+
8413
8823
  // src/fortress-engagement-gate.ts
8414
8824
  function isEngagementRequiredSkip(skip2) {
8415
8825
  if (skip2.skipReason === "engagement_required") return true;
@@ -8417,6 +8827,10 @@ function isEngagementRequiredSkip(skip2) {
8417
8827
  return reason.includes("engagement_required") || reason.includes("engagement_not_found") || reason.includes("engagement_expired") || reason.includes("engagement_revoked");
8418
8828
  }
8419
8829
 
8830
+ // src/index.ts
8831
+ init_landing_contract_gate();
8832
+ init_exited_salvage();
8833
+
8420
8834
  // src/providers/openai-codex-resilience.ts
8421
8835
  var OPENAI_CODEX_PROVIDER = "openai-codex";
8422
8836
  var TRANSIENT_OPENAI_CODEX_ERROR_CLASSES = /* @__PURE__ */ new Set([
@@ -8706,6 +9120,9 @@ function redactHarness(text, secret) {
8706
9120
  return out;
8707
9121
  }
8708
9122
 
9123
+ // src/index.ts
9124
+ init_worker_env();
9125
+
8709
9126
  // src/db-credential-env-paths.ts
8710
9127
  import * as fs from "node:fs";
8711
9128
  import { homedir as homedir12 } from "node:os";
@@ -8923,10 +9340,14 @@ function applyProductionDatabaseToProcess(options = {}) {
8923
9340
  }
8924
9341
 
8925
9342
  // src/worktree.ts
9343
+ init_git();
9344
+ init_run_store();
8926
9345
  import { existsSync as existsSync29, mkdirSync as mkdirSync6 } from "node:fs";
8927
9346
  import path38 from "node:path";
8928
9347
 
8929
9348
  // src/run-list.ts
9349
+ init_run_store();
9350
+ init_run_worker_index();
8930
9351
  import { existsSync as existsSync28, readFileSync as readFileSync15 } from "node:fs";
8931
9352
  import path37 from "node:path";
8932
9353
 
@@ -8934,6 +9355,10 @@ import path37 from "node:path";
8934
9355
  import path36 from "node:path";
8935
9356
 
8936
9357
  // src/finalize.ts
9358
+ init_run_store();
9359
+ init_run_worker_index();
9360
+ init_status();
9361
+ init_util();
8937
9362
  import path30 from "node:path";
8938
9363
  var ACTIVE_RUN_STATUSES = /* @__PURE__ */ new Set([
8939
9364
  "running",
@@ -8991,11 +9416,21 @@ function finalizeStaleRuns() {
8991
9416
  return finalized;
8992
9417
  }
8993
9418
 
9419
+ // src/stale-reconcile.ts
9420
+ init_run_store();
9421
+ init_run_worker_index();
9422
+ init_status();
9423
+ init_util();
9424
+
8994
9425
  // src/worker-metadata-reconcile.ts
9426
+ init_heartbeat();
9427
+ init_stream();
8995
9428
  import { existsSync as existsSync27, lstatSync, readdirSync as readdirSync7, readlinkSync, renameSync as renameSync2, rmSync } from "node:fs";
8996
9429
  import path34 from "node:path";
8997
9430
 
8998
9431
  // src/worker-metadata-paths.ts
9432
+ init_paths();
9433
+ init_util();
8999
9434
  import path31 from "node:path";
9000
9435
  var NESTED_RUNS = `${path31.sep}runs${path31.sep}runs${path31.sep}`;
9001
9436
  function hasNestedRunsSegment(filePath) {
@@ -9053,6 +9488,9 @@ import { existsSync as existsSync26, readdirSync as readdirSync6, statSync as st
9053
9488
  import path33 from "node:path";
9054
9489
 
9055
9490
  // src/default-repo.ts
9491
+ init_config();
9492
+ init_default_repo_discovery();
9493
+ init_path_values();
9056
9494
  import path32 from "node:path";
9057
9495
  function expandConfiguredRepo(value) {
9058
9496
  return path32.resolve(resolveUserPath(value.trim()));
@@ -9122,6 +9560,10 @@ function formatResolvedDefaultRepo(resolved) {
9122
9560
  }
9123
9561
 
9124
9562
  // src/run-metadata-retention.ts
9563
+ init_heartbeat();
9564
+ init_paths();
9565
+ init_run_store();
9566
+ init_util();
9125
9567
  var RUN_METADATA_ACTIVE_SIGNAL_MS = 15 * 60 * 1e3;
9126
9568
  function isHarnessRunMetadataPath(targetPath, harnessRoot) {
9127
9569
  const resolved = path33.resolve(targetPath);
@@ -9262,6 +9704,8 @@ function collectFilesystemLiveRunKeys(harnessRoot, now = Date.now()) {
9262
9704
  }
9263
9705
 
9264
9706
  // src/worker-metadata-reconcile.ts
9707
+ init_run_store();
9708
+ init_util();
9265
9709
  function materializeSymlinkedRunDir(harnessRoot, runId) {
9266
9710
  const canonical = canonicalRunDir(harnessRoot, runId);
9267
9711
  let stat;
@@ -9567,6 +10011,12 @@ function reconcileWorkerMetadataCli() {
9567
10011
  }
9568
10012
 
9569
10013
  // src/local-pr-attention-reconcile.ts
10014
+ init_heartbeat();
10015
+ init_worker_final_result_embed();
10016
+ init_status();
10017
+ init_run_store();
10018
+ init_run_worker_index();
10019
+ init_util();
9570
10020
  import { execFileSync as execFileSync2 } from "node:child_process";
9571
10021
  import path35 from "node:path";
9572
10022
  function normalizePrUrl3(url) {
@@ -9893,6 +10343,8 @@ function reconcileRunsCli() {
9893
10343
  }
9894
10344
 
9895
10345
  // src/run-list.ts
10346
+ init_status();
10347
+ init_util();
9896
10348
  function heartbeatByteLength(heartbeatPath) {
9897
10349
  if (!heartbeatPath || !existsSync28(heartbeatPath)) return 0;
9898
10350
  try {
@@ -10008,6 +10460,7 @@ function listRunsCli() {
10008
10460
  }
10009
10461
 
10010
10462
  // src/worktree.ts
10463
+ init_util();
10011
10464
  function resolveCreateRunRepo(args) {
10012
10465
  const explicit = typeof args.repo === "string" ? args.repo.trim() : "";
10013
10466
  if (explicit) return explicit;
@@ -10047,6 +10500,7 @@ function failExists(message) {
10047
10500
  }
10048
10501
 
10049
10502
  // src/run-resolve.ts
10503
+ init_util();
10050
10504
  function resolveHarnessRunByName(runName) {
10051
10505
  const name = runName.trim();
10052
10506
  if (!name) return null;
@@ -10070,8 +10524,15 @@ function resolveHarnessRunCli(args) {
10070
10524
  );
10071
10525
  }
10072
10526
 
10527
+ // src/index.ts
10528
+ init_harness_worker_active();
10529
+
10073
10530
  // src/sweep.ts
10531
+ init_config();
10074
10532
  import path39 from "node:path";
10533
+ init_run_store();
10534
+ init_status();
10535
+ init_util();
10075
10536
  async function sweepRun(args) {
10076
10537
  const pipeline = args.pipeline === true || args.pipeline === "true";
10077
10538
  try {
@@ -10131,7 +10592,13 @@ async function sweepRun(args) {
10131
10592
  }
10132
10593
  }
10133
10594
 
10595
+ // src/index.ts
10596
+ init_config();
10597
+ init_default_repo_discovery();
10598
+ init_paths();
10599
+
10134
10600
  // src/harness-storage-snapshot.ts
10601
+ init_paths();
10135
10602
  import { existsSync as existsSync31, readdirSync as readdirSync9, statSync as statSync7 } from "node:fs";
10136
10603
  import path41 from "node:path";
10137
10604
 
@@ -10259,11 +10726,17 @@ function harnessStorageSnapshot(opts = {}) {
10259
10726
  }
10260
10727
 
10261
10728
  // src/cleanup.ts
10729
+ init_paths();
10262
10730
  import path53 from "node:path";
10263
10731
 
10264
10732
  // src/cleanup-guards.ts
10733
+ init_landing_gate();
10265
10734
  import path42 from "node:path";
10266
10735
 
10736
+ // src/cleanup-index-status.ts
10737
+ init_git();
10738
+ init_status();
10739
+
10267
10740
  // src/cleanup-build-cache-paths.ts
10268
10741
  var HARNESS_BUILD_CACHE_RELATIVE_PATHS = [
10269
10742
  ".next",
@@ -10318,6 +10791,7 @@ function isPrOrUnmergedWork(status) {
10318
10791
  }
10319
10792
 
10320
10793
  // src/cleanup-index-status.ts
10794
+ init_util();
10321
10795
  function indexedWorktreeStatus(entry) {
10322
10796
  if (!entry.status) {
10323
10797
  entry.status = computeWorkerStatus(entry.worker, {
@@ -10394,7 +10868,15 @@ function resolveWorktreeGuardStatus(entry, ctx) {
10394
10868
  return indexedWorktreeStatus(entry);
10395
10869
  }
10396
10870
 
10871
+ // src/cleanup-guards.ts
10872
+ init_status();
10873
+
10874
+ // src/cleanup-run-liveness.ts
10875
+ init_status();
10876
+
10397
10877
  // src/cleanup-completion-blocker.ts
10878
+ init_landing_gate();
10879
+ init_status();
10398
10880
  function completionBlockerBlocksWorktreeRemoval(indexed, status) {
10399
10881
  const blocker = typeof indexed.worker.completionBlocker === "string" ? indexed.worker.completionBlocker.trim() : "";
10400
10882
  if (!blocker) return false;
@@ -10414,6 +10896,7 @@ function completionBlockerBlocksWorktreeRemoval(indexed, status) {
10414
10896
  }
10415
10897
 
10416
10898
  // src/cleanup-run-liveness.ts
10899
+ init_util();
10417
10900
  var TERMINAL_WORKER_JSON_STATUSES = /* @__PURE__ */ new Set([
10418
10901
  "done",
10419
10902
  "exited",
@@ -10544,11 +11027,11 @@ var LIVE_SKIP_REASONS = /* @__PURE__ */ new Set([
10544
11027
  function collectPreservedLivePaths(actions, skips) {
10545
11028
  const out = [];
10546
11029
  const seen = /* @__PURE__ */ new Set();
10547
- const push = (path73, reason, detail) => {
10548
- const key = `${path73}\0${reason}`;
11030
+ const push = (path75, reason, detail) => {
11031
+ const key = `${path75}\0${reason}`;
10549
11032
  if (seen.has(key) || out.length >= MAX_PRESERVED_LIVE_PATH_SAMPLES) return;
10550
11033
  seen.add(key);
10551
- out.push({ path: path73, reason, ...detail ? { detail } : {} });
11034
+ out.push({ path: path75, reason, ...detail ? { detail } : {} });
10552
11035
  };
10553
11036
  for (const skip2 of skips) {
10554
11037
  if (!LIVE_SKIP_REASONS.has(skip2.reason)) continue;
@@ -10567,8 +11050,11 @@ import { existsSync as existsSync33, readdirSync as readdirSync11, statSync as s
10567
11050
  import path44 from "node:path";
10568
11051
 
10569
11052
  // src/cleanup-active-worktrees.ts
11053
+ init_run_store();
11054
+ init_paths();
10570
11055
  import { existsSync as existsSync32, readdirSync as readdirSync10, statSync as statSync8 } from "node:fs";
10571
11056
  import path43 from "node:path";
11057
+ init_util();
10572
11058
  function workerHasRecentHarnessActivity(worker, now) {
10573
11059
  const paths = [worker.heartbeatPath, worker.stdoutPath, worker.stderrPath];
10574
11060
  for (const target of paths) {
@@ -10617,6 +11103,7 @@ function isWorktreeOnLiveRun(worktreePath, harnessRoot, runId, liveRunKeys) {
10617
11103
  }
10618
11104
 
10619
11105
  // src/cleanup-run-directory.ts
11106
+ init_util();
10620
11107
  function pathAgeMs(target, now) {
10621
11108
  try {
10622
11109
  const mtime = statSync9(target).mtimeMs;
@@ -10679,10 +11166,12 @@ function scanStaleRunDirectoryCandidates(opts) {
10679
11166
  }
10680
11167
 
10681
11168
  // src/cleanup-execute.ts
11169
+ init_git();
10682
11170
  import { existsSync as existsSync35, rmSync as rmSync3 } from "node:fs";
10683
11171
 
10684
11172
  // src/cleanup-remove-path.ts
10685
11173
  import { existsSync as existsSync34, rmSync as rmSync2 } from "node:fs";
11174
+ init_paths();
10686
11175
 
10687
11176
  // src/cleanup-path-ownership.ts
10688
11177
  import { lstatSync as lstatSync2, readdirSync as readdirSync12 } from "node:fs";
@@ -11191,6 +11680,7 @@ function scanDependencyCacheCandidates(opts) {
11191
11680
  }
11192
11681
 
11193
11682
  // src/cleanup-duplicate-worktrees.ts
11683
+ init_git();
11194
11684
  import { existsSync as existsSync38, statSync as statSync12 } from "node:fs";
11195
11685
  import path49 from "node:path";
11196
11686
  function pathAgeMs4(target, now) {
@@ -11283,6 +11773,8 @@ function scanDuplicateWorktreeCandidates(opts) {
11283
11773
  }
11284
11774
 
11285
11775
  // src/cleanup-worktree-index.ts
11776
+ init_run_store();
11777
+ init_util();
11286
11778
  import path50 from "node:path";
11287
11779
  function buildWorktreeIndexAt(harnessRoot) {
11288
11780
  const index = /* @__PURE__ */ new Map();
@@ -11367,6 +11859,7 @@ function resolvePipelineHarnessRetention(runId) {
11367
11859
  }
11368
11860
 
11369
11861
  // src/cleanup-orphan-safety.ts
11862
+ init_git();
11370
11863
  import { existsSync as existsSync39, statSync as statSync13 } from "node:fs";
11371
11864
  import path51 from "node:path";
11372
11865
  var DEFAULT_HEARTBEAT_FRESH_MS = 30 * 60 * 1e3;
@@ -11419,6 +11912,7 @@ function assessOrphanWorktreeSafety(input) {
11419
11912
  }
11420
11913
 
11421
11914
  // src/cleanup-harness-roots.ts
11915
+ init_paths();
11422
11916
  import { existsSync as existsSync40 } from "node:fs";
11423
11917
  import { homedir as homedir13 } from "node:os";
11424
11918
  import path52 from "node:path";
@@ -11454,6 +11948,7 @@ function resolveHarnessScanRoots(options = {}) {
11454
11948
  }
11455
11949
 
11456
11950
  // src/cleanup-disk-pressure.ts
11951
+ init_disk_gate();
11457
11952
  function envFlag2(name) {
11458
11953
  const v = process.env[name];
11459
11954
  return v === "1" || v === "true" || v === "yes";
@@ -11503,6 +11998,7 @@ function emitCleanupProgress(phase, detail) {
11503
11998
  }
11504
11999
 
11505
12000
  // src/cleanup-git-rev-cache.ts
12001
+ init_git();
11506
12002
  var CleanupGitRevCache = class {
11507
12003
  aheadOfMain = /* @__PURE__ */ new Map();
11508
12004
  countAheadOfMain(worktreePath, base = "origin/main") {
@@ -11521,6 +12017,7 @@ var CleanupGitRevCache = class {
11521
12017
  };
11522
12018
 
11523
12019
  // src/cleanup-git-status-cache.ts
12020
+ init_git();
11524
12021
  var CleanupGitStatusCache = class {
11525
12022
  cache = /* @__PURE__ */ new Map();
11526
12023
  porcelain(worktreePath) {
@@ -11950,10 +12447,79 @@ function isPipelineCleanupEnabled() {
11950
12447
  }
11951
12448
 
11952
12449
  // src/cli.ts
11953
- import { mkdirSync as mkdirSync10, realpathSync } from "node:fs";
12450
+ init_config();
12451
+ import { mkdirSync as mkdirSync11, realpathSync } from "node:fs";
11954
12452
  import { fileURLToPath as fileURLToPath5 } from "node:url";
11955
12453
 
12454
+ // src/bootstrap.ts
12455
+ init_config();
12456
+ init_util();
12457
+ init_device_login();
12458
+ import os9 from "node:os";
12459
+ function resolveBootstrapBaseUrl(args) {
12460
+ const raw = (typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : void 0) || (typeof args.baseUrl === "string" ? args.baseUrl : void 0) || process.env.KYNVER_API_URL || loadUserConfig().apiBaseUrl;
12461
+ return raw ? trimTrailingSlash(String(raw)) : void 0;
12462
+ }
12463
+ async function fetchPrimaryAgentOs(base, apiKey) {
12464
+ const res = await fetch(`${base}/api/agent-os`, {
12465
+ headers: { Authorization: `Bearer ${apiKey}` }
12466
+ });
12467
+ if (!res.ok) return null;
12468
+ const body = await res.json().catch(() => null);
12469
+ if (!body?.primarySlug) return null;
12470
+ const match = body.items?.find((it) => it.slug === body.primarySlug);
12471
+ if (match?.id && match.slug) return { id: match.id, slug: match.slug };
12472
+ return { id: "", slug: body.primarySlug };
12473
+ }
12474
+ async function runBootstrap(args) {
12475
+ const base = resolveBootstrapBaseUrl(args);
12476
+ if (!base) {
12477
+ console.error(
12478
+ "kynver bootstrap requires a Kynver URL \u2014 pass --api-base-url https://your-kynver-site or set KYNVER_API_URL."
12479
+ );
12480
+ process.exit(1);
12481
+ }
12482
+ if (!loadApiKey()) {
12483
+ if (typeof args.apiKey === "string") {
12484
+ saveApiKey(args.apiKey);
12485
+ } else {
12486
+ const login = await runDeviceLogin({ ...args, apiBaseUrl: base });
12487
+ if (!login.ok) process.exit(1);
12488
+ }
12489
+ }
12490
+ const apiKey = loadApiKey();
12491
+ if (!apiKey) {
12492
+ console.error("No API key after login \u2014 aborting.");
12493
+ process.exit(1);
12494
+ }
12495
+ const primary = await fetchPrimaryAgentOs(base, apiKey);
12496
+ if (!primary) {
12497
+ console.error(
12498
+ "Could not resolve your AgentOS workspace from the account. Confirm this account has AgentOS access, then retry."
12499
+ );
12500
+ process.exit(1);
12501
+ }
12502
+ const setupArgs = {
12503
+ ...args,
12504
+ apiBaseUrl: base,
12505
+ agentOsSlug: primary.slug,
12506
+ ...primary.id ? { agentOsId: primary.id } : {},
12507
+ // Best-effort repo discovery unless the caller pinned one.
12508
+ ...typeof args.repo === "string" ? {} : { discoverRepo: true }
12509
+ };
12510
+ await runSetup(setupArgs);
12511
+ console.log("");
12512
+ console.log(` Bootstrap complete \u2014 ${os9.hostname()} is linked to workspace "${primary.slug}".`);
12513
+ console.log(" Next: run autonomous work with `kynver daemon --run <RUN_ID> --agent-os-id <AOS_ID> --execute`");
12514
+ console.log(" (create a run first with `kynver run create --repo /path/to/repo`).");
12515
+ }
12516
+
12517
+ // src/cli.ts
12518
+ init_run_store();
12519
+
11956
12520
  // src/discard-disposable.ts
12521
+ init_run_store();
12522
+ init_status();
11957
12523
  import { existsSync as existsSync41, rmSync as rmSync4 } from "node:fs";
11958
12524
  import path54 from "node:path";
11959
12525
  function normalizeRelativePath2(value) {
@@ -12007,8 +12573,14 @@ function discardDisposableCli(args) {
12007
12573
  if (!result.ok) process.exit(1);
12008
12574
  }
12009
12575
 
12576
+ // src/daemon.ts
12577
+ init_config();
12578
+
12010
12579
  // src/daemon-box-identity.ts
12011
- import os8 from "node:os";
12580
+ init_config();
12581
+ init_box_identity();
12582
+ init_worker_cap_source();
12583
+ import os10 from "node:os";
12012
12584
  function emitDaemonIdentityMessage(level, message) {
12013
12585
  console.error(JSON.stringify({ event: "daemon_identity", level, message }));
12014
12586
  }
@@ -12016,7 +12588,7 @@ function validateDaemonInstallIdentity(config = loadUserConfig(), env = process.
12016
12588
  const box = resolveBoxIdentity(env, config);
12017
12589
  const cap = resolveWorkerCap({
12018
12590
  config,
12019
- totalMemBytes: os8.totalmem(),
12591
+ totalMemBytes: os10.totalmem(),
12020
12592
  env
12021
12593
  });
12022
12594
  const warnings = [...box.warnings];
@@ -12046,6 +12618,47 @@ function validateDaemonInstallIdentity(config = loadUserConfig(), env = process.
12046
12618
  };
12047
12619
  }
12048
12620
 
12621
+ // src/daemon-heartbeat.ts
12622
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync16, renameSync as renameSync3, writeFileSync as writeFileSync4 } from "node:fs";
12623
+ import { homedir as homedir14 } from "node:os";
12624
+ import path55 from "node:path";
12625
+ function daemonHeartbeatPath(agentOsId) {
12626
+ const safe = agentOsId.replace(/[^A-Za-z0-9_-]/g, "_");
12627
+ return path55.join(homedir14(), ".kynver", `daemon-heartbeat-${safe}.json`);
12628
+ }
12629
+ function writeDaemonHeartbeat(input) {
12630
+ try {
12631
+ const file = daemonHeartbeatPath(input.agentOsId);
12632
+ mkdirSync7(path55.dirname(file), { recursive: true });
12633
+ const beat = {
12634
+ observedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
12635
+ pid: process.pid,
12636
+ runId: input.runId,
12637
+ agentOsId: input.agentOsId
12638
+ };
12639
+ const tmp = `${file}.tmp-${process.pid}`;
12640
+ writeFileSync4(tmp, JSON.stringify(beat), "utf8");
12641
+ renameSync3(tmp, file);
12642
+ } catch {
12643
+ }
12644
+ }
12645
+ function readDaemonHeartbeat(agentOsId) {
12646
+ try {
12647
+ const raw = readFileSync16(daemonHeartbeatPath(agentOsId), "utf8");
12648
+ const parsed = JSON.parse(raw);
12649
+ if (typeof parsed?.observedAt !== "string") return null;
12650
+ return parsed;
12651
+ } catch {
12652
+ return null;
12653
+ }
12654
+ }
12655
+ function isDaemonHeartbeatStale(beat, stallMs, nowMs = Date.now()) {
12656
+ if (!beat) return false;
12657
+ const observed = Date.parse(beat.observedAt);
12658
+ if (Number.isNaN(observed)) return true;
12659
+ return nowMs - observed > stallMs;
12660
+ }
12661
+
12049
12662
  // src/daemon-platform-guard.ts
12050
12663
  function envFlag3(name) {
12051
12664
  const raw = process.env[name]?.trim().toLowerCase();
@@ -12065,9 +12678,10 @@ function assertNativeDaemonAllowed() {
12065
12678
  }
12066
12679
 
12067
12680
  // src/cron/cron-env.ts
12681
+ init_config();
12068
12682
  import { existsSync as existsSync42 } from "node:fs";
12069
- import { homedir as homedir14 } from "node:os";
12070
- import path55 from "node:path";
12683
+ import { homedir as homedir15 } from "node:os";
12684
+ import path56 from "node:path";
12071
12685
  function envFlag4(name, defaultValue) {
12072
12686
  const raw = process.env[name]?.trim().toLowerCase();
12073
12687
  if (!raw) return defaultValue;
@@ -12083,7 +12697,7 @@ function envInt(name, fallback, min = 1) {
12083
12697
  function defaultKynverCronStorePath() {
12084
12698
  const explicit = process.env.KYNVER_CRON_STORE_PATH?.trim() || process.env.OPENCLAW_CRON_STORE_PATH?.trim();
12085
12699
  if (explicit) return explicit;
12086
- return path55.join(homedir14(), ".kynver", "agent-os-cron.json");
12700
+ return path56.join(homedir15(), ".kynver", "agent-os-cron.json");
12087
12701
  }
12088
12702
  function defaultKynverCronStatePath(storePath = defaultKynverCronStorePath()) {
12089
12703
  const explicit = process.env.KYNVER_CRON_TICK_STATE_PATH?.trim();
@@ -12156,12 +12770,13 @@ async function fireKynverCronJob(input) {
12156
12770
  }
12157
12771
 
12158
12772
  // src/cron/cron-lock.ts
12159
- import { closeSync as closeSync6, existsSync as existsSync43, openSync as openSync6, readFileSync as readFileSync16, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
12773
+ init_util();
12774
+ import { closeSync as closeSync6, existsSync as existsSync43, openSync as openSync6, readFileSync as readFileSync17, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
12160
12775
  var STALE_LOCK_MS = 10 * 6e4;
12161
12776
  function readLockInfo(lockPath) {
12162
12777
  if (!existsSync43(lockPath)) return null;
12163
12778
  try {
12164
- const parsed = JSON.parse(readFileSync16(lockPath, "utf8"));
12779
+ const parsed = JSON.parse(readFileSync17(lockPath, "utf8"));
12165
12780
  if (typeof parsed.pid === "number" && typeof parsed.at === "string") return parsed;
12166
12781
  } catch {
12167
12782
  return null;
@@ -12192,7 +12807,7 @@ function tryAcquireCronTickLock(lockPath) {
12192
12807
  }
12193
12808
  try {
12194
12809
  const fd = openSync6(lockPath, "wx");
12195
- writeFileSync4(
12810
+ writeFileSync5(
12196
12811
  fd,
12197
12812
  JSON.stringify({ pid: process.pid, at: (/* @__PURE__ */ new Date()).toISOString() }),
12198
12813
  "utf8"
@@ -12325,7 +12940,7 @@ async function loadCronJobs(storePath = defaultKynverCronStorePath()) {
12325
12940
  // src/cron/cron-tick-state.ts
12326
12941
  import { randomBytes } from "node:crypto";
12327
12942
  import { promises as fs4 } from "node:fs";
12328
- import path56 from "node:path";
12943
+ import path57 from "node:path";
12329
12944
  var EMPTY = { version: 1, jobs: {} };
12330
12945
  async function readFileIfExists2(filePath) {
12331
12946
  try {
@@ -12352,7 +12967,7 @@ async function loadCronTickState(statePath) {
12352
12967
  return parseCronTickState(raw);
12353
12968
  }
12354
12969
  async function writeStateAtomic(statePath, state) {
12355
- await fs4.mkdir(path56.dirname(statePath), { recursive: true });
12970
+ await fs4.mkdir(path57.dirname(statePath), { recursive: true });
12356
12971
  const suffix = randomBytes(6).toString("hex");
12357
12972
  const tmp = `${statePath}.tmp-${process.pid}-${Date.now()}-${suffix}`;
12358
12973
  await fs4.writeFile(tmp, `${JSON.stringify(state, null, 2)}
@@ -12528,8 +13143,12 @@ async function runKynverCronTick(opts = {}) {
12528
13143
  }
12529
13144
  }
12530
13145
 
13146
+ // src/daemon.ts
13147
+ init_util();
13148
+
12531
13149
  // src/pipeline-tick.ts
12532
- import path58 from "node:path";
13150
+ import path60 from "node:path";
13151
+ init_config();
12533
13152
 
12534
13153
  // src/pipeline-dispatch.ts
12535
13154
  var RESERVED_REVIEW_STARTS = 1;
@@ -12659,10 +13278,21 @@ function resolvePipelineMaxStarts(resourceGate, operatorTick) {
12659
13278
  };
12660
13279
  }
12661
13280
 
13281
+ // src/pipeline-tick.ts
13282
+ init_resource_gate();
13283
+ init_run_store();
13284
+ init_exited_salvage();
13285
+ init_status();
13286
+ init_util();
13287
+
12662
13288
  // src/plan-progress-daemon-sync.ts
12663
- import path57 from "node:path";
13289
+ init_status();
13290
+ init_run_store();
13291
+ init_util();
13292
+ import path58 from "node:path";
12664
13293
 
12665
13294
  // src/plan-progress-sync.ts
13295
+ init_config();
12666
13296
  async function syncPlanProgress(args) {
12667
13297
  const base = resolveBaseUrl(args.baseUrl);
12668
13298
  const secret = await resolveCallbackSecretWithMint(args.secret, args.agentOsId, { baseUrl: base });
@@ -12684,7 +13314,7 @@ async function syncActiveWorkerPlanProgress(runId, args) {
12684
13314
  const outcomes = [];
12685
13315
  for (const name of Object.keys(run.workers || {})) {
12686
13316
  const worker = readJson(
12687
- path57.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
13317
+ path58.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
12688
13318
  void 0
12689
13319
  );
12690
13320
  if (!worker?.dispatched || !worker.taskId) continue;
@@ -12712,6 +13342,8 @@ async function syncActiveWorkerPlanProgress(runId, args) {
12712
13342
  }
12713
13343
 
12714
13344
  // src/workspace-runtime-config.ts
13345
+ init_config();
13346
+ init_box_identity();
12715
13347
  function shouldApplyWorkspaceRuntimePreferences(env = process.env) {
12716
13348
  const config = loadUserConfig();
12717
13349
  return resolveBoxKindFromConfig(config, env) !== "forge";
@@ -12740,13 +13372,359 @@ async function fetchWorkspaceRuntimePreferences(agentOsId, args) {
12740
13372
  }
12741
13373
  }
12742
13374
 
13375
+ // src/pipeline-tick.ts
13376
+ init_config();
13377
+ init_box_identity();
13378
+
13379
+ // src/provider-evidence/exec.ts
13380
+ import { spawnSync as spawnSync8 } from "node:child_process";
13381
+ var DEFAULT_CLI_TIMEOUT_MS = 1e4;
13382
+ var MAX_CLI_BUFFER_BYTES = 4 * 1024 * 1024;
13383
+ var defaultCliRunner = (cmd, args, opts) => {
13384
+ try {
13385
+ const result = spawnSync8(cmd, args, {
13386
+ encoding: "utf8",
13387
+ stdio: ["ignore", "pipe", "pipe"],
13388
+ timeout: opts?.timeoutMs ?? DEFAULT_CLI_TIMEOUT_MS,
13389
+ maxBuffer: MAX_CLI_BUFFER_BYTES
13390
+ });
13391
+ return {
13392
+ ok: result.status === 0,
13393
+ stdout: typeof result.stdout === "string" ? result.stdout : "",
13394
+ stderr: typeof result.stderr === "string" ? result.stderr : ""
13395
+ };
13396
+ } catch (err) {
13397
+ return { ok: false, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
13398
+ }
13399
+ };
13400
+ function runCliJson(run, cmd, args) {
13401
+ const result = run(cmd, args);
13402
+ if (!result.ok || !result.stdout.trim()) return null;
13403
+ try {
13404
+ return JSON.parse(result.stdout);
13405
+ } catch {
13406
+ return null;
13407
+ }
13408
+ }
13409
+
13410
+ // src/provider-evidence/types.ts
13411
+ function providerEvidenceKey(provider, kind, subject) {
13412
+ return `${provider} ${kind} ${subject}`;
13413
+ }
13414
+ function parseCommitEvidenceSubject(subject) {
13415
+ const at = subject.lastIndexOf("@");
13416
+ if (at <= 0 || at === subject.length - 1) return null;
13417
+ const repo = subject.slice(0, at);
13418
+ const sha = subject.slice(at + 1);
13419
+ if (!/^[^/\s]+\/[^/\s]+$/.test(repo) || !/^[0-9a-f]{7,40}$/i.test(sha)) return null;
13420
+ return { repo, sha };
13421
+ }
13422
+ function parsePrUrlSubject(subject) {
13423
+ const m = subject.trim().match(/[/:]([^/]+\/[^/]+)\/(?:pull|pulls|merge_requests|pull-requests)\/(\d+)/i);
13424
+ if (!m) return null;
13425
+ const number = Number(m[2]);
13426
+ if (!Number.isFinite(number) || number <= 0) return null;
13427
+ return { repo: m[1], number };
13428
+ }
13429
+
13430
+ // src/provider-evidence/recipes-github.ts
13431
+ var MAX_BODY_CHARS = 8e3;
13432
+ var MAX_STATUS_ROWS = 30;
13433
+ var MAX_CHECK_RUNS = 100;
13434
+ var MAX_CHANGED_FILES = 400;
13435
+ function githubCliAvailable(run) {
13436
+ if (process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim()) return true;
13437
+ return run("gh", ["auth", "token"]).ok;
13438
+ }
13439
+ function asRecord4(value) {
13440
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
13441
+ }
13442
+ function pickStatusRows(value) {
13443
+ if (!Array.isArray(value)) return [];
13444
+ return value.map((raw) => asRecord4(raw)).filter((row) => row !== null).slice(0, MAX_STATUS_ROWS).map((row) => ({
13445
+ context: row.context ?? null,
13446
+ state: row.state ?? null,
13447
+ target_url: row.target_url ?? null,
13448
+ description: row.description ?? null
13449
+ }));
13450
+ }
13451
+ function fetchCombinedStatus(run, repo, sha) {
13452
+ const status = runCliJson(run, "gh", [
13453
+ "api",
13454
+ `repos/${repo}/commits/${sha}/status`
13455
+ ]);
13456
+ if (!status) return null;
13457
+ return { state: status.state ?? null, statuses: pickStatusRows(status.statuses) };
13458
+ }
13459
+ var githubPrSnapshotRecipe = {
13460
+ provider: "github",
13461
+ kind: "pr_snapshot",
13462
+ version: "1",
13463
+ isAvailable: githubCliAvailable,
13464
+ collect(subject, run) {
13465
+ const parsed = parsePrUrlSubject(subject);
13466
+ if (!parsed) return null;
13467
+ const pull = runCliJson(run, "gh", [
13468
+ "api",
13469
+ `repos/${parsed.repo}/pulls/${parsed.number}`
13470
+ ]);
13471
+ if (!pull) return null;
13472
+ const head = asRecord4(pull.head);
13473
+ const headSha = typeof head?.sha === "string" ? head.sha : null;
13474
+ const user = asRecord4(pull.user);
13475
+ const headRepoOwner = asRecord4(asRecord4(head?.repo)?.owner);
13476
+ const body = typeof pull.body === "string" ? pull.body.slice(0, MAX_BODY_CHARS) : null;
13477
+ let checkRuns = [];
13478
+ let combinedStatus = {
13479
+ state: null,
13480
+ statuses: []
13481
+ };
13482
+ if (headSha) {
13483
+ const runs = runCliJson(run, "gh", [
13484
+ "api",
13485
+ `repos/${parsed.repo}/commits/${headSha}/check-runs?per_page=100`
13486
+ ]);
13487
+ if (Array.isArray(runs?.check_runs)) {
13488
+ checkRuns = runs.check_runs.map((raw) => asRecord4(raw)).filter((row) => row !== null).slice(0, MAX_CHECK_RUNS).map((row) => ({
13489
+ name: row.name ?? null,
13490
+ status: row.status ?? null,
13491
+ conclusion: row.conclusion ?? null
13492
+ }));
13493
+ }
13494
+ combinedStatus = fetchCombinedStatus(run, parsed.repo, headSha) ?? combinedStatus;
13495
+ }
13496
+ const filesResult = run("gh", [
13497
+ "api",
13498
+ "--paginate",
13499
+ `repos/${parsed.repo}/pulls/${parsed.number}/files?per_page=100`,
13500
+ "--jq",
13501
+ ".[].filename"
13502
+ ]);
13503
+ const changedFiles = filesResult.ok ? filesResult.stdout.split("\n").map((line) => line.trim()).filter(Boolean).slice(0, MAX_CHANGED_FILES) : [];
13504
+ return {
13505
+ pull: {
13506
+ html_url: pull.html_url ?? null,
13507
+ title: pull.title ?? null,
13508
+ body,
13509
+ user: { login: user?.login ?? null },
13510
+ state: pull.state ?? null,
13511
+ draft: pull.draft ?? null,
13512
+ merged: pull.merged ?? null,
13513
+ merged_at: pull.merged_at ?? null,
13514
+ merge_commit_sha: pull.merge_commit_sha ?? null,
13515
+ mergeable: pull.mergeable ?? null,
13516
+ mergeable_state: pull.mergeable_state ?? null,
13517
+ head: {
13518
+ sha: headSha,
13519
+ ref: head?.ref ?? null,
13520
+ repo: { owner: { login: headRepoOwner?.login ?? null } }
13521
+ }
13522
+ },
13523
+ checkRuns,
13524
+ combinedStatus,
13525
+ changedFiles
13526
+ };
13527
+ }
13528
+ };
13529
+ var githubCommitStatusRecipe = {
13530
+ provider: "github",
13531
+ kind: "commit_status",
13532
+ version: "1",
13533
+ isAvailable: githubCliAvailable,
13534
+ collect(subject, run) {
13535
+ const parsed = parseCommitEvidenceSubject(subject);
13536
+ if (!parsed) return null;
13537
+ return fetchCombinedStatus(run, parsed.repo, parsed.sha);
13538
+ }
13539
+ };
13540
+ var githubBranchReachabilityRecipe = {
13541
+ provider: "github",
13542
+ kind: "branch_reachability",
13543
+ version: "1",
13544
+ isAvailable: githubCliAvailable,
13545
+ collect(subject, run) {
13546
+ const parsed = parseCommitEvidenceSubject(subject);
13547
+ if (!parsed) return null;
13548
+ const repoMeta = runCliJson(run, "gh", [
13549
+ "api",
13550
+ `repos/${parsed.repo}`
13551
+ ]);
13552
+ const defaultBranch = typeof repoMeta?.default_branch === "string" && repoMeta.default_branch.trim() ? repoMeta.default_branch.trim() : null;
13553
+ if (!defaultBranch) return null;
13554
+ const compare = runCliJson(run, "gh", [
13555
+ "api",
13556
+ `repos/${parsed.repo}/compare/${encodeURIComponent(defaultBranch)}...${parsed.sha}`
13557
+ ]);
13558
+ if (!compare) return null;
13559
+ const compareStatus = typeof compare.status === "string" ? compare.status : null;
13560
+ return {
13561
+ defaultBranch,
13562
+ compareStatus,
13563
+ reachable: compareStatus === "identical" || compareStatus === "behind"
13564
+ };
13565
+ }
13566
+ };
13567
+
13568
+ // src/provider-evidence/recipes-vercel.ts
13569
+ var MAX_DEPLOYMENT_ROWS = 5;
13570
+ var STATE_PATTERN = /\b(READY|ERROR|BUILDING|QUEUED|CANCELED|INITIALIZING)\b/i;
13571
+ var URL_PATTERN = /https:\/\/[^\s]+/;
13572
+ var vercelDeploymentStatusRecipe = {
13573
+ provider: "vercel",
13574
+ kind: "deployment_status",
13575
+ version: "1",
13576
+ isAvailable(run) {
13577
+ return run("vercel", ["whoami"]).ok;
13578
+ },
13579
+ collect(subject, run) {
13580
+ const parsed = parseCommitEvidenceSubject(subject);
13581
+ if (!parsed) return null;
13582
+ const result = run("vercel", [
13583
+ "list",
13584
+ "--prod",
13585
+ "--meta",
13586
+ `githubCommitSha=${parsed.sha}`
13587
+ ]);
13588
+ if (!result.ok) return null;
13589
+ const deployments = [];
13590
+ for (const line of result.stdout.split("\n")) {
13591
+ const url = line.match(URL_PATTERN)?.[0];
13592
+ if (!url) continue;
13593
+ const state = line.match(STATE_PATTERN)?.[1]?.toUpperCase() ?? null;
13594
+ deployments.push({ url, state });
13595
+ if (deployments.length >= MAX_DEPLOYMENT_ROWS) break;
13596
+ }
13597
+ return { found: deployments.length > 0, deployments };
13598
+ }
13599
+ };
13600
+
13601
+ // src/provider-evidence/registry.ts
13602
+ var _recipes = [];
13603
+ function registerEvidenceCollector(recipe) {
13604
+ if (_recipes.some((r) => r.provider === recipe.provider && r.kind === recipe.kind)) return;
13605
+ _recipes.push(recipe);
13606
+ }
13607
+ function getEvidenceCollector(provider, kind) {
13608
+ return _recipes.find((r) => r.provider === provider && r.kind === kind) ?? null;
13609
+ }
13610
+ function registerDefaultEvidenceCollectors() {
13611
+ registerEvidenceCollector(githubPrSnapshotRecipe);
13612
+ registerEvidenceCollector(githubCommitStatusRecipe);
13613
+ registerEvidenceCollector(githubBranchReachabilityRecipe);
13614
+ registerEvidenceCollector(vercelDeploymentStatusRecipe);
13615
+ }
13616
+
13617
+ // src/provider-evidence/collect.ts
13618
+ var DEFAULT_MAX_SUBJECTS_PER_TICK = 8;
13619
+ var DEFAULT_DEADLINE_MS = 25e3;
13620
+ function collectProviderEvidence(wanted, opts = {}) {
13621
+ registerDefaultEvidenceCollectors();
13622
+ const run = opts.run ?? defaultCliRunner;
13623
+ const now = opts.now ?? (() => /* @__PURE__ */ new Date());
13624
+ const maxSubjects = opts.maxSubjects ?? DEFAULT_MAX_SUBJECTS_PER_TICK;
13625
+ const deadline = Date.now() + (opts.deadlineMs ?? DEFAULT_DEADLINE_MS);
13626
+ const seen = /* @__PURE__ */ new Set();
13627
+ const deduped = wanted.filter((w) => {
13628
+ const key = providerEvidenceKey(w.provider, w.kind, w.subject);
13629
+ if (seen.has(key)) return false;
13630
+ seen.add(key);
13631
+ return true;
13632
+ });
13633
+ const offset = deduped.length > 0 ? Math.floor(now().getTime() / 6e4) % deduped.length : 0;
13634
+ const rotated = deduped.map((_, i) => deduped[(offset + i) % deduped.length]);
13635
+ const window = rotated.slice(0, maxSubjects);
13636
+ const summary = {
13637
+ attempted: 0,
13638
+ collected: 0,
13639
+ items: [],
13640
+ skipped: []
13641
+ };
13642
+ const availability = /* @__PURE__ */ new Map();
13643
+ for (const item of window) {
13644
+ if (Date.now() > deadline) {
13645
+ summary.skipped.push({ ...item, reason: "budget_exhausted" });
13646
+ continue;
13647
+ }
13648
+ const recipe = getEvidenceCollector(item.provider, item.kind);
13649
+ if (!recipe) {
13650
+ summary.skipped.push({ ...item, reason: "no_recipe" });
13651
+ continue;
13652
+ }
13653
+ const availKey = `${recipe.provider} ${recipe.kind}`;
13654
+ let available = availability.get(availKey);
13655
+ if (available === void 0) {
13656
+ available = recipe.isAvailable(run);
13657
+ availability.set(availKey, available);
13658
+ }
13659
+ if (!available) {
13660
+ summary.skipped.push({ ...item, reason: "provider_unavailable" });
13661
+ continue;
13662
+ }
13663
+ summary.attempted += 1;
13664
+ const payload = recipe.collect(item.subject, run);
13665
+ if (payload === null || payload === void 0) {
13666
+ summary.skipped.push({ ...item, reason: "collect_failed" });
13667
+ continue;
13668
+ }
13669
+ summary.collected += 1;
13670
+ summary.items.push({
13671
+ provider: item.provider,
13672
+ kind: item.kind,
13673
+ subject: item.subject,
13674
+ payload,
13675
+ observedAt: now().toISOString(),
13676
+ collectorVersion: recipe.version
13677
+ });
13678
+ }
13679
+ return summary;
13680
+ }
13681
+
13682
+ // src/provider-evidence/wanted-store.ts
13683
+ init_run_store();
13684
+ init_util();
13685
+ import path59 from "node:path";
13686
+ var WANTED_FILE = "provider-evidence-wanted.json";
13687
+ function wantedFilePath(runId) {
13688
+ return path59.join(runDirectory(runId), WANTED_FILE);
13689
+ }
13690
+ function parseWantedItems(value) {
13691
+ if (!Array.isArray(value)) return [];
13692
+ const out = [];
13693
+ for (const raw of value) {
13694
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
13695
+ const row = raw;
13696
+ const provider = typeof row.provider === "string" ? row.provider.trim() : "";
13697
+ const kind = typeof row.kind === "string" ? row.kind.trim() : "";
13698
+ const subject = typeof row.subject === "string" ? row.subject.trim() : "";
13699
+ if (!provider || !kind || !subject) continue;
13700
+ out.push({ provider, kind, subject });
13701
+ }
13702
+ return out;
13703
+ }
13704
+ function loadPersistedProviderEvidenceWanted(runId) {
13705
+ const persisted = readJson(wantedFilePath(runId), null);
13706
+ return parseWantedItems(persisted?.wanted);
13707
+ }
13708
+ function persistProviderEvidenceWanted(runId, wanted) {
13709
+ writeJson(wantedFilePath(runId), {
13710
+ savedAt: (/* @__PURE__ */ new Date()).toISOString(),
13711
+ wanted
13712
+ });
13713
+ }
13714
+ function extractProviderEvidenceWanted(tickResponse) {
13715
+ if (!tickResponse || typeof tickResponse !== "object" || Array.isArray(tickResponse)) return null;
13716
+ const wanted = tickResponse.providerEvidenceWanted;
13717
+ if (!Array.isArray(wanted)) return null;
13718
+ return parseWantedItems(wanted);
13719
+ }
13720
+
12743
13721
  // src/pipeline-tick.ts
12744
13722
  async function completeFinishedWorkers(runId, args) {
12745
13723
  const run = loadRun(runId);
12746
13724
  const outcomes = [];
12747
13725
  for (const name of Object.keys(run.workers || {})) {
12748
13726
  const worker = readJson(
12749
- path58.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
13727
+ path60.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
12750
13728
  void 0
12751
13729
  );
12752
13730
  if (!worker?.taskId || worker.localOnly) continue;
@@ -12779,6 +13757,13 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args, harnessCle
12779
13757
  const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/operator/tick`;
12780
13758
  const packageVersions = await collectInstalledPackageVersions();
12781
13759
  const activeHarnessWorkers = collectRunActiveHarnessWorkers(runId);
13760
+ let evidenceCollection = null;
13761
+ try {
13762
+ const evidenceWanted = loadPersistedProviderEvidenceWanted(runId);
13763
+ evidenceCollection = evidenceWanted.length > 0 ? collectProviderEvidence(evidenceWanted) : null;
13764
+ } catch {
13765
+ evidenceCollection = null;
13766
+ }
12782
13767
  const res = await postJson(url, secret, {
12783
13768
  agentOsId,
12784
13769
  runId,
@@ -12793,9 +13778,27 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args, harnessCle
12793
13778
  ...harnessCleanup ? { harnessCleanup } : {},
12794
13779
  runnerPresence: resolveRunnerPresencePayload({ runId }),
12795
13780
  activeHarnessWorkers,
12796
- ...harnessCleanup ? { harnessCleanup } : {}
13781
+ ...evidenceCollection && evidenceCollection.items.length > 0 ? { providerEvidence: evidenceCollection.items } : {}
12797
13782
  });
12798
- return { ok: res.ok, httpStatus: res.status, response: res.response };
13783
+ const nextWanted = extractProviderEvidenceWanted(res.response);
13784
+ if (nextWanted) {
13785
+ try {
13786
+ persistProviderEvidenceWanted(runId, nextWanted);
13787
+ } catch {
13788
+ }
13789
+ }
13790
+ return {
13791
+ ok: res.ok,
13792
+ httpStatus: res.status,
13793
+ response: res.response,
13794
+ ...evidenceCollection ? {
13795
+ providerEvidence: {
13796
+ attempted: evidenceCollection.attempted,
13797
+ collected: evidenceCollection.collected,
13798
+ skipped: evidenceCollection.skipped.length
13799
+ }
13800
+ } : {}
13801
+ };
12799
13802
  }
12800
13803
  async function runPipelineTick(args) {
12801
13804
  const runId = String(required(String(args.run || ""), "--run"));
@@ -12943,6 +13946,7 @@ async function runDaemon(args) {
12943
13946
  const cronEnv = resolveKynverCronEnv();
12944
13947
  while (!stopping) {
12945
13948
  try {
13949
+ writeDaemonHeartbeat({ agentOsId, runId });
12946
13950
  if (cronEnv.tickEnabled) {
12947
13951
  const cronTick = await runKynverCronTick({
12948
13952
  env: cronEnv,
@@ -12969,8 +13973,140 @@ async function runDaemon(args) {
12969
13973
  console.error(JSON.stringify({ event: "daemon_stop", runId, agentOsId }));
12970
13974
  }
12971
13975
 
13976
+ // src/daemon-keeper.ts
13977
+ init_config();
13978
+ import { spawn as spawn6 } from "node:child_process";
13979
+ init_util();
13980
+ var DEFAULT_STALL_MS = 15 * 6e4;
13981
+ var STARTUP_GRACE_MS = 2 * 6e4;
13982
+ var KILL_GRACE_MS = 1e4;
13983
+ var BACKOFF_BASE_MS = 5e3;
13984
+ var BACKOFF_CAP_MS = 5 * 6e4;
13985
+ var HEALTHY_RESET_MS = 30 * 6e4;
13986
+ var POLL_MS = 5e3;
13987
+ function resolveKeeperStallMs(flag, env = process.env) {
13988
+ const fromFlag = typeof flag === "string" ? Number.parseInt(flag, 10) : NaN;
13989
+ if (Number.isFinite(fromFlag) && fromFlag > 0) return fromFlag;
13990
+ const fromEnv = Number.parseInt(env.KYNVER_DAEMON_STALL_MS ?? "", 10);
13991
+ if (Number.isFinite(fromEnv) && fromEnv > 0) return fromEnv;
13992
+ return DEFAULT_STALL_MS;
13993
+ }
13994
+ function shouldRunDaemonKeeper(args, env = process.env) {
13995
+ if (args.keeperChild === true || args.keeperChild === "true") return false;
13996
+ if (args.noSupervise === true || args.noSupervise === "true") return false;
13997
+ if (args.supervised === "false") return false;
13998
+ const envFlag5 = (env.KYNVER_DAEMON_SUPERVISED ?? "").trim().toLowerCase();
13999
+ if (envFlag5 === "0" || envFlag5 === "false" || envFlag5 === "no" || envFlag5 === "off") {
14000
+ return false;
14001
+ }
14002
+ return true;
14003
+ }
14004
+ function nextKeeperBackoffMs(consecutiveFailures, base = BACKOFF_BASE_MS, cap = BACKOFF_CAP_MS) {
14005
+ const exp = Math.min(Math.max(consecutiveFailures, 1) - 1, 10);
14006
+ return Math.min(base * 2 ** exp, cap);
14007
+ }
14008
+ function keeperRunWasHealthy(startedAtMs, endedAtMs, healthyMs = HEALTHY_RESET_MS) {
14009
+ return endedAtMs - startedAtMs >= healthyMs;
14010
+ }
14011
+ function keeperLog(event, detail = {}) {
14012
+ console.error(JSON.stringify({ event: `daemon_keeper_${event}`, ...detail }));
14013
+ }
14014
+ function buildKeeperChildArgv(argv) {
14015
+ const out = [];
14016
+ for (let i = 0; i < argv.length; i += 1) {
14017
+ const arg = argv[i];
14018
+ if (arg === "--supervised" || arg === "--no-supervise" || arg === "--keeper-child") continue;
14019
+ if (arg === "--stall-ms") {
14020
+ if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) i += 1;
14021
+ continue;
14022
+ }
14023
+ if (arg.startsWith("--stall-ms=") || arg.startsWith("--supervised=")) continue;
14024
+ out.push(arg);
14025
+ }
14026
+ out.push("--keeper-child");
14027
+ return out;
14028
+ }
14029
+ async function runDaemonKeeper(args, rawArgv = process.argv.slice(2)) {
14030
+ const agentOsId = String(
14031
+ required(String(args.agentOsId || loadUserConfig().agentOsId || ""), "--agent-os-id")
14032
+ );
14033
+ const stallMs = resolveKeeperStallMs(args.stallMs);
14034
+ const childArgv = buildKeeperChildArgv(rawArgv);
14035
+ const cliEntry = process.argv[1];
14036
+ let stopping = false;
14037
+ let child = null;
14038
+ let consecutiveFailures = 0;
14039
+ const stop = (signal) => {
14040
+ stopping = true;
14041
+ keeperLog("stop", { signal });
14042
+ if (child?.pid) child.kill(signal);
14043
+ };
14044
+ process.on("SIGINT", () => stop("SIGINT"));
14045
+ process.on("SIGTERM", () => stop("SIGTERM"));
14046
+ keeperLog("start", { agentOsId, stallMs, childArgv });
14047
+ while (!stopping) {
14048
+ const startedAt = Date.now();
14049
+ let exited = false;
14050
+ let exitCode = null;
14051
+ let exitSignal = null;
14052
+ child = spawn6(process.execPath, [cliEntry, ...childArgv], {
14053
+ stdio: "inherit",
14054
+ env: process.env
14055
+ });
14056
+ keeperLog("child_spawned", { pid: child.pid ?? null });
14057
+ child.on("exit", (code, signal) => {
14058
+ exited = true;
14059
+ exitCode = code;
14060
+ exitSignal = signal;
14061
+ });
14062
+ while (!exited && !stopping) {
14063
+ await sleepMsAsync(POLL_MS);
14064
+ if (exited || stopping) break;
14065
+ if (Date.now() - startedAt < STARTUP_GRACE_MS) continue;
14066
+ const beat = readDaemonHeartbeat(agentOsId);
14067
+ const ownBeat = beat && beat.pid === child.pid ? beat : null;
14068
+ if (ownBeat && isDaemonHeartbeatStale(ownBeat, stallMs)) {
14069
+ keeperLog("stall_detected", {
14070
+ pid: child.pid ?? null,
14071
+ lastBeatAt: ownBeat.observedAt,
14072
+ stallMs
14073
+ });
14074
+ child.kill("SIGTERM");
14075
+ await sleepMsAsync(KILL_GRACE_MS);
14076
+ if (!exited) child.kill("SIGKILL");
14077
+ break;
14078
+ }
14079
+ if (!ownBeat && Date.now() - startedAt > stallMs + STARTUP_GRACE_MS) {
14080
+ keeperLog("no_heartbeat_detected", { pid: child.pid ?? null, stallMs });
14081
+ child.kill("SIGTERM");
14082
+ await sleepMsAsync(KILL_GRACE_MS);
14083
+ if (!exited) child.kill("SIGKILL");
14084
+ break;
14085
+ }
14086
+ }
14087
+ while (!exited && !stopping) {
14088
+ await sleepMsAsync(POLL_MS);
14089
+ }
14090
+ if (stopping) break;
14091
+ const endedAt = Date.now();
14092
+ if (keeperRunWasHealthy(startedAt, endedAt)) consecutiveFailures = 0;
14093
+ consecutiveFailures += 1;
14094
+ const backoff = nextKeeperBackoffMs(consecutiveFailures);
14095
+ keeperLog("child_exited", {
14096
+ code: exitCode,
14097
+ signal: exitSignal,
14098
+ uptimeMs: endedAt - startedAt,
14099
+ consecutiveFailures,
14100
+ respawnInMs: backoff
14101
+ });
14102
+ await sleepMsAsync(backoff);
14103
+ }
14104
+ keeperLog("stopped", { agentOsId });
14105
+ }
14106
+
12972
14107
  // src/plan-progress.ts
12973
- import path62 from "node:path";
14108
+ init_config();
14109
+ import path64 from "node:path";
12974
14110
 
12975
14111
  // src/bounded-build/constants.ts
12976
14112
  var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
@@ -12979,6 +14115,9 @@ var DEFAULT_NODE_OLD_SPACE_SIZE_MB = 1024;
12979
14115
  var DEFAULT_SYSTEMD_MEMORY_MAX = "1.5G";
12980
14116
  var DEFAULT_SYSTEMD_MEMORY_SWAP_MAX = "2G";
12981
14117
 
14118
+ // src/bounded-build/index.ts
14119
+ init_meminfo();
14120
+
12982
14121
  // src/bounded-build/node-options.ts
12983
14122
  var MAX_OLD_SPACE_RE = /--max-old-space-size=(\d+)/;
12984
14123
  function parsePositiveInt(value, fallback) {
@@ -13008,7 +14147,7 @@ function formatNodeOptionsFlag(mb = resolveNodeOldSpaceSizeMb()) {
13008
14147
  }
13009
14148
 
13010
14149
  // src/bounded-build/systemd-wrap.ts
13011
- import { spawnSync as spawnSync8 } from "node:child_process";
14150
+ import { spawnSync as spawnSync9 } from "node:child_process";
13012
14151
  var systemdAvailableCache;
13013
14152
  function isSystemdRunAvailable() {
13014
14153
  if (process.env.KYNVER_BUILD_SKIP_SYSTEMD === "1" || process.env.KYNVER_BUILD_SKIP_SYSTEMD === "true") {
@@ -13019,7 +14158,7 @@ function isSystemdRunAvailable() {
13019
14158
  systemdAvailableCache = false;
13020
14159
  return false;
13021
14160
  }
13022
- const res = spawnSync8("systemd-run", ["--version"], { encoding: "utf8", stdio: ["ignore", "ignore", "pipe"] });
14161
+ const res = spawnSync9("systemd-run", ["--version"], { encoding: "utf8", stdio: ["ignore", "ignore", "pipe"] });
13023
14162
  systemdAvailableCache = res.status === 0;
13024
14163
  return systemdAvailableCache;
13025
14164
  }
@@ -13043,7 +14182,9 @@ function buildSystemdRunArgv(opts) {
13043
14182
  }
13044
14183
 
13045
14184
  // src/bounded-build/admission.ts
13046
- import { spawnSync as spawnSync9 } from "node:child_process";
14185
+ init_config();
14186
+ import { spawnSync as spawnSync10 } from "node:child_process";
14187
+ init_meminfo();
13047
14188
  function positiveInt4(value, fallback) {
13048
14189
  const n = Number(value);
13049
14190
  if (!Number.isFinite(n) || n <= 0) return fallback;
@@ -13079,7 +14220,7 @@ function assessBuildAdmission(opts = {}) {
13079
14220
  }
13080
14221
  function sleepMs2(ms) {
13081
14222
  if (ms <= 0) return;
13082
- spawnSync9(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
14223
+ spawnSync10(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
13083
14224
  stdio: "ignore"
13084
14225
  });
13085
14226
  }
@@ -13100,33 +14241,34 @@ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
13100
14241
  }
13101
14242
 
13102
14243
  // src/bounded-build/exec.ts
13103
- import { spawnSync as spawnSync11 } from "node:child_process";
14244
+ import { spawnSync as spawnSync12 } from "node:child_process";
13104
14245
 
13105
14246
  // src/heavy-verification/slot.ts
14247
+ init_util();
13106
14248
  import {
13107
14249
  closeSync as closeSync7,
13108
14250
  existsSync as existsSync44,
13109
- mkdirSync as mkdirSync8,
14251
+ mkdirSync as mkdirSync9,
13110
14252
  openSync as openSync7,
13111
14253
  readdirSync as readdirSync15,
13112
- readFileSync as readFileSync17,
14254
+ readFileSync as readFileSync18,
13113
14255
  unlinkSync as unlinkSync4,
13114
- writeFileSync as writeFileSync5
14256
+ writeFileSync as writeFileSync6
13115
14257
  } from "node:fs";
13116
- import path60 from "node:path";
14258
+ import path62 from "node:path";
13117
14259
 
13118
14260
  // src/heavy-verification/paths.ts
13119
- import { mkdirSync as mkdirSync7 } from "node:fs";
13120
- import path59 from "node:path";
14261
+ import { mkdirSync as mkdirSync8 } from "node:fs";
14262
+ import path61 from "node:path";
13121
14263
  function resolveHeavyVerificationRoot() {
13122
- return path59.join(resolveKynverStateRoot(), "heavy-verification");
14264
+ return path61.join(resolveKynverStateRoot(), "heavy-verification");
13123
14265
  }
13124
14266
  function heavyVerificationSlotsDir() {
13125
- return path59.join(resolveHeavyVerificationRoot(), "slots");
14267
+ return path61.join(resolveHeavyVerificationRoot(), "slots");
13126
14268
  }
13127
14269
  function ensureHeavyVerificationDirs() {
13128
14270
  const dir = heavyVerificationSlotsDir();
13129
- mkdirSync7(dir, { recursive: true });
14271
+ mkdirSync8(dir, { recursive: true });
13130
14272
  return dir;
13131
14273
  }
13132
14274
 
@@ -13151,12 +14293,12 @@ function indexedSlotId(index) {
13151
14293
  return `slot-${index}`;
13152
14294
  }
13153
14295
  function slotFilePath(slotId, slotsDir = heavyVerificationSlotsDir()) {
13154
- return path60.join(slotsDir, `${slotId}.json`);
14296
+ return path62.join(slotsDir, `${slotId}.json`);
13155
14297
  }
13156
14298
  function readSlotRecord(filePath) {
13157
14299
  if (!existsSync44(filePath)) return null;
13158
14300
  try {
13159
- const parsed = JSON.parse(readFileSync17(filePath, "utf8"));
14301
+ const parsed = JSON.parse(readFileSync18(filePath, "utf8"));
13160
14302
  if (typeof parsed.slotId === "string" && typeof parsed.pid === "number" && typeof parsed.acquiredAt === "string" && typeof parsed.command === "string") {
13161
14303
  return parsed;
13162
14304
  }
@@ -13181,7 +14323,7 @@ function reclaimStaleSlot(filePath, staleMs) {
13181
14323
  }
13182
14324
  }
13183
14325
  function ensureSlotsDir(slotsDir) {
13184
- mkdirSync8(slotsDir, { recursive: true });
14326
+ mkdirSync9(slotsDir, { recursive: true });
13185
14327
  return slotsDir;
13186
14328
  }
13187
14329
  function reclaimStaleHeavyVerificationSlots(opts = {}) {
@@ -13190,7 +14332,7 @@ function reclaimStaleHeavyVerificationSlots(opts = {}) {
13190
14332
  let reclaimed = 0;
13191
14333
  for (const name of readdirSync15(slotsDir)) {
13192
14334
  if (!name.endsWith(".json")) continue;
13193
- const filePath = path60.join(slotsDir, name);
14335
+ const filePath = path62.join(slotsDir, name);
13194
14336
  const before = existsSync44(filePath);
13195
14337
  reclaimStaleSlot(filePath, staleMs);
13196
14338
  if (before && !existsSync44(filePath)) reclaimed += 1;
@@ -13204,7 +14346,7 @@ function listActiveHeavyVerificationSlots(opts = {}) {
13204
14346
  const active = [];
13205
14347
  for (const name of readdirSync15(slotsDir)) {
13206
14348
  if (!name.endsWith(".json")) continue;
13207
- const record3 = readSlotRecord(path60.join(slotsDir, name));
14349
+ const record3 = readSlotRecord(path62.join(slotsDir, name));
13208
14350
  if (record3 && !slotIsStale(record3, staleMs)) active.push(record3);
13209
14351
  }
13210
14352
  return active;
@@ -13246,7 +14388,7 @@ function tryAcquireHeavyVerificationSlot(command, opts = {}) {
13246
14388
  };
13247
14389
  try {
13248
14390
  const fd = openSync7(filePath, "wx");
13249
- writeFileSync5(fd, JSON.stringify(record3, null, 2), "utf8");
14391
+ writeFileSync6(fd, JSON.stringify(record3, null, 2), "utf8");
13250
14392
  closeSync7(fd);
13251
14393
  const activeSlots2 = countActiveHeavyVerificationSlots({ slotsDir, staleMs });
13252
14394
  return {
@@ -13306,10 +14448,10 @@ function assessHeavyVerificationGate(command, opts = {}) {
13306
14448
  }
13307
14449
 
13308
14450
  // src/heavy-verification/gate.ts
13309
- import { spawnSync as spawnSync10 } from "node:child_process";
14451
+ import { spawnSync as spawnSync11 } from "node:child_process";
13310
14452
  function sleepMs3(ms) {
13311
14453
  if (ms <= 0) return;
13312
- spawnSync10(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
14454
+ spawnSync11(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
13313
14455
  stdio: "ignore"
13314
14456
  });
13315
14457
  }
@@ -13324,11 +14466,12 @@ function waitForHeavyVerificationSlot(command, timeoutMs, pollMs = 2e3, opts = {
13324
14466
  }
13325
14467
 
13326
14468
  // src/harness-worktree-build-guard.ts
13327
- import path61 from "node:path";
14469
+ init_paths();
14470
+ import path63 from "node:path";
13328
14471
  function isPathUnderHarnessWorktree(cwd) {
13329
14472
  const worktreesDir = harnessWorktreesDir(resolveHarnessRoot());
13330
- const rel = path61.relative(worktreesDir, path61.resolve(cwd));
13331
- return rel.length > 0 && !rel.startsWith("..") && !path61.isAbsolute(rel);
14473
+ const rel = path63.relative(worktreesDir, path63.resolve(cwd));
14474
+ return rel.length > 0 && !rel.startsWith("..") && !path63.isAbsolute(rel);
13332
14475
  }
13333
14476
  function assessHarnessWorktreeBuildGuard(cwd) {
13334
14477
  if (!isPathUnderHarnessWorktree(cwd)) return { ok: true };
@@ -13352,7 +14495,7 @@ function envArgv(env) {
13352
14495
  return out;
13353
14496
  }
13354
14497
  function runSpawn(argv, opts) {
13355
- const res = spawnSync11(argv[0], argv.slice(1), {
14498
+ const res = spawnSync12(argv[0], argv.slice(1), {
13356
14499
  cwd: opts.cwd,
13357
14500
  env: opts.env,
13358
14501
  encoding: "utf8",
@@ -13478,6 +14621,7 @@ function runHarnessVerifyCommands(cwd, commands = DEFAULT_HARNESS_VERIFY_COMMAND
13478
14621
  }
13479
14622
 
13480
14623
  // src/plan-progress.ts
14624
+ init_util();
13481
14625
  function parseEvidenceArg(raw) {
13482
14626
  const idx = raw.indexOf(":");
13483
14627
  if (idx <= 0) throw new Error(`invalid --evidence ${raw} (expected type:value)`);
@@ -13540,7 +14684,7 @@ async function emitPlanProgress(args) {
13540
14684
  }
13541
14685
  function verifyPlanLocal(args) {
13542
14686
  const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
13543
- const cwd = path62.resolve(worktree);
14687
+ const cwd = path64.resolve(worktree);
13544
14688
  const summary = runHarnessVerifyCommands(cwd);
13545
14689
  const emitJson = args.json === true || args.json === "true";
13546
14690
  const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
@@ -13589,9 +14733,10 @@ async function verifyPlan(args) {
13589
14733
  }
13590
14734
 
13591
14735
  // src/harness-verify-cli.ts
13592
- import path63 from "node:path";
14736
+ import path65 from "node:path";
14737
+ init_util();
13593
14738
  function runHarnessVerifyCli(args) {
13594
- const cwd = path63.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
14739
+ const cwd = path65.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
13595
14740
  const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
13596
14741
  const commands = [];
13597
14742
  const rawCmd = args.command;
@@ -13636,7 +14781,9 @@ function runHarnessVerifyCli(args) {
13636
14781
  }
13637
14782
 
13638
14783
  // src/plan-persist-cli.ts
13639
- import { readFileSync as readFileSync18 } from "node:fs";
14784
+ init_config();
14785
+ import { readFileSync as readFileSync19 } from "node:fs";
14786
+ init_util();
13640
14787
  var OPERATIONS = ["create", "add_version", "update_metadata"];
13641
14788
  var FAILURE_KINDS = [
13642
14789
  "approval_guard",
@@ -13648,7 +14795,7 @@ var FAILURE_KINDS = [
13648
14795
  function readBodyArg(args) {
13649
14796
  const bodyFile = args.bodyFile ? String(args.bodyFile) : void 0;
13650
14797
  if (bodyFile) {
13651
- return { body: readFileSync18(bodyFile, "utf8"), bodyPathHint: bodyFile };
14798
+ return { body: readFileSync19(bodyFile, "utf8"), bodyPathHint: bodyFile };
13652
14799
  }
13653
14800
  const inline = args.body ? String(args.body) : void 0;
13654
14801
  if (inline) return { body: inline };
@@ -14028,9 +15175,14 @@ ${text.slice(0, 800)}`,
14028
15175
  }
14029
15176
 
14030
15177
  // src/monitor/monitor.service.ts
14031
- import path65 from "node:path";
15178
+ import path67 from "node:path";
15179
+ init_run_store();
15180
+ init_status();
15181
+ init_util();
14032
15182
 
14033
15183
  // src/monitor/monitor.classify.ts
15184
+ init_status();
15185
+ init_util();
14034
15186
  function classifyWorkerHealth(input) {
14035
15187
  const { worker, status, taskLease } = input;
14036
15188
  const leaseOwner = taskLease?.leaseOwner ?? null;
@@ -14080,19 +15232,21 @@ function classifyWorkerHealth(input) {
14080
15232
  }
14081
15233
 
14082
15234
  // src/monitor/monitor.store.ts
14083
- import { existsSync as existsSync45, mkdirSync as mkdirSync9, readdirSync as readdirSync16, unlinkSync as unlinkSync5 } from "node:fs";
14084
- import path64 from "node:path";
15235
+ init_paths();
15236
+ init_util();
15237
+ import { existsSync as existsSync45, mkdirSync as mkdirSync10, readdirSync as readdirSync16, unlinkSync as unlinkSync5 } from "node:fs";
15238
+ import path66 from "node:path";
14085
15239
  function monitorsDir() {
14086
15240
  const { harnessRoot } = getHarnessPaths();
14087
- const dir = path64.join(harnessRoot, "monitors");
14088
- mkdirSync9(dir, { recursive: true });
15241
+ const dir = path66.join(harnessRoot, "monitors");
15242
+ mkdirSync10(dir, { recursive: true });
14089
15243
  return dir;
14090
15244
  }
14091
15245
  function monitorIdFor(runId, workerName) {
14092
15246
  return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
14093
15247
  }
14094
15248
  function monitorPath(monitorId) {
14095
- return path64.join(monitorsDir(), `${monitorId}.json`);
15249
+ return path66.join(monitorsDir(), `${monitorId}.json`);
14096
15250
  }
14097
15251
  function loadMonitorSession(monitorId) {
14098
15252
  return readJson(monitorPath(monitorId), void 0);
@@ -14113,7 +15267,7 @@ function listMonitorSessions() {
14113
15267
  for (const name of readdirSync16(dir)) {
14114
15268
  if (!name.endsWith(".json")) continue;
14115
15269
  const session = readJson(
14116
- path64.join(dir, name),
15270
+ path66.join(dir, name),
14117
15271
  void 0
14118
15272
  );
14119
15273
  if (!session?.monitorId) continue;
@@ -14133,6 +15287,7 @@ function listMonitorSessions() {
14133
15287
  }
14134
15288
 
14135
15289
  // src/monitor/monitor.terminal.ts
15290
+ init_status();
14136
15291
  function assessAutoCompleteEligibility(input) {
14137
15292
  const { worker, status } = input;
14138
15293
  const blockers = [];
@@ -14176,6 +15331,7 @@ function assessAutoCompleteEligibility(input) {
14176
15331
  }
14177
15332
 
14178
15333
  // src/monitor/monitor.task-lease.ts
15334
+ init_config();
14179
15335
  async function fetchTaskLeasesForWorkers(input) {
14180
15336
  const out = /* @__PURE__ */ new Map();
14181
15337
  const agentOsId = input.agentOsId?.trim();
@@ -14204,7 +15360,7 @@ async function fetchTaskLeasesForWorkers(input) {
14204
15360
  // src/monitor/monitor.service.ts
14205
15361
  function workerRecord2(runId, name) {
14206
15362
  return readJson(
14207
- path65.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
15363
+ path67.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
14208
15364
  void 0
14209
15365
  );
14210
15366
  }
@@ -14374,6 +15530,7 @@ async function monitorAutoCompleteCli(args) {
14374
15530
  }
14375
15531
 
14376
15532
  // src/monitor/monitor-loop.ts
15533
+ init_util();
14377
15534
  var DEFAULT_POLL_MS2 = 5e3;
14378
15535
  var DEFAULT_MAX_TOTAL_MS2 = 6 * 60 * 60 * 1e3;
14379
15536
  async function runMonitorLoop(args) {
@@ -14409,19 +15566,21 @@ async function runMonitorLoop(args) {
14409
15566
  }
14410
15567
 
14411
15568
  // src/monitor/monitor-spawn.ts
14412
- import { spawn as spawn6 } from "node:child_process";
15569
+ init_util();
15570
+ init_paths();
15571
+ import { spawn as spawn7 } from "node:child_process";
14413
15572
  import { closeSync as closeSync8, existsSync as existsSync46, openSync as openSync8 } from "node:fs";
14414
- import path66 from "node:path";
15573
+ import path68 from "node:path";
14415
15574
  import { fileURLToPath as fileURLToPath4 } from "node:url";
14416
15575
  function resolveDefaultCliPath2() {
14417
- return path66.join(fileURLToPath4(new URL(".", import.meta.url)), "cli.js");
15576
+ return path68.join(fileURLToPath4(new URL(".", import.meta.url)), "cli.js");
14418
15577
  }
14419
15578
  function spawnMonitorSidecar(opts) {
14420
15579
  const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
14421
15580
  if (!existsSync46(cliPath)) return void 0;
14422
15581
  const monitorId = monitorIdFor(opts.runId, opts.workerName);
14423
15582
  const { harnessRoot } = getHarnessPaths();
14424
- const logPath = path66.join(harnessRoot, "monitors", `${monitorId}.log`);
15583
+ const logPath = path68.join(harnessRoot, "monitors", `${monitorId}.log`);
14425
15584
  let logFd;
14426
15585
  try {
14427
15586
  logFd = openSync8(logPath, "a");
@@ -14455,7 +15614,7 @@ function spawnMonitorSidecar(opts) {
14455
15614
  logFd ?? "ignore"
14456
15615
  ];
14457
15616
  try {
14458
- const child = spawn6(
15617
+ const child = spawn7(
14459
15618
  nodeExecutable,
14460
15619
  args,
14461
15620
  hiddenSpawnOptions({
@@ -14490,6 +15649,7 @@ function spawnMonitorSidecar(opts) {
14490
15649
  }
14491
15650
 
14492
15651
  // src/monitor/monitor-cli.ts
15652
+ init_util();
14493
15653
  async function startMonitorCli(args) {
14494
15654
  const runId = String(args.run || "");
14495
15655
  required(runId, "--run");
@@ -14541,7 +15701,11 @@ async function monitorTickCli(args) {
14541
15701
  }
14542
15702
 
14543
15703
  // src/post-restart-unblock.ts
14544
- import path67 from "node:path";
15704
+ init_run_store();
15705
+ init_status();
15706
+ init_util();
15707
+ init_config();
15708
+ import path69 from "node:path";
14545
15709
  function skip(runId, worker, taskId, agentOsId, leaseOwner, reason) {
14546
15710
  return { runId, worker, taskId, agentOsId, leaseOwner, action: "skipped", reason };
14547
15711
  }
@@ -14554,7 +15718,7 @@ async function postRestartUnblock(args) {
14554
15718
  const errors = [];
14555
15719
  for (const run of listRunRecords()) {
14556
15720
  for (const name of Object.keys(run.workers ?? {})) {
14557
- const workerPath = path67.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json");
15721
+ const workerPath = path69.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json");
14558
15722
  const worker = readJson(workerPath, void 0);
14559
15723
  if (!worker) {
14560
15724
  skipped.push(skip(run.id, name, "", "", "", "worker.json missing"));
@@ -14666,9 +15830,11 @@ async function postRestartUnblockCli(args) {
14666
15830
  }
14667
15831
 
14668
15832
  // src/default-repo-cli.ts
14669
- import path68 from "node:path";
14670
- import { homedir as homedir15 } from "node:os";
14671
- var CONFIG_FILE2 = path68.join(homedir15(), ".kynver", "config.json");
15833
+ init_path_values();
15834
+ init_config();
15835
+ import path70 from "node:path";
15836
+ import { homedir as homedir16 } from "node:os";
15837
+ var CONFIG_FILE2 = path70.join(homedir16(), ".kynver", "config.json");
14672
15838
  function ensureDefaultRepo(opts) {
14673
15839
  const existing = loadUserConfig();
14674
15840
  const resolved = resolveDefaultRepo({ ...opts, config: existing });
@@ -14749,16 +15915,19 @@ function summarizeResolvedDefaultRepo(resolved) {
14749
15915
  }
14750
15916
 
14751
15917
  // src/doctor/runtime-takeover.ts
14752
- import path70 from "node:path";
15918
+ import path72 from "node:path";
15919
+ init_path_values();
14753
15920
 
14754
15921
  // src/doctor/runtime-takeover.probes.ts
14755
- import { accessSync, constants, existsSync as existsSync47, readFileSync as readFileSync19 } from "node:fs";
14756
- import { homedir as homedir16 } from "node:os";
14757
- import path69 from "node:path";
14758
- import { spawnSync as spawnSync12 } from "node:child_process";
15922
+ init_config();
15923
+ import { accessSync, constants, existsSync as existsSync47, readFileSync as readFileSync20 } from "node:fs";
15924
+ import { homedir as homedir17 } from "node:os";
15925
+ import path71 from "node:path";
15926
+ import { spawnSync as spawnSync13 } from "node:child_process";
15927
+ init_paths();
14759
15928
  function captureCommand(bin, args) {
14760
15929
  try {
14761
- const res = spawnSync12(bin, args, { encoding: "utf8" });
15930
+ const res = spawnSync13(bin, args, { encoding: "utf8" });
14762
15931
  const stdout = (res.stdout || "").trim();
14763
15932
  const stderr = (res.stderr || "").trim();
14764
15933
  const ok = res.status === 0;
@@ -14796,15 +15965,15 @@ var defaultRuntimeTakeoverProbes = {
14796
15965
  commandOnPath: (bin) => captureCommand(process.platform === "win32" ? "where" : "which", [bin]),
14797
15966
  kynverVersion: (bin) => captureCommand(bin, ["--version"]),
14798
15967
  loadConfig: () => loadUserConfig(),
14799
- configFilePath: () => path69.join(homedir16(), ".kynver", "config.json"),
14800
- credentialsFilePath: () => path69.join(homedir16(), ".kynver", "credentials"),
15968
+ configFilePath: () => path71.join(homedir17(), ".kynver", "config.json"),
15969
+ credentialsFilePath: () => path71.join(homedir17(), ".kynver", "credentials"),
14801
15970
  readCredentials: () => {
14802
- const credPath = path69.join(homedir16(), ".kynver", "credentials");
15971
+ const credPath = path71.join(homedir17(), ".kynver", "credentials");
14803
15972
  if (!existsSync47(credPath)) {
14804
15973
  return { hasApiKey: false };
14805
15974
  }
14806
15975
  try {
14807
- const parsed = JSON.parse(readFileSync19(credPath, "utf8"));
15976
+ const parsed = JSON.parse(readFileSync20(credPath, "utf8"));
14808
15977
  return {
14809
15978
  hasApiKey: Boolean(parsed.apiKey?.trim()),
14810
15979
  runnerTokenPrefix: tokenPrefix(parsed.runnerToken),
@@ -14834,7 +16003,7 @@ var defaultRuntimeTakeoverProbes = {
14834
16003
  })()
14835
16004
  }),
14836
16005
  harnessRoot: () => resolveHarnessRoot(),
14837
- legacyOpenclawHarnessRoot: () => path69.join(homedir16(), ".openclaw", "harness"),
16006
+ legacyOpenclawHarnessRoot: () => path71.join(homedir17(), ".openclaw", "harness"),
14838
16007
  pathExists: (target) => existsSync47(target),
14839
16008
  pathWritable: (target) => isWritable(target)
14840
16009
  };
@@ -15241,8 +16410,8 @@ function assessVercelDeployEvidence(probes) {
15241
16410
  }
15242
16411
  function assessHarnessDirs(probes) {
15243
16412
  const harnessRoot = probes.harnessRoot();
15244
- const runsDir = path70.join(harnessRoot, "runs");
15245
- const worktreesDir = path70.join(harnessRoot, "worktrees");
16413
+ const runsDir = path72.join(harnessRoot, "runs");
16414
+ const worktreesDir = path72.join(harnessRoot, "worktrees");
15246
16415
  const displayHarnessRoot = redactHomePath(harnessRoot);
15247
16416
  const displayRunsDir = redactHomePath(runsDir);
15248
16417
  const displayWorktreesDir = redactHomePath(worktreesDir);
@@ -15418,6 +16587,7 @@ function runRuntimeTakeoverDoctorCli(args = {}) {
15418
16587
  }
15419
16588
 
15420
16589
  // src/command-center-contract-cli.ts
16590
+ init_config();
15421
16591
  async function runCommandCenterContractCli(args) {
15422
16592
  const config = loadUserConfig();
15423
16593
  const agentOsId = (args.agentOsId ? String(args.agentOsId) : config.agentOsId) || "";
@@ -15448,6 +16618,9 @@ async function runCommandCenterContractCli(args) {
15448
16618
  console.log(JSON.stringify(res.response, null, 2));
15449
16619
  }
15450
16620
 
16621
+ // src/scheduler-cutover-cli.ts
16622
+ init_path_values();
16623
+
15451
16624
  // src/scheduler-cutover.ts
15452
16625
  var DEPLOYMENT_SCHEDULER_CUTOVER_STEPS = [
15453
16626
  "Vercel/hosted: set KYNVER_SCHEDULER_PROVIDER=qstash",
@@ -15506,9 +16679,10 @@ function applySchedulerCutoverAttestation(config) {
15506
16679
  }
15507
16680
 
15508
16681
  // src/scheduler-cutover-cli.ts
15509
- import path71 from "node:path";
15510
- import { homedir as homedir17 } from "node:os";
15511
- var CONFIG_FILE3 = path71.join(homedir17(), ".kynver", "config.json");
16682
+ init_config();
16683
+ import path73 from "node:path";
16684
+ import { homedir as homedir18 } from "node:os";
16685
+ var CONFIG_FILE3 = path73.join(homedir18(), ".kynver", "config.json");
15512
16686
  function runSchedulerCutoverCheckCli(json = false) {
15513
16687
  const config = loadUserConfig();
15514
16688
  const report = assessSchedulerCutover(config);
@@ -15646,7 +16820,12 @@ async function runCronTickCli(args) {
15646
16820
  }
15647
16821
 
15648
16822
  // src/lane/landing-maintainer-tick.ts
15649
- import os9 from "node:os";
16823
+ init_config();
16824
+ import os11 from "node:os";
16825
+ init_config();
16826
+ init_box_identity();
16827
+ init_resource_gate();
16828
+ init_util();
15650
16829
 
15651
16830
  // src/lane/lane-spec.ts
15652
16831
  var LANDING_MAINTAINER_LANE_SPEC = {
@@ -15658,10 +16837,10 @@ var LANDING_MAINTAINER_LANE_SPEC = {
15658
16837
  };
15659
16838
 
15660
16839
  // src/lane/landing-maintainer-local.ts
15661
- import { spawnSync as spawnSync13 } from "node:child_process";
15662
- import path72 from "node:path";
16840
+ import { spawnSync as spawnSync14 } from "node:child_process";
16841
+ import path74 from "node:path";
15663
16842
  function runLandingWrapper(prNumber, repoRoot, execute) {
15664
- const script = path72.join(repoRoot, LANDING_MAINTAINER_LANE_SPEC.landScript);
16843
+ const script = path74.join(repoRoot, LANDING_MAINTAINER_LANE_SPEC.landScript);
15665
16844
  const args = [script, String(prNumber), ...LANDING_MAINTAINER_LANE_SPEC.landScriptArgs];
15666
16845
  if (!execute) {
15667
16846
  return {
@@ -15672,7 +16851,7 @@ function runLandingWrapper(prNumber, repoRoot, execute) {
15672
16851
  stderr: ""
15673
16852
  };
15674
16853
  }
15675
- const result = spawnSync13("node", args, {
16854
+ const result = spawnSync14("node", args, {
15676
16855
  cwd: repoRoot,
15677
16856
  encoding: "utf8",
15678
16857
  timeout: 10 * 60 * 1e3
@@ -15687,7 +16866,7 @@ function runLandingWrapper(prNumber, repoRoot, execute) {
15687
16866
  }
15688
16867
  function resolveLandingMaintainerRepoRoot(args) {
15689
16868
  const explicit = args.repoPath ? String(args.repoPath).trim() : "";
15690
- if (explicit) return path72.resolve(explicit);
16869
+ if (explicit) return path74.resolve(explicit);
15691
16870
  const resolved = resolveDefaultRepo();
15692
16871
  return resolved?.repo ?? process.cwd();
15693
16872
  }
@@ -15706,7 +16885,7 @@ async function runLandingMaintainerLaneTick(args) {
15706
16885
  ...buildBoxResourceSnapshotFromGate(resourceGate, {
15707
16886
  harnessRunId: runId,
15708
16887
  boxKind: resolveBoxKindFromConfig(loadUserConfig()),
15709
- hostLabel: os9.hostname()
16888
+ hostLabel: os11.hostname()
15710
16889
  }),
15711
16890
  providerHealthy: resourceGate.ok,
15712
16891
  authorizedForRepair: resourceGate.ok,
@@ -15810,10 +16989,11 @@ function usage(code = 0) {
15810
16989
  out(
15811
16990
  [
15812
16991
  "Usage:",
15813
- " kynver login --api-key KEY",
16992
+ " kynver login [--api-key KEY] [--api-base-url URL] (omit --api-key to authorize in the browser)",
16993
+ " kynver bootstrap [--api-base-url URL] [--api-key KEY] [--repo PATH] (login + setup + runner credential in one shot)",
15814
16994
  " kynver runner credential [--agent-os-id ID] [--base-url URL]",
15815
16995
  " kynver setup [--api-base-url URL] [--agent-os-id ID] [--agent-os-slug SLUG] [--box-kind forge|ghost] [--repo PATH] [--discover-repo] [--max-workers N] [--provider claude|cursor]",
15816
- " kynver daemon --run RUN_ID --agent-os-id AOS_ID [--execute] [--interval-ms MS]",
16996
+ " kynver daemon --run RUN_ID --agent-os-id AOS_ID [--execute] [--interval-ms MS] [--stall-ms MS] [--no-supervise]",
15817
16997
  " kynver status --run RUN_ID [--blocked] [--running] [--task TASK_ID] [--worker WORKER] [--full] # top-level compact run status",
15818
16998
  " kynver run create [--repo /path/repo] [--name name] [--base origin/main]",
15819
16999
  " kynver run list",
@@ -15874,8 +17054,8 @@ async function main(argv = process.argv.slice(2)) {
15874
17054
  if (action && isHelpFlag(action) || rest.some(isHelpFlag)) return usage(0);
15875
17055
  const args = parseArgs(rest);
15876
17056
  const { runsDir, worktreesDir } = getPaths();
15877
- mkdirSync10(runsDir, { recursive: true });
15878
- mkdirSync10(worktreesDir, { recursive: true });
17057
+ mkdirSync11(runsDir, { recursive: true });
17058
+ mkdirSync11(worktreesDir, { recursive: true });
15879
17059
  if (scope === "daemon") {
15880
17060
  assertNativeDaemonAllowed();
15881
17061
  }
@@ -15895,10 +17075,16 @@ async function main(argv = process.argv.slice(2)) {
15895
17075
  });
15896
17076
  }
15897
17077
  if (scope === "login") return void await runLogin(args);
17078
+ if (scope === "bootstrap") return void await runBootstrap(args);
15898
17079
  if (scope === "status") return runStatus(args);
15899
17080
  if (scope === "runner" && action === "credential") return void await mintRunnerCredential(args);
15900
17081
  if (scope === "setup") return void await runSetup(args);
15901
- if (scope === "daemon") return void await runDaemon(args);
17082
+ if (scope === "daemon") {
17083
+ if (shouldRunDaemonKeeper(args)) {
17084
+ return void await runDaemonKeeper(args);
17085
+ }
17086
+ return void await runDaemon(args);
17087
+ }
15902
17088
  if (scope === "plan" && action === "progress") return void await emitPlanProgress(args);
15903
17089
  if (scope === "plan" && action === "verify") return void await verifyPlan(args);
15904
17090
  if (scope === "harness" && action === "verify") return runHarnessVerifyCli(args);