@kynver-app/runtime 0.1.42 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +15 -0
  2. package/dist/auto-complete.d.ts +60 -0
  3. package/dist/bounded-build/admission.d.ts +30 -0
  4. package/dist/bounded-build/constants.d.ts +10 -0
  5. package/dist/bounded-build/exec.d.ts +26 -0
  6. package/dist/bounded-build/index.d.ts +6 -0
  7. package/dist/bounded-build/meminfo.d.ts +5 -0
  8. package/dist/bounded-build/node-options.d.ts +9 -0
  9. package/dist/bounded-build/systemd-wrap.d.ts +17 -0
  10. package/dist/callback-headers.d.ts +2 -0
  11. package/dist/callbacks.d.ts +38 -0
  12. package/dist/cleanup-cli.d.ts +1 -0
  13. package/dist/cleanup-dir-size.d.ts +4 -0
  14. package/dist/cleanup-execute.d.ts +4 -0
  15. package/dist/cleanup-guards.d.ts +18 -0
  16. package/dist/cleanup-scan.d.ts +14 -0
  17. package/dist/cleanup-types.d.ts +56 -0
  18. package/dist/cleanup-worktree-index.d.ts +13 -0
  19. package/dist/cleanup.d.ts +5 -0
  20. package/dist/cli.d.ts +3 -0
  21. package/dist/cli.js +789 -74
  22. package/dist/cli.js.map +4 -4
  23. package/dist/command-center-contract-cli.d.ts +1 -0
  24. package/dist/completion-ack.d.ts +10 -0
  25. package/dist/completion-response.d.ts +15 -0
  26. package/dist/config.d.ts +61 -0
  27. package/dist/daemon.d.ts +5 -0
  28. package/dist/disk-gate.d.ts +9 -0
  29. package/dist/dispatch.d.ts +16 -0
  30. package/dist/doctor/doctor.types.d.ts +25 -0
  31. package/dist/doctor/index.d.ts +4 -0
  32. package/dist/doctor/runtime-takeover-cli.d.ts +1 -0
  33. package/dist/doctor/runtime-takeover.d.ts +3 -0
  34. package/dist/doctor/runtime-takeover.probes.d.ts +37 -0
  35. package/dist/exit-classify.d.ts +12 -0
  36. package/dist/exited-salvage.d.ts +22 -0
  37. package/dist/finalize.d.ts +16 -0
  38. package/dist/fortress-engagement-gate.d.ts +5 -0
  39. package/dist/git.d.ts +37 -0
  40. package/dist/github-repo.d.ts +5 -0
  41. package/dist/harness-verify-cli.d.ts +1 -0
  42. package/dist/harness-verify.d.ts +19 -0
  43. package/dist/heartbeat.d.ts +22 -0
  44. package/dist/index.d.ts +33 -0
  45. package/dist/index.js +829 -78
  46. package/dist/index.js.map +4 -4
  47. package/dist/installed-package-versions.d.ts +6 -0
  48. package/dist/landing-contract-gate.d.ts +24 -0
  49. package/dist/landing-gate.d.ts +24 -0
  50. package/dist/lease-renewal.d.ts +15 -0
  51. package/dist/model-routing-task-enrich.d.ts +8 -0
  52. package/dist/model-routing.d.ts +29 -0
  53. package/dist/monitor/index.d.ts +7 -0
  54. package/dist/monitor/monitor-cli.d.ts +9 -0
  55. package/dist/monitor/monitor-loop.d.ts +1 -0
  56. package/dist/monitor/monitor-spawn.d.ts +18 -0
  57. package/dist/monitor/monitor.classify.d.ts +15 -0
  58. package/dist/monitor/monitor.service.d.ts +17 -0
  59. package/dist/monitor/monitor.store.d.ts +6 -0
  60. package/dist/monitor/monitor.task-lease.d.ts +11 -0
  61. package/dist/monitor/monitor.terminal.d.ts +11 -0
  62. package/dist/monitor/monitor.types.d.ts +74 -0
  63. package/dist/package-version.d.ts +5 -0
  64. package/dist/path-values.d.ts +5 -0
  65. package/dist/paths.d.ts +7 -0
  66. package/dist/pipeline-dispatch.d.ts +7 -0
  67. package/dist/pipeline-tick.d.ts +45 -0
  68. package/dist/plan-persist/agentos-api.d.ts +28 -0
  69. package/dist/plan-persist/body-hash.d.ts +3 -0
  70. package/dist/plan-persist/drain.d.ts +7 -0
  71. package/dist/plan-persist/errors.d.ts +9 -0
  72. package/dist/plan-persist/handoff.d.ts +7 -0
  73. package/dist/plan-persist/idempotency.d.ts +2 -0
  74. package/dist/plan-persist/index.d.ts +8 -0
  75. package/dist/plan-persist/outbox-store.d.ts +18 -0
  76. package/dist/plan-persist/paths.d.ts +8 -0
  77. package/dist/plan-persist/persist.d.ts +10 -0
  78. package/dist/plan-persist/readback.d.ts +17 -0
  79. package/dist/plan-persist/types.d.ts +91 -0
  80. package/dist/plan-persist-cli.d.ts +3 -0
  81. package/dist/plan-progress-daemon-sync.d.ts +7 -0
  82. package/dist/plan-progress-sync.d.ts +21 -0
  83. package/dist/plan-progress.d.ts +10 -0
  84. package/dist/pr-handoff/index.d.ts +4 -0
  85. package/dist/pr-handoff/pr-handoff-assess.d.ts +26 -0
  86. package/dist/pr-handoff/pr-handoff-gh.d.ts +44 -0
  87. package/dist/pr-handoff/pr-handoff.d.ts +8 -0
  88. package/dist/pr-handoff/pr-handoff.types.d.ts +45 -0
  89. package/dist/prompt.d.ts +14 -0
  90. package/dist/providers/claude.d.ts +4 -0
  91. package/dist/providers/cursor-windows.d.ts +7 -0
  92. package/dist/providers/cursor.d.ts +11 -0
  93. package/dist/providers/model-preflight.d.ts +31 -0
  94. package/dist/providers/registry.d.ts +4 -0
  95. package/dist/providers/types.d.ts +32 -0
  96. package/dist/redact.d.ts +1 -0
  97. package/dist/resource-gate.d.ts +53 -0
  98. package/dist/retry-limits.d.ts +8 -0
  99. package/dist/run-store.d.ts +30 -0
  100. package/dist/shell-command-outcome.d.ts +32 -0
  101. package/dist/stale-reconcile.d.ts +25 -0
  102. package/dist/status.d.ts +161 -0
  103. package/dist/stream.d.ts +20 -0
  104. package/dist/supervisor.d.ts +25 -0
  105. package/dist/sweep.d.ts +1 -0
  106. package/dist/util.d.ts +22 -0
  107. package/dist/validate.d.ts +5 -0
  108. package/dist/vercel/index.d.ts +3 -0
  109. package/dist/vercel/vercel-evidence.d.ts +48 -0
  110. package/dist/vercel/vercel-github-status.d.ts +19 -0
  111. package/dist/vercel/vercel-url.d.ts +16 -0
  112. package/dist/worker-env.d.ts +15 -0
  113. package/dist/worker-lifecycle.d.ts +28 -0
  114. package/dist/worker-ops.d.ts +20 -0
  115. package/dist/workspace-runtime-config.d.ts +8 -0
  116. package/dist/worktree.d.ts +4 -0
  117. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -508,12 +508,12 @@ var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
508
508
  var DEFAULT_MAX_USED_PERCENT = 80;
509
509
  var DEFAULT_HARD_MAX_USED_PERCENT = 90;
510
510
  function observeRunnerDiskGate(input = {}) {
511
- const path35 = input.diskPath?.trim() || "/";
511
+ const path38 = input.diskPath?.trim() || "/";
512
512
  const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
513
513
  const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
514
514
  const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
515
515
  const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
516
- const stats = statfsSync(path35);
516
+ const stats = statfsSync(path38);
517
517
  const freeBytes = Number(stats.bavail) * Number(stats.bsize);
518
518
  const totalBytes = Number(stats.blocks) * Number(stats.bsize);
519
519
  const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
@@ -533,7 +533,7 @@ function observeRunnerDiskGate(input = {}) {
533
533
  }
534
534
  return {
535
535
  ok,
536
- path: path35,
536
+ path: path38,
537
537
  freeBytes,
538
538
  totalBytes,
539
539
  usedPercent,
@@ -546,8 +546,29 @@ function observeRunnerDiskGate(input = {}) {
546
546
  }
547
547
 
548
548
  // src/resource-gate.ts
549
- import { readFileSync as readFileSync6 } from "node:fs";
549
+ import os2 from "node:os";
550
+
551
+ // src/bounded-build/meminfo.ts
552
+ import { readFileSync as readFileSync4 } from "node:fs";
550
553
  import os from "node:os";
554
+ function readMemAvailableBytes(meminfoText) {
555
+ if (meminfoText !== void 0) {
556
+ const match = meminfoText.match(/^MemAvailable:\s+(\d+)\s*kB/m);
557
+ if (match) return Number(match[1]) * 1024;
558
+ return os.freemem();
559
+ }
560
+ if (process.platform === "linux") {
561
+ try {
562
+ const meminfo = readFileSync4("/proc/meminfo", "utf8");
563
+ const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
564
+ if (match) return Number(match[1]) * 1024;
565
+ } catch {
566
+ }
567
+ }
568
+ return os.freemem();
569
+ }
570
+
571
+ // src/resource-gate.ts
551
572
  import path6 from "node:path";
552
573
 
553
574
  // src/run-store.ts
@@ -623,7 +644,7 @@ function runDirectory(id) {
623
644
  }
624
645
 
625
646
  // src/heartbeat.ts
626
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:fs";
647
+ import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
627
648
  var HEARTBEAT_FUTURE_SKEW_MS = 6e4;
628
649
  function isTerminalHeartbeatPhase(phase) {
629
650
  return phase === "complete";
@@ -645,7 +666,7 @@ function parseHeartbeat(file) {
645
666
  if (!existsSync6(file)) return result;
646
667
  const maxFutureMs = Date.now() + HEARTBEAT_FUTURE_SKEW_MS;
647
668
  const clampedTo = new Date(maxFutureMs).toISOString();
648
- const lines = readFileSync4(file, "utf8").split("\n").filter(Boolean);
669
+ const lines = readFileSync5(file, "utf8").split("\n").filter(Boolean);
649
670
  for (const line of lines) {
650
671
  const entry = safeJson(line);
651
672
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
@@ -672,7 +693,155 @@ function parseHeartbeat(file) {
672
693
  }
673
694
 
674
695
  // src/stream.ts
675
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
696
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
697
+
698
+ // src/shell-command-outcome.ts
699
+ var NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
700
+ function tidy(text, max = 200) {
701
+ const one = text.replace(/\s+/g, " ").trim();
702
+ return one.length > max ? `${one.slice(0, max - 1)}\u2026` : one;
703
+ }
704
+ function extractJsonObject(text) {
705
+ const trimmed = text.trim();
706
+ if (!trimmed) return null;
707
+ if (trimmed.startsWith("{")) {
708
+ try {
709
+ return JSON.parse(trimmed);
710
+ } catch {
711
+ }
712
+ }
713
+ const start = trimmed.indexOf("{");
714
+ const end = trimmed.lastIndexOf("}");
715
+ if (start >= 0 && end > start) {
716
+ try {
717
+ return JSON.parse(trimmed.slice(start, end + 1));
718
+ } catch {
719
+ return null;
720
+ }
721
+ }
722
+ return null;
723
+ }
724
+ function isRecord(value) {
725
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
726
+ }
727
+ function summarizeNpmAuditReport(report) {
728
+ const meta = report.metadata;
729
+ if (!isRecord(meta)) return null;
730
+ const vuln = meta.vulnerabilities;
731
+ if (!isRecord(vuln)) return null;
732
+ const num = (key) => typeof vuln[key] === "number" ? vuln[key] : 0;
733
+ const summary = {
734
+ info: num("info"),
735
+ low: num("low"),
736
+ moderate: num("moderate"),
737
+ high: num("high"),
738
+ critical: num("critical"),
739
+ total: num("total")
740
+ };
741
+ if (typeof vuln.total !== "number" && !summary.critical && !summary.high && !summary.moderate && !summary.low && !summary.info) {
742
+ return null;
743
+ }
744
+ return summary;
745
+ }
746
+ function formatAuditSummaryLine(audit) {
747
+ const parts = [];
748
+ if (audit.critical) parts.push(`${audit.critical} critical`);
749
+ if (audit.high) parts.push(`${audit.high} high`);
750
+ if (audit.moderate) parts.push(`${audit.moderate} moderate`);
751
+ if (audit.low) parts.push(`${audit.low} low`);
752
+ if (audit.info) parts.push(`${audit.info} info`);
753
+ const breakdown = parts.length ? parts.join(", ") : "see report";
754
+ return `npm audit: ${audit.total} vulnerabilit${audit.total === 1 ? "y" : "ies"} (${breakdown}) \u2014 remediation required`;
755
+ }
756
+ function npmAuditFailureReason(report, stderr) {
757
+ const err = report.error;
758
+ if (isRecord(err)) {
759
+ const summary = typeof err.summary === "string" ? err.summary.trim() : "";
760
+ const code = typeof err.code === "string" ? err.code.trim() : "";
761
+ if (summary) return code ? `${code}: ${summary}` : summary;
762
+ if (code) return code;
763
+ }
764
+ const detail = typeof report.message === "string" ? report.message.trim() : "";
765
+ if (detail) return detail;
766
+ const errTail = stderr.trim();
767
+ if (errTail) return tidy(errTail.split("\n").find(Boolean) ?? errTail, 160);
768
+ return "npm audit failed";
769
+ }
770
+ function classifyNpmAuditOutcome(input) {
771
+ const combined = `${input.stdout}
772
+ ${input.stderr}`.trim();
773
+ const parsed = extractJsonObject(combined);
774
+ if (!parsed || !isRecord(parsed)) {
775
+ const tail = tidy(combined || `exit ${input.exitCode}`, 180);
776
+ return {
777
+ kind: "command_failure",
778
+ exitCode: input.exitCode,
779
+ summary: `npm audit failed (invalid or missing JSON): ${tail}`,
780
+ parseError: "invalid_json"
781
+ };
782
+ }
783
+ if (isRecord(parsed.error)) {
784
+ return {
785
+ kind: "command_failure",
786
+ exitCode: input.exitCode,
787
+ summary: `npm audit command failed: ${npmAuditFailureReason(parsed, input.stderr)}`
788
+ };
789
+ }
790
+ const audit = summarizeNpmAuditReport(parsed);
791
+ if (!audit) {
792
+ return {
793
+ kind: "command_failure",
794
+ exitCode: input.exitCode,
795
+ summary: "npm audit failed: JSON response missing vulnerability metadata",
796
+ parseError: "missing_metadata"
797
+ };
798
+ }
799
+ if (input.exitCode === 0 && audit.total === 0) {
800
+ return {
801
+ kind: "success",
802
+ exitCode: 0,
803
+ summary: "npm audit: no vulnerabilities reported",
804
+ audit
805
+ };
806
+ }
807
+ return {
808
+ kind: "audit_findings",
809
+ exitCode: input.exitCode,
810
+ summary: formatAuditSummaryLine(audit),
811
+ audit
812
+ };
813
+ }
814
+ function isNpmAuditCommand(command) {
815
+ return NPM_AUDIT_RE.test(command);
816
+ }
817
+ function classifyShellCommandOutcome(input) {
818
+ const stdout = input.stdout ?? "";
819
+ const stderr = input.stderr ?? "";
820
+ const interleaved = input.interleavedOutput ?? "";
821
+ if (isNpmAuditCommand(input.command)) {
822
+ const body = stdout.trim() || interleaved.trim() || stderr.trim();
823
+ return classifyNpmAuditOutcome({
824
+ exitCode: input.exitCode,
825
+ stdout: body,
826
+ stderr
827
+ });
828
+ }
829
+ if (input.exitCode === 0) {
830
+ return {
831
+ kind: "success",
832
+ exitCode: 0,
833
+ summary: `command succeeded (exit 0)`
834
+ };
835
+ }
836
+ const tail = tidy(interleaved || stdout || stderr || `exit ${input.exitCode}`, 180);
837
+ return {
838
+ kind: "command_failure",
839
+ exitCode: input.exitCode,
840
+ summary: `command failed (exit ${input.exitCode}): ${tail}`
841
+ };
842
+ }
843
+
844
+ // src/stream.ts
676
845
  function eventTimestampIso(event) {
677
846
  const tsMs = event.timestamp_ms;
678
847
  return event.timestamp || event.ts || (tsMs ? new Date(tsMs).toISOString() : void 0);
@@ -693,16 +862,43 @@ function recordStreamResult(result, event) {
693
862
  result.error = String(event.result || event.api_error_status || "stream result error");
694
863
  }
695
864
  }
865
+ function shellPayloadFromCursorEvent(event) {
866
+ if (event.type !== "tool_call" || event.subtype !== "completed") return null;
867
+ const toolCall = event.tool_call && typeof event.tool_call === "object" && !Array.isArray(event.tool_call) ? event.tool_call : null;
868
+ const shell = toolCall?.shellToolCall;
869
+ if (!shell || typeof shell !== "object" || Array.isArray(shell)) return null;
870
+ const shellObj = shell;
871
+ const args = shellObj.args;
872
+ const command = args && typeof args === "object" && !Array.isArray(args) && typeof args.command === "string" ? String(args.command) : "";
873
+ const result = shellObj.result;
874
+ if (!result || typeof result !== "object" || Array.isArray(result)) return null;
875
+ const body = result.success ?? result.failure;
876
+ if (!body || typeof body !== "object" || Array.isArray(body)) return null;
877
+ const row = body;
878
+ const exitCode = typeof row.exitCode === "number" ? row.exitCode : 0;
879
+ return {
880
+ command,
881
+ exitCode,
882
+ stdout: typeof row.stdout === "string" ? row.stdout : "",
883
+ stderr: typeof row.stderr === "string" ? row.stderr : "",
884
+ interleaved: typeof row.interleavedOutput === "string" ? row.interleavedOutput : ""
885
+ };
886
+ }
887
+ function applyShellOutcome(parsed, outcome) {
888
+ if (outcome.kind === "success") return;
889
+ parsed.lastShellOutcome = outcome;
890
+ }
696
891
  function parseHarnessStream(file) {
697
892
  const result = {
698
893
  firstEventAt: null,
699
894
  lastEventAt: null,
700
895
  currentTool: null,
701
896
  finalResult: null,
702
- error: null
897
+ error: null,
898
+ lastShellOutcome: null
703
899
  };
704
900
  if (!existsSync7(file)) return result;
705
- const lines = readFileSync5(file, "utf8").split("\n").filter(Boolean);
901
+ const lines = readFileSync6(file, "utf8").split("\n").filter(Boolean);
706
902
  for (const line of lines) {
707
903
  const event = safeJson(line);
708
904
  if (!event) continue;
@@ -727,6 +923,19 @@ function parseHarnessStream(file) {
727
923
  const name = cursorToolNameFromCall(toolCall);
728
924
  if (name) result.currentTool = name;
729
925
  }
926
+ const shell = shellPayloadFromCursorEvent(event);
927
+ if (shell) {
928
+ applyShellOutcome(
929
+ result,
930
+ classifyShellCommandOutcome({
931
+ command: shell.command,
932
+ exitCode: shell.exitCode,
933
+ stdout: shell.stdout,
934
+ stderr: shell.stderr,
935
+ interleavedOutput: shell.interleaved
936
+ })
937
+ );
938
+ }
730
939
  if (event.type === "result") {
731
940
  recordStreamResult(result, event);
732
941
  }
@@ -736,6 +945,25 @@ function parseHarnessStream(file) {
736
945
  function parseClaudeStream(file) {
737
946
  return parseHarnessStream(file);
738
947
  }
948
+ function summarizeShellToolCallEvent(event) {
949
+ const shell = shellPayloadFromCursorEvent(event);
950
+ if (!shell) return void 0;
951
+ const outcome = classifyShellCommandOutcome({
952
+ command: shell.command,
953
+ exitCode: shell.exitCode,
954
+ stdout: shell.stdout,
955
+ stderr: shell.stderr,
956
+ interleavedOutput: shell.interleaved
957
+ });
958
+ const cmd = oneLine(shell.command).slice(0, 120);
959
+ if (outcome.kind === "audit_findings") {
960
+ return `[audit:findings] ${outcome.summary}${cmd ? ` \xB7 ${cmd}` : ""}`;
961
+ }
962
+ if (outcome.kind === "command_failure") {
963
+ return `[command:failed] ${outcome.summary}${cmd ? ` \xB7 ${cmd}` : ""}`;
964
+ }
965
+ return `[command:ok] exit 0${cmd ? ` \xB7 ${cmd}` : ""}`;
966
+ }
739
967
  function summarizeEvent(event) {
740
968
  if (event.type === "system" && event.subtype) {
741
969
  return `[system:${event.subtype}] ${String(event.status || event.cwd || "")}`.trim();
@@ -768,6 +996,8 @@ function summarizeEvent(event) {
768
996
  }
769
997
  if (event.type === "tool_call") {
770
998
  const subtype = String(event.subtype || "");
999
+ const shellSummary = subtype === "completed" ? summarizeShellToolCallEvent(event) : void 0;
1000
+ if (shellSummary) return shellSummary;
771
1001
  const toolCall = event.tool_call && typeof event.tool_call === "object" && !Array.isArray(event.tool_call) ? event.tool_call : void 0;
772
1002
  const name = cursorToolNameFromCall(toolCall) ?? "tool";
773
1003
  return `[tool:${subtype}] ${name}`;
@@ -809,7 +1039,7 @@ var FAILURE_PATTERNS = [
809
1039
  label: "provider authentication failed"
810
1040
  }
811
1041
  ];
812
- function tidy(errorText, max = 240) {
1042
+ function tidy2(errorText, max = 240) {
813
1043
  const oneLine2 = errorText.replace(/\s+/g, " ").trim();
814
1044
  return oneLine2.length > max ? `${oneLine2.slice(0, max - 1)}\u2026` : oneLine2;
815
1045
  }
@@ -818,7 +1048,7 @@ function classifyExitFailure(errorText) {
818
1048
  if (!text) return null;
819
1049
  for (const pattern of FAILURE_PATTERNS) {
820
1050
  if (pattern.test.test(text)) {
821
- return { blocked: true, reason: `${pattern.label}: ${tidy(text)}` };
1051
+ return { blocked: true, reason: `${pattern.label}: ${tidy2(text)}` };
822
1052
  }
823
1053
  }
824
1054
  return null;
@@ -884,6 +1114,63 @@ function assessExitedWorkerSalvage(input) {
884
1114
 
885
1115
  // src/git.ts
886
1116
  import { spawnSync } from "node:child_process";
1117
+
1118
+ // src/worker-env.ts
1119
+ var FORBIDDEN_WORKER_ENV_KEYS = [
1120
+ "ANTHROPIC_API_KEY",
1121
+ "ANALYST_API_KEY",
1122
+ "RECRUITER_API_KEY",
1123
+ "AUTH_SECRET",
1124
+ "NEXTAUTH_SECRET",
1125
+ "DATABASE_URL",
1126
+ "PRODUCTION_DATABASE_URL",
1127
+ "REDIS_URL",
1128
+ "GOOGLE_CLIENT_SECRET",
1129
+ "GITHUB_CLIENT_SECRET",
1130
+ "KYNVER_API_KEY",
1131
+ "KYNVER_SERVICE_SECRET",
1132
+ "KYNVER_RUNTIME_SECRET",
1133
+ "OPENCLAW_CRON_SECRET",
1134
+ "QSTASH_TOKEN",
1135
+ "QSTASH_CURRENT_SIGNING_KEY",
1136
+ "QSTASH_NEXT_SIGNING_KEY",
1137
+ "TOOL_SECRETS_KEK",
1138
+ "TOOL_EXECUTOR_DISPATCH_SECRET",
1139
+ "CLOUDFLARE_API_TOKEN",
1140
+ "STRIPE_SECRET_KEY",
1141
+ "STRIPE_WEBHOOK_SECRET",
1142
+ "STRIPE_IDENTITY_WEBHOOK_SECRET",
1143
+ "VOYAGE_API_KEY",
1144
+ "PERPLEXITY_API_KEY",
1145
+ "FRED_API_KEY",
1146
+ "FMP_API_KEY",
1147
+ "CURSOR_API_KEY"
1148
+ ];
1149
+ var FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
1150
+ var FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
1151
+ function isForbiddenWorkerEnvKey(key) {
1152
+ if (FORBIDDEN_KEY_SET.has(key)) return true;
1153
+ return FORBIDDEN_SUFFIXES.some((suffix) => key.endsWith(suffix));
1154
+ }
1155
+ function listForbiddenWorkerEnvKeys(env) {
1156
+ return Object.keys(env).filter(isForbiddenWorkerEnvKey).sort();
1157
+ }
1158
+ function scrubWorkerEnv(env) {
1159
+ const next = { ...env };
1160
+ for (const key of Object.keys(next)) {
1161
+ if (isForbiddenWorkerEnvKey(key)) delete next[key];
1162
+ }
1163
+ return next;
1164
+ }
1165
+ function auditWorkerEnv(env) {
1166
+ const forbiddenPresent = listForbiddenWorkerEnvKeys(env);
1167
+ return { forbiddenPresent, safe: forbiddenPresent.length === 0 };
1168
+ }
1169
+ function scrubClaudeEnv(env) {
1170
+ return scrubWorkerEnv(env);
1171
+ }
1172
+
1173
+ // src/git.ts
887
1174
  function git(cwd, args, options = {}) {
888
1175
  const res = spawnSync("git", args, { cwd, encoding: "utf8" });
889
1176
  if (res.status !== 0 && !options.allowFailure) {
@@ -999,11 +1286,6 @@ function unknownAncestry(base, error, head = null) {
999
1286
  error
1000
1287
  };
1001
1288
  }
1002
- function scrubClaudeEnv(env) {
1003
- const next = { ...env };
1004
- delete next.ANTHROPIC_API_KEY;
1005
- return next;
1006
- }
1007
1289
 
1008
1290
  // src/landing-gate.ts
1009
1291
  function trimOrNull2(value) {
@@ -1353,15 +1635,7 @@ function computeAutoMaxWorkers(totalMemBytes, opts = {}) {
1353
1635
  return Math.min(raw, AUTO_MAX_WORKERS_CEILING);
1354
1636
  }
1355
1637
  function readAvailableMemBytes() {
1356
- if (process.platform === "linux") {
1357
- try {
1358
- const meminfo = readFileSync6("/proc/meminfo", "utf8");
1359
- const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
1360
- if (match) return Number(match[1]) * 1024;
1361
- } catch {
1362
- }
1363
- }
1364
- return os.freemem();
1638
+ return readMemAvailableBytes();
1365
1639
  }
1366
1640
  function isActiveHarnessWorker(worker) {
1367
1641
  const status = computeWorkerStatus(worker);
@@ -1389,7 +1663,7 @@ function observeRunnerResourceGate(input) {
1389
1663
  input.config,
1390
1664
  input.configuredMaxWorkersOverride
1391
1665
  );
1392
- const totalMemBytes = input.totalMemBytes ?? os.totalmem();
1666
+ const totalMemBytes = input.totalMemBytes ?? os2.totalmem();
1393
1667
  const freeMemBytes = input.freeMemBytes ?? readAvailableMemBytes();
1394
1668
  const activeWorkers = input.activeWorkers ?? countActiveWorkersGlobal();
1395
1669
  const budgetBytes = Math.max(0, Math.floor(totalMemBytes * memUtilization) - memReserveBytes);
@@ -1598,7 +1872,7 @@ var claudeProvider = {
1598
1872
  cwd: opts.worktreePath,
1599
1873
  detached: true,
1600
1874
  stdio,
1601
- env: scrubClaudeEnv(process.env)
1875
+ env: scrubWorkerEnv(process.env)
1602
1876
  })
1603
1877
  );
1604
1878
  closeSync(stdoutFd);
@@ -1985,12 +2259,12 @@ function resolveAgentBin() {
1985
2259
  return "agent";
1986
2260
  }
1987
2261
  function cursorWorkerEnv(agentBin, spawnTarget) {
1988
- return {
2262
+ return scrubWorkerEnv({
1989
2263
  ...process.env,
1990
2264
  CI: "1",
1991
2265
  NO_COLOR: "1",
1992
2266
  ...spawnTarget.bundledVersionDir ? { CURSOR_INVOKED_AS: path9.basename(agentBin) || "agent.cmd" } : {}
1993
- };
2267
+ });
1994
2268
  }
1995
2269
  var cursorProvider = {
1996
2270
  name: "cursor",
@@ -2083,6 +2357,39 @@ function persistCompletionAck(worker, runId, fields) {
2083
2357
  // src/worker-ops.ts
2084
2358
  import path11 from "node:path";
2085
2359
 
2360
+ // src/completion-response.ts
2361
+ function asRecord(value) {
2362
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2363
+ }
2364
+ function asString(value) {
2365
+ if (typeof value !== "string") return null;
2366
+ const trimmed = value.trim();
2367
+ return trimmed.length ? trimmed : null;
2368
+ }
2369
+ var ADVANCED_OUTCOMES = /* @__PURE__ */ new Set([
2370
+ "review_scheduled",
2371
+ "review_already_scheduled"
2372
+ ]);
2373
+ function summarizeHarnessCompletionResponse(parsed) {
2374
+ const record = asRecord(parsed);
2375
+ if (!record) {
2376
+ return { routeOutcome: null, taskAdvanced: false, detail: null };
2377
+ }
2378
+ const outcome = asString(record.outcome);
2379
+ const detail = asString(record.detail) ?? asString(record.error);
2380
+ const task = asRecord(record.task);
2381
+ const taskStatus = task ? asString(task.status) : null;
2382
+ const taskAdvanced = outcome !== null && ADVANCED_OUTCOMES.has(outcome) || taskStatus === "awaiting_review" || taskStatus === "done";
2383
+ return {
2384
+ routeOutcome: outcome,
2385
+ taskAdvanced,
2386
+ detail
2387
+ };
2388
+ }
2389
+ function completionPostSucceeded(summary) {
2390
+ return summary.taskAdvanced;
2391
+ }
2392
+
2086
2393
  // src/pr-handoff/pr-handoff-assess.ts
2087
2394
  var REVIEW_LANE_RULE = /^(lane:)?(review|deep_review|planning|landing)(:|$)/i;
2088
2395
  function trimOrNull4(value) {
@@ -2143,6 +2450,36 @@ function buildPrHandoffSnapshotFromStatus(status, extras) {
2143
2450
 
2144
2451
  // src/pr-handoff/pr-handoff-gh.ts
2145
2452
  import { spawnSync as spawnSync2 } from "node:child_process";
2453
+
2454
+ // src/github-repo.ts
2455
+ function parseGithubOwnerRepo(remoteUrl) {
2456
+ const trimmed = remoteUrl.trim();
2457
+ if (!trimmed) return null;
2458
+ const ssh = trimmed.match(/^git@github\.com:([^/]+\/[^/\s]+?)(?:\.git)?$/i);
2459
+ if (ssh) return normalizeOwnerRepo(ssh[1]);
2460
+ const scp = trimmed.match(/^ssh:\/\/git@github\.com\/([^/]+\/[^/\s]+?)(?:\.git)?$/i);
2461
+ if (scp) return normalizeOwnerRepo(scp[1]);
2462
+ try {
2463
+ const url = new URL(trimmed.includes("://") ? trimmed : `https://${trimmed}`);
2464
+ if (url.hostname.toLowerCase() !== "github.com") return null;
2465
+ const parts = url.pathname.replace(/^\/+|\/+$/g, "").split("/");
2466
+ if (parts.length < 2) return null;
2467
+ const [owner, repo] = parts;
2468
+ if (!owner || !repo) return null;
2469
+ return `${owner}/${repo.replace(/\.git$/i, "")}`;
2470
+ } catch {
2471
+ return null;
2472
+ }
2473
+ }
2474
+ function normalizeOwnerRepo(value) {
2475
+ const parts = value.split("/").filter(Boolean);
2476
+ if (parts.length < 2) return null;
2477
+ const owner = parts[0];
2478
+ const repo = parts[1].replace(/\.git$/i, "");
2479
+ return owner && repo ? `${owner}/${repo}` : null;
2480
+ }
2481
+
2482
+ // src/pr-handoff/pr-handoff-gh.ts
2146
2483
  function capture(bin, cwd, args) {
2147
2484
  try {
2148
2485
  const res = spawnSync2(bin, args, { cwd, encoding: "utf8" });
@@ -2165,21 +2502,13 @@ var defaultPrHandoffExec = {
2165
2502
  git: (cwd, args) => gitCapture(cwd, args),
2166
2503
  gh: (cwd, args) => capture("gh", cwd, args)
2167
2504
  };
2168
- function parseGithubRepo(remoteUrl) {
2169
- const trimmed = remoteUrl.trim();
2170
- const ssh = trimmed.match(/git@github\.com:([^/]+\/[^/.]+)(?:\.git)?/i);
2171
- if (ssh) return ssh[1];
2172
- const https = trimmed.match(/github\.com[/:]([^/]+\/[^/.]+?)(?:\.git)?/i);
2173
- if (https) return https[1];
2174
- return null;
2175
- }
2176
2505
  function firstLine(text) {
2177
2506
  return text.split("\n").map((l) => l.trim()).find(Boolean) ?? "";
2178
2507
  }
2179
2508
  function resolveGithubRepo(worktreePath, exec) {
2180
2509
  const remote = exec.git(worktreePath, ["remote", "get-url", "origin"]);
2181
2510
  if (remote.status !== 0) return null;
2182
- return parseGithubRepo(remote.stdout);
2511
+ return parseGithubOwnerRepo(remote.stdout);
2183
2512
  }
2184
2513
  function resolveHeadCommit(worktreePath, exec) {
2185
2514
  const head = exec.git(worktreePath, ["rev-parse", "HEAD"]);
@@ -2513,10 +2842,10 @@ function completionErrorText(parsed) {
2513
2842
  }
2514
2843
  return void 0;
2515
2844
  }
2516
- function asRecord(value) {
2845
+ function asRecord2(value) {
2517
2846
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2518
2847
  }
2519
- function asString(value) {
2848
+ function asString2(value) {
2520
2849
  if (typeof value !== "string") return null;
2521
2850
  const trimmed = value.trim();
2522
2851
  return trimmed.length ? trimmed : null;
@@ -2636,7 +2965,27 @@ async function tryCompleteWorker(args) {
2636
2965
  }
2637
2966
  }
2638
2967
  if (result.ok) {
2968
+ const summary = summarizeHarnessCompletionResponse(result.parsed);
2969
+ if (!completionPostSucceeded(summary)) {
2970
+ const detail2 = summary.detail ?? (summary.routeOutcome ? `harness completion returned ${summary.routeOutcome}` : "harness completion did not advance the linked task");
2971
+ const reason2 = `completion acknowledged but board not advanced: ${detail2}`;
2972
+ persistCompletionBlocker(worker, reason2);
2973
+ const ack2 = {
2974
+ completionReportedAt: (/* @__PURE__ */ new Date()).toISOString(),
2975
+ completionOutcome: "rejected",
2976
+ completionResponse: result.parsed
2977
+ };
2978
+ persistCompletionAck(worker, worker.runId, ack2);
2979
+ return {
2980
+ ok: false,
2981
+ httpStatus: result.status,
2982
+ response: result.parsed,
2983
+ reason: reason2,
2984
+ completionBlocked: true
2985
+ };
2986
+ }
2639
2987
  persistCompletionBlocker(worker, void 0);
2988
+ const routeOutcome = summary.routeOutcome ?? "acknowledged";
2640
2989
  const ack = {
2641
2990
  completionReportedAt: (/* @__PURE__ */ new Date()).toISOString(),
2642
2991
  completionOutcome: "acknowledged",
@@ -2649,6 +2998,7 @@ async function tryCompleteWorker(args) {
2649
2998
  ok: true,
2650
2999
  httpStatus: result.status,
2651
3000
  response: result.parsed,
3001
+ reason: routeOutcome,
2652
3002
  ...prUrl ? { prHandoff: { prUrl } } : {}
2653
3003
  };
2654
3004
  }
@@ -2741,13 +3091,13 @@ function buildRunBoard(runId) {
2741
3091
  const completionBlocker = typeof rawBlocker === "string" && rawBlocker ? rawBlocker : void 0;
2742
3092
  const boardStatus = completionBlocker ? "blocked" : status.status;
2743
3093
  const boardAttention = completionBlocker ? "blocked" : status.attention.state;
2744
- const completionResponse = asRecord(worker.completionResponse);
2745
- const completionTask = asRecord(completionResponse?.task);
2746
- const completionOutcome = asString(completionResponse?.outcome);
2747
- const completionRouteStatus = asString(completionResponse?.status);
3094
+ const completionResponse = asRecord2(worker.completionResponse);
3095
+ const completionTask = asRecord2(completionResponse?.task);
3096
+ const completionOutcome = asString2(completionResponse?.outcome);
3097
+ const completionRouteStatus = asString2(completionResponse?.status);
2748
3098
  const completionWarnings = Array.isArray(completionResponse?.warnings) ? completionResponse.warnings.filter((w) => typeof w === "string" && w.trim().length > 0) : [];
2749
- const prUrl = asString(completionTask?.prUrl) ?? asString(completionResponse?.prUrl);
2750
- const completionReportedAt = asString(worker.completionReportedAt);
3099
+ const prUrl = asString2(completionTask?.prUrl) ?? asString2(completionResponse?.prUrl);
3100
+ const completionReportedAt = asString2(worker.completionReportedAt);
2751
3101
  const lifecycleStage = deriveLifecycleStage({
2752
3102
  finished: isFinishedWorkerStatus(status),
2753
3103
  completionBlocker,
@@ -3938,7 +4288,8 @@ async function dispatchRun(args) {
3938
4288
  harnessBoardSnapshot: buildRunBoard(run.id),
3939
4289
  ...args.lane ? { lane: String(args.lane) } : {},
3940
4290
  executor: args.executor ? String(args.executor) : "harness",
3941
- ...args.diskPath ? { diskPath: String(args.diskPath) } : {}
4291
+ ...args.diskPath ? { diskPath: String(args.diskPath) } : {},
4292
+ ...args.targetTaskId ? { targetTaskId: String(args.targetTaskId) } : {}
3942
4293
  };
3943
4294
  const dispatch = await postJsonWithCredentialRefresh(dispatchUrl, secret, body, { agentOsId, baseUrl: base });
3944
4295
  const responseBody = dispatch.response;
@@ -4117,6 +4468,13 @@ async function dispatchRun(args) {
4117
4468
  }
4118
4469
  }
4119
4470
 
4471
+ // src/fortress-engagement-gate.ts
4472
+ function isEngagementRequiredSkip(skip) {
4473
+ if (skip.skipReason === "engagement_required") return true;
4474
+ const reason = skip.reason ?? "";
4475
+ return reason.includes("engagement_required") || reason.includes("engagement_not_found") || reason.includes("engagement_expired") || reason.includes("engagement_revoked");
4476
+ }
4477
+
4120
4478
  // src/redact.ts
4121
4479
  function redactHarness(text, secret) {
4122
4480
  let out = text;
@@ -4262,7 +4620,7 @@ import { mkdirSync as mkdirSync7, realpathSync } from "node:fs";
4262
4620
  import { fileURLToPath as fileURLToPath4 } from "node:url";
4263
4621
 
4264
4622
  // src/pipeline-tick.ts
4265
- import path29 from "node:path";
4623
+ import path30 from "node:path";
4266
4624
 
4267
4625
  // src/pipeline-dispatch.ts
4268
4626
  var RESERVED_REVIEW_STARTS = 1;
@@ -4968,13 +5326,62 @@ function isPipelineCleanupEnabled() {
4968
5326
  return process.env.KYNVER_PIPELINE_CLEANUP !== "0";
4969
5327
  }
4970
5328
 
5329
+ // src/installed-package-versions.ts
5330
+ import { readFile } from "node:fs/promises";
5331
+ import { homedir as homedir5 } from "node:os";
5332
+ import path29 from "node:path";
5333
+ var MANAGED_PACKAGES = [
5334
+ "@kynver-app/runtime",
5335
+ "@kynver-app/openclaw-agent-os",
5336
+ "@kynver-app/mcp-agent-os"
5337
+ ];
5338
+ function trim(value) {
5339
+ const out = value?.trim();
5340
+ return out ? out : null;
5341
+ }
5342
+ function unique(values) {
5343
+ return [...new Set(values.filter((value) => Boolean(value)))];
5344
+ }
5345
+ function moduleRoots() {
5346
+ const home = homedir5();
5347
+ const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path29.join(home, ".openclaw", "npm");
5348
+ const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path29.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path29.join(home, ".npm-global", "lib", "node_modules"));
5349
+ return unique([
5350
+ path29.join(openClawPrefix, "lib", "node_modules"),
5351
+ path29.join(openClawPrefix, "node_modules"),
5352
+ npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path29.join(npmGlobalRoot, "lib", "node_modules")
5353
+ ]);
5354
+ }
5355
+ async function readVersion(packageJsonPath) {
5356
+ try {
5357
+ const parsed = JSON.parse(await readFile(packageJsonPath, "utf8"));
5358
+ return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
5359
+ } catch {
5360
+ return null;
5361
+ }
5362
+ }
5363
+ async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
5364
+ const roots = moduleRoots();
5365
+ const out = {};
5366
+ for (const packageName of MANAGED_PACKAGES) {
5367
+ for (const root of roots) {
5368
+ const packageJsonPath = path29.join(root, packageName, "package.json");
5369
+ const version = await readVersion(packageJsonPath);
5370
+ if (!version) continue;
5371
+ out[packageName] = { version, observedAt, path: packageJsonPath };
5372
+ break;
5373
+ }
5374
+ }
5375
+ return out;
5376
+ }
5377
+
4971
5378
  // src/pipeline-tick.ts
4972
5379
  async function completeFinishedWorkers(runId, args) {
4973
5380
  const run = loadRun(runId);
4974
5381
  const outcomes = [];
4975
5382
  for (const name of Object.keys(run.workers || {})) {
4976
5383
  const worker = readJson(
4977
- path29.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
5384
+ path30.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
4978
5385
  void 0
4979
5386
  );
4980
5387
  if (!worker?.taskId || worker.localOnly) continue;
@@ -5005,12 +5412,14 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args) {
5005
5412
  const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : void 0);
5006
5413
  const secret = await resolveCallbackSecretWithMint(args.secret ? String(args.secret) : void 0, agentOsId, { baseUrl: base });
5007
5414
  const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/operator/tick`;
5415
+ const packageVersions = await collectInstalledPackageVersions();
5008
5416
  const res = await postJson(url, secret, {
5009
5417
  agentOsId,
5010
5418
  runId,
5011
5419
  ingestHarness: true,
5012
5420
  harnessBoardSnapshot: buildRunBoard(runId),
5013
- resourceGate
5421
+ resourceGate,
5422
+ packageVersions
5014
5423
  });
5015
5424
  return { ok: res.ok, httpStatus: res.status, response: res.response };
5016
5425
  }
@@ -5113,6 +5522,231 @@ async function runDaemon(args) {
5113
5522
  console.error(JSON.stringify({ event: "daemon_stop", runId, agentOsId }));
5114
5523
  }
5115
5524
 
5525
+ // src/plan-progress.ts
5526
+ import path31 from "node:path";
5527
+
5528
+ // src/bounded-build/constants.ts
5529
+ var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
5530
+ var DEFAULT_BUILD_MEM_RESERVE_BYTES = 2 * 1024 * 1024 * 1024;
5531
+ var DEFAULT_NODE_OLD_SPACE_SIZE_MB = 1024;
5532
+ var DEFAULT_SYSTEMD_MEMORY_MAX = "1.5G";
5533
+ var DEFAULT_SYSTEMD_MEMORY_SWAP_MAX = "2G";
5534
+
5535
+ // src/bounded-build/node-options.ts
5536
+ var MAX_OLD_SPACE_RE = /--max-old-space-size=(\d+)/;
5537
+ function parsePositiveInt(value, fallback) {
5538
+ const n = Number(value);
5539
+ if (!Number.isFinite(n) || n <= 0) return fallback;
5540
+ return Math.floor(n);
5541
+ }
5542
+ function resolveNodeOldSpaceSizeMb() {
5543
+ return parsePositiveInt(process.env.KYNVER_NODE_OLD_SPACE_SIZE_MB, DEFAULT_NODE_OLD_SPACE_SIZE_MB);
5544
+ }
5545
+ function mergeNodeOptionsForBuildCheck(baseEnv = process.env) {
5546
+ const env = { ...baseEnv };
5547
+ if (process.env.KYNVER_NODE_OLD_SPACE_SIZE_MB === "0") {
5548
+ return env;
5549
+ }
5550
+ const existing = env.NODE_OPTIONS ?? "";
5551
+ if (MAX_OLD_SPACE_RE.test(existing)) {
5552
+ return env;
5553
+ }
5554
+ const mb = resolveNodeOldSpaceSizeMb();
5555
+ const flag = `--max-old-space-size=${mb}`;
5556
+ env.NODE_OPTIONS = existing.trim() ? `${existing.trim()} ${flag}` : flag;
5557
+ return env;
5558
+ }
5559
+ function formatNodeOptionsFlag(mb = resolveNodeOldSpaceSizeMb()) {
5560
+ return `--max-old-space-size=${mb}`;
5561
+ }
5562
+
5563
+ // src/bounded-build/systemd-wrap.ts
5564
+ import { spawnSync as spawnSync3 } from "node:child_process";
5565
+ var systemdAvailableCache;
5566
+ function isSystemdRunAvailable() {
5567
+ if (process.env.KYNVER_BUILD_SKIP_SYSTEMD === "1" || process.env.KYNVER_BUILD_SKIP_SYSTEMD === "true") {
5568
+ return false;
5569
+ }
5570
+ if (systemdAvailableCache !== void 0) return systemdAvailableCache;
5571
+ if (process.platform !== "linux") {
5572
+ systemdAvailableCache = false;
5573
+ return false;
5574
+ }
5575
+ const res = spawnSync3("systemd-run", ["--version"], { encoding: "utf8", stdio: ["ignore", "ignore", "pipe"] });
5576
+ systemdAvailableCache = res.status === 0;
5577
+ return systemdAvailableCache;
5578
+ }
5579
+ function buildSystemdRunArgv(opts) {
5580
+ const memoryMax = opts.memoryMax ?? process.env.KYNVER_BUILD_SYSTEMD_MEMORY_MAX ?? DEFAULT_SYSTEMD_MEMORY_MAX;
5581
+ const memorySwapMax = opts.memorySwapMax ?? process.env.KYNVER_BUILD_SYSTEMD_MEMORY_SWAP_MAX ?? DEFAULT_SYSTEMD_MEMORY_SWAP_MAX;
5582
+ const argv = [
5583
+ "systemd-run",
5584
+ "--scope",
5585
+ "--collect",
5586
+ "-p",
5587
+ `MemoryMax=${memoryMax}`,
5588
+ "-p",
5589
+ `MemorySwapMax=${memorySwapMax}`
5590
+ ];
5591
+ if (opts.cwd) {
5592
+ argv.push("--working-directory", opts.cwd);
5593
+ }
5594
+ argv.push("--", ...opts.command);
5595
+ return argv;
5596
+ }
5597
+
5598
+ // src/bounded-build/admission.ts
5599
+ import { spawnSync as spawnSync4 } from "node:child_process";
5600
+ function positiveInt3(value, fallback) {
5601
+ const n = Number(value);
5602
+ if (!Number.isFinite(n) || n <= 0) return fallback;
5603
+ return Math.floor(n);
5604
+ }
5605
+ function resolveBuildAdmissionConfig(config = loadUserConfig()) {
5606
+ const envBudget = process.env.KYNVER_BUILD_MEM_BUDGET_BYTES ? positiveInt3(process.env.KYNVER_BUILD_MEM_BUDGET_BYTES, DEFAULT_BUILD_MEM_BUDGET_BYTES) : void 0;
5607
+ const envReserve = process.env.KYNVER_BUILD_MEM_RESERVE_BYTES ? positiveInt3(process.env.KYNVER_BUILD_MEM_RESERVE_BYTES, DEFAULT_BUILD_MEM_RESERVE_BYTES) : void 0;
5608
+ return {
5609
+ perBuildBudgetBytes: envBudget ?? positiveInt3(config.perWorkerMemBytes, DEFAULT_BUILD_MEM_BUDGET_BYTES),
5610
+ reserveBytes: envReserve ?? positiveInt3(config.memReserveBytes, DEFAULT_BUILD_MEM_RESERVE_BYTES)
5611
+ };
5612
+ }
5613
+ var activeBuilds = 0;
5614
+ function registerBuildStart() {
5615
+ activeBuilds += 1;
5616
+ }
5617
+ function registerBuildEnd() {
5618
+ activeBuilds = Math.max(0, activeBuilds - 1);
5619
+ }
5620
+ function assessBuildAdmission(opts = {}) {
5621
+ const cfg = { ...resolveBuildAdmissionConfig(), ...opts };
5622
+ const memAvailableBytes = opts.memAvailableBytes ?? readMemAvailableBytes();
5623
+ const requiredBytes = cfg.perBuildBudgetBytes + cfg.reserveBytes;
5624
+ const admitted = memAvailableBytes >= requiredBytes;
5625
+ return {
5626
+ admitted,
5627
+ memAvailableBytes,
5628
+ requiredBytes,
5629
+ activeBuilds,
5630
+ reason: admitted ? null : `insufficient memory: need ${requiredBytes} bytes available (budget ${cfg.perBuildBudgetBytes} + reserve ${cfg.reserveBytes}), have ${memAvailableBytes}`
5631
+ };
5632
+ }
5633
+ function sleepMs2(ms) {
5634
+ if (ms <= 0) return;
5635
+ spawnSync4(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
5636
+ stdio: "ignore"
5637
+ });
5638
+ }
5639
+ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
5640
+ const deadline = Date.now() + Math.max(0, timeoutMs);
5641
+ let verdict = assessBuildAdmission({
5642
+ ...opts,
5643
+ memAvailableBytes: opts.memAvailableBytes?.()
5644
+ });
5645
+ while (!verdict.admitted && Date.now() < deadline) {
5646
+ sleepMs2(Math.min(pollMs, deadline - Date.now()));
5647
+ verdict = assessBuildAdmission({
5648
+ ...opts,
5649
+ memAvailableBytes: opts.memAvailableBytes?.()
5650
+ });
5651
+ }
5652
+ return verdict;
5653
+ }
5654
+
5655
+ // src/bounded-build/exec.ts
5656
+ import { spawnSync as spawnSync5 } from "node:child_process";
5657
+ function envArgv(env) {
5658
+ const out = [];
5659
+ for (const [key, value] of Object.entries(env)) {
5660
+ if (value === void 0) continue;
5661
+ out.push(`${key}=${value}`);
5662
+ }
5663
+ return out;
5664
+ }
5665
+ function runSpawn(argv, opts) {
5666
+ const res = spawnSync5(argv[0], argv.slice(1), {
5667
+ cwd: opts.cwd,
5668
+ env: opts.env,
5669
+ encoding: "utf8",
5670
+ stdio: ["ignore", "pipe", "pipe"],
5671
+ shell: opts.shell,
5672
+ timeout: opts.timeoutMs
5673
+ });
5674
+ return {
5675
+ exitCode: res.status ?? 1,
5676
+ stdout: (res.stdout ?? "").trim(),
5677
+ stderr: (res.stderr ?? "").trim()
5678
+ };
5679
+ }
5680
+ function runBoundedBuildCheck(input) {
5681
+ const waitMs = input.waitForAdmissionMs ?? 6e5;
5682
+ const admission = waitMs > 0 ? waitForBuildAdmission(waitMs) : assessBuildAdmission();
5683
+ if (!admission.admitted) {
5684
+ return {
5685
+ ok: false,
5686
+ exitCode: 1,
5687
+ stdout: "",
5688
+ stderr: admission.reason ?? "build admission denied",
5689
+ admitted: false,
5690
+ wrappedWithSystemd: false,
5691
+ nodeOptionsFlag: formatNodeOptionsFlag(),
5692
+ admission,
5693
+ command: input.command
5694
+ };
5695
+ }
5696
+ const env = mergeNodeOptionsForBuildCheck({ ...process.env, ...input.env });
5697
+ const nodeOptionsFlag = formatNodeOptionsFlag();
5698
+ const useSystemd = isSystemdRunAvailable();
5699
+ registerBuildStart();
5700
+ try {
5701
+ let result;
5702
+ if (useSystemd) {
5703
+ const argv = buildSystemdRunArgv({
5704
+ cwd: input.cwd,
5705
+ command: ["/usr/bin/env", ...envArgv(env), "/bin/bash", "-lc", input.command]
5706
+ });
5707
+ result = runSpawn(argv, { cwd: input.cwd, env, timeoutMs: input.timeoutMs });
5708
+ } else {
5709
+ result = runSpawn([input.command], {
5710
+ cwd: input.cwd,
5711
+ env,
5712
+ shell: true,
5713
+ timeoutMs: input.timeoutMs
5714
+ });
5715
+ }
5716
+ return {
5717
+ ok: result.exitCode === 0,
5718
+ exitCode: result.exitCode,
5719
+ stdout: result.stdout,
5720
+ stderr: result.stderr,
5721
+ admitted: true,
5722
+ wrappedWithSystemd: useSystemd,
5723
+ nodeOptionsFlag,
5724
+ admission,
5725
+ command: input.command
5726
+ };
5727
+ } finally {
5728
+ registerBuildEnd();
5729
+ }
5730
+ }
5731
+
5732
+ // src/harness-verify.ts
5733
+ var DEFAULT_HARNESS_VERIFY_COMMANDS = ["npm run typecheck", "npm run test"];
5734
+ function runHarnessVerifyCommands(cwd, commands = DEFAULT_HARNESS_VERIFY_COMMANDS, opts = {}) {
5735
+ const steps = [];
5736
+ let passed = true;
5737
+ for (const command of commands) {
5738
+ const result = runBoundedBuildCheck({
5739
+ cwd,
5740
+ command,
5741
+ waitForAdmissionMs: opts.waitForAdmissionMs,
5742
+ timeoutMs: opts.timeoutMs
5743
+ });
5744
+ steps.push({ command, result });
5745
+ if (!result.ok) passed = false;
5746
+ }
5747
+ return { passed, steps };
5748
+ }
5749
+
5116
5750
  // src/plan-progress.ts
5117
5751
  function parseEvidenceArg(raw) {
5118
5752
  const idx = raw.indexOf(":");
@@ -5173,8 +5807,23 @@ async function emitPlanProgress(args) {
5173
5807
  }
5174
5808
  console.log(JSON.stringify(parsed, null, 2));
5175
5809
  }
5810
+ function verifyPlanLocal(args) {
5811
+ const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
5812
+ const cwd = path31.resolve(worktree);
5813
+ const summary = runHarnessVerifyCommands(cwd);
5814
+ const emitJson = args.json === true || args.json === "true";
5815
+ const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
5816
+ if (emitJson) console.log(JSON.stringify(payload, null, 2));
5817
+ else console.log(summary.passed ? "local plan verify passed" : "local plan verify failed");
5818
+ if (!summary.passed) process.exit(1);
5819
+ }
5176
5820
  async function verifyPlan(args) {
5177
5821
  const planId = required(args.plan ? String(args.plan) : void 0, "plan");
5822
+ const localOnly = args.local === true || args.local === "true";
5823
+ if (localOnly) {
5824
+ verifyPlanLocal(args);
5825
+ return;
5826
+ }
5178
5827
  const slug = loadUserConfig().agentOsSlug;
5179
5828
  if (!slug) {
5180
5829
  console.error("requires agentOsSlug in ~/.kynver/config.json for verify (session route)");
@@ -5208,6 +5857,52 @@ async function verifyPlan(args) {
5208
5857
  console.log(JSON.stringify(parsed, null, 2));
5209
5858
  }
5210
5859
 
5860
+ // src/harness-verify-cli.ts
5861
+ import path32 from "node:path";
5862
+ function runHarnessVerifyCli(args) {
5863
+ const cwd = path32.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
5864
+ const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
5865
+ const commands = [];
5866
+ const rawCmd = args.command;
5867
+ if (Array.isArray(rawCmd)) {
5868
+ for (const c of rawCmd) commands.push(String(c));
5869
+ } else if (typeof rawCmd === "string") {
5870
+ commands.push(rawCmd);
5871
+ }
5872
+ const summary = runHarnessVerifyCommands(
5873
+ cwd,
5874
+ commands.length ? commands : DEFAULT_HARNESS_VERIFY_COMMANDS,
5875
+ {
5876
+ waitForAdmissionMs: args.waitForAdmissionMs ? Number(args.waitForAdmissionMs) : void 0,
5877
+ timeoutMs: args.timeoutMs ? Number(args.timeoutMs) : void 0
5878
+ }
5879
+ );
5880
+ const payload = {
5881
+ passed: summary.passed,
5882
+ worktree: cwd,
5883
+ steps: summary.steps.map((s) => ({
5884
+ command: s.command,
5885
+ ok: s.result.ok,
5886
+ exitCode: s.result.exitCode,
5887
+ admitted: s.result.admitted,
5888
+ wrappedWithSystemd: s.result.wrappedWithSystemd,
5889
+ nodeOptionsFlag: s.result.nodeOptionsFlag,
5890
+ admission: s.result.admission,
5891
+ stderr: s.result.stderr.slice(0, 4e3)
5892
+ }))
5893
+ };
5894
+ if (emitJson) {
5895
+ console.log(JSON.stringify(payload, null, 2));
5896
+ } else {
5897
+ console.log(summary.passed ? "harness verify passed" : "harness verify failed");
5898
+ for (const step of payload.steps) {
5899
+ console.log(` ${step.ok ? "\u2713" : "\u2717"} ${step.command} (exit ${step.exitCode}, systemd=${step.wrappedWithSystemd})`);
5900
+ if (!step.ok && step.stderr) console.log(` ${step.stderr.split("\n")[0]}`);
5901
+ }
5902
+ }
5903
+ process.exit(summary.passed ? 0 : 1);
5904
+ }
5905
+
5211
5906
  // src/plan-persist-cli.ts
5212
5907
  import { readFileSync as readFileSync8 } from "node:fs";
5213
5908
  var OPERATIONS = ["create", "add_version", "update_metadata"];
@@ -5309,7 +6004,7 @@ function runCleanupCli(args) {
5309
6004
  }
5310
6005
 
5311
6006
  // src/monitor/monitor.service.ts
5312
- import path31 from "node:path";
6007
+ import path34 from "node:path";
5313
6008
 
5314
6009
  // src/monitor/monitor.classify.ts
5315
6010
  function expectedLeaseOwner(runId) {
@@ -5366,10 +6061,10 @@ function classifyWorkerHealth(input) {
5366
6061
 
5367
6062
  // src/monitor/monitor.store.ts
5368
6063
  import { existsSync as existsSync18, mkdirSync as mkdirSync6, readdirSync as readdirSync7, unlinkSync as unlinkSync2 } from "node:fs";
5369
- import path30 from "node:path";
6064
+ import path33 from "node:path";
5370
6065
  function monitorsDir() {
5371
6066
  const { harnessRoot } = getHarnessPaths();
5372
- const dir = path30.join(harnessRoot, "monitors");
6067
+ const dir = path33.join(harnessRoot, "monitors");
5373
6068
  mkdirSync6(dir, { recursive: true });
5374
6069
  return dir;
5375
6070
  }
@@ -5377,7 +6072,7 @@ function monitorIdFor(runId, workerName) {
5377
6072
  return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
5378
6073
  }
5379
6074
  function monitorPath(monitorId) {
5380
- return path30.join(monitorsDir(), `${monitorId}.json`);
6075
+ return path33.join(monitorsDir(), `${monitorId}.json`);
5381
6076
  }
5382
6077
  function loadMonitorSession(monitorId) {
5383
6078
  return readJson(monitorPath(monitorId), void 0);
@@ -5398,7 +6093,7 @@ function listMonitorSessions() {
5398
6093
  for (const name of readdirSync7(dir)) {
5399
6094
  if (!name.endsWith(".json")) continue;
5400
6095
  const session = readJson(
5401
- path30.join(dir, name),
6096
+ path33.join(dir, name),
5402
6097
  void 0
5403
6098
  );
5404
6099
  if (!session?.monitorId) continue;
@@ -5489,7 +6184,7 @@ async function fetchTaskLeasesForWorkers(input) {
5489
6184
  // src/monitor/monitor.service.ts
5490
6185
  function workerRecord2(runId, name) {
5491
6186
  return readJson(
5492
- path31.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
6187
+ path34.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
5493
6188
  void 0
5494
6189
  );
5495
6190
  }
@@ -5692,17 +6387,17 @@ async function runMonitorLoop(args) {
5692
6387
  // src/monitor/monitor-spawn.ts
5693
6388
  import { spawn as spawn4 } from "node:child_process";
5694
6389
  import { closeSync as closeSync4, existsSync as existsSync19, openSync as openSync4 } from "node:fs";
5695
- import path32 from "node:path";
6390
+ import path35 from "node:path";
5696
6391
  import { fileURLToPath as fileURLToPath3 } from "node:url";
5697
6392
  function resolveDefaultCliPath2() {
5698
- return path32.join(fileURLToPath3(new URL(".", import.meta.url)), "..", "cli.js");
6393
+ return path35.join(fileURLToPath3(new URL(".", import.meta.url)), "..", "cli.js");
5699
6394
  }
5700
6395
  function spawnMonitorSidecar(opts) {
5701
6396
  const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
5702
6397
  if (!existsSync19(cliPath)) return void 0;
5703
6398
  const monitorId = monitorIdFor(opts.runId, opts.workerName);
5704
6399
  const { harnessRoot } = getHarnessPaths();
5705
- const logPath = path32.join(harnessRoot, "monitors", `${monitorId}.log`);
6400
+ const logPath = path35.join(harnessRoot, "monitors", `${monitorId}.log`);
5706
6401
  let logFd;
5707
6402
  try {
5708
6403
  logFd = openSync4(logPath, "a");
@@ -5822,16 +6517,16 @@ async function monitorTickCli(args) {
5822
6517
  }
5823
6518
 
5824
6519
  // src/doctor/runtime-takeover.ts
5825
- import path34 from "node:path";
6520
+ import path37 from "node:path";
5826
6521
 
5827
6522
  // src/doctor/runtime-takeover.probes.ts
5828
6523
  import { accessSync, constants, existsSync as existsSync20, readFileSync as readFileSync9 } from "node:fs";
5829
- import { homedir as homedir5 } from "node:os";
5830
- import path33 from "node:path";
5831
- import { spawnSync as spawnSync3 } from "node:child_process";
6524
+ import { homedir as homedir6 } from "node:os";
6525
+ import path36 from "node:path";
6526
+ import { spawnSync as spawnSync6 } from "node:child_process";
5832
6527
  function captureCommand(bin, args) {
5833
6528
  try {
5834
- const res = spawnSync3(bin, args, { encoding: "utf8" });
6529
+ const res = spawnSync6(bin, args, { encoding: "utf8" });
5835
6530
  const stdout = (res.stdout || "").trim();
5836
6531
  const stderr = (res.stderr || "").trim();
5837
6532
  const ok = res.status === 0;
@@ -5869,10 +6564,10 @@ var defaultRuntimeTakeoverProbes = {
5869
6564
  commandOnPath: (bin) => captureCommand(process.platform === "win32" ? "where" : "which", [bin]),
5870
6565
  kynverVersion: (bin) => captureCommand(bin, ["--version"]),
5871
6566
  loadConfig: () => loadUserConfig(),
5872
- configFilePath: () => path33.join(homedir5(), ".kynver", "config.json"),
5873
- credentialsFilePath: () => path33.join(homedir5(), ".kynver", "credentials"),
6567
+ configFilePath: () => path36.join(homedir6(), ".kynver", "config.json"),
6568
+ credentialsFilePath: () => path36.join(homedir6(), ".kynver", "credentials"),
5874
6569
  readCredentials: () => {
5875
- const credPath = path33.join(homedir5(), ".kynver", "credentials");
6570
+ const credPath = path36.join(homedir6(), ".kynver", "credentials");
5876
6571
  if (!existsSync20(credPath)) {
5877
6572
  return { hasApiKey: false };
5878
6573
  }
@@ -5898,7 +6593,7 @@ var defaultRuntimeTakeoverProbes = {
5898
6593
  kynverSchedulerProvider: process.env.KYNVER_SCHEDULER_PROVIDER?.trim() || void 0
5899
6594
  }),
5900
6595
  harnessRoot: () => resolveHarnessRoot(),
5901
- legacyOpenclawHarnessRoot: () => path33.join(homedir5(), ".openclaw", "harness"),
6596
+ legacyOpenclawHarnessRoot: () => path36.join(homedir6(), ".openclaw", "harness"),
5902
6597
  pathExists: (target) => existsSync20(target),
5903
6598
  pathWritable: (target) => isWritable(target),
5904
6599
  vercelVersion: () => captureCommand("vercel", ["--version"]),
@@ -6084,8 +6779,8 @@ function assessVercelCli(probes) {
6084
6779
  }
6085
6780
  function assessHarnessDirs(probes) {
6086
6781
  const harnessRoot = probes.harnessRoot();
6087
- const runsDir = path34.join(harnessRoot, "runs");
6088
- const worktreesDir = path34.join(harnessRoot, "worktrees");
6782
+ const runsDir = path37.join(harnessRoot, "runs");
6783
+ const worktreesDir = path37.join(harnessRoot, "worktrees");
6089
6784
  const displayHarnessRoot = redactHomePath(harnessRoot);
6090
6785
  const displayRunsDir = redactHomePath(runsDir);
6091
6786
  const displayWorktreesDir = redactHomePath(worktreesDir);
@@ -6237,6 +6932,37 @@ function runRuntimeTakeoverDoctorCli() {
6237
6932
  }
6238
6933
  }
6239
6934
 
6935
+ // src/command-center-contract-cli.ts
6936
+ async function runCommandCenterContractCli(args) {
6937
+ const config = loadUserConfig();
6938
+ const agentOsId = (args.agentOsId ? String(args.agentOsId) : config.agentOsId) || "";
6939
+ if (!agentOsId) {
6940
+ console.error("requires --agent-os-id or agentOsId in ~/.kynver/config.json");
6941
+ process.exit(1);
6942
+ }
6943
+ const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : config.apiBaseUrl);
6944
+ const secret = await resolveCallbackSecretWithMint(
6945
+ args.secret ? String(args.secret) : void 0,
6946
+ agentOsId,
6947
+ { baseUrl: base }
6948
+ );
6949
+ const qs = new URLSearchParams();
6950
+ if (typeof args.since === "string" && args.since.trim()) qs.set("since", args.since.trim());
6951
+ if (args.limit != null && String(args.limit).trim()) {
6952
+ const n = Number(args.limit);
6953
+ if (Number.isFinite(n) && n > 0) qs.set("limit", String(Math.floor(n)));
6954
+ }
6955
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
6956
+ const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/command-center/dashboard-contract${suffix}`;
6957
+ const res = await getJson(url, secret);
6958
+ if (!res.ok) {
6959
+ console.error(`dashboard-contract GET failed: HTTP ${res.status}`);
6960
+ if (res.response) console.error(JSON.stringify(res.response, null, 2));
6961
+ process.exit(1);
6962
+ }
6963
+ console.log(JSON.stringify(res.response, null, 2));
6964
+ }
6965
+
6240
6966
  // src/cli.ts
6241
6967
  function isHelpFlag(arg) {
6242
6968
  return arg === "help" || arg === "--help" || arg === "-h";
@@ -6258,7 +6984,7 @@ function usage(code = 0) {
6258
6984
  " kynver run create --repo /path/repo [--name name] [--base origin/main]",
6259
6985
  " kynver run list",
6260
6986
  " kynver run status --run RUN_ID",
6261
- " kynver run dispatch --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--execute] [--lane any|implementation|review|landing] [--executor harness] [--max-starts 1] [--lease-ms MS] [--owned path[,path]] [--model claude-opus-4-8] [--disk-path /]",
6987
+ " kynver run dispatch --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--execute] [--lane any|implementation|review|landing] [--target-task-id TASK_ID] [--executor harness] [--max-starts 1] [--lease-ms MS] [--owned path[,path]] [--model claude-opus-4-8] [--disk-path /]",
6262
6988
  " kynver run sweep --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--grace-ms MS]",
6263
6989
  ' kynver worker start --run RUN_ID --name worker --task "..." [--owned path[,path]] [--model MODEL] [--provider claude|cursor] [--agent-os-id AOS_ID] [--task-id TASK_ID] [--wait]',
6264
6990
  " kynver worker status --run RUN_ID --name worker",
@@ -6268,7 +6994,8 @@ function usage(code = 0) {
6268
6994
  " kynver worker auto-complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--poll-ms 5000] [--max-total-ms 21600000] [--complete-attempts 3] [--complete-backoff-ms 5000] [--base-url URL] [--secret SECRET]",
6269
6995
  " kynver run reconcile",
6270
6996
  " kynver plan progress --plan PLAN_ID --row ROW_KEY --role ROLE --status STATUS [--task TASK_ID] [--note NOTE] [--evidence type:value] [--agent-os-id AOS_ID]",
6271
- " kynver plan verify --plan PLAN_ID [--worktree PATH] [--task TASK_ID] [--human-override]",
6997
+ " kynver plan verify --plan PLAN_ID [--worktree PATH] [--task TASK_ID] [--human-override] [--local]",
6998
+ " kynver harness verify --worktree PATH [--command CMD] [--json] [--wait-for-admission-ms MS] [--timeout-ms MS]",
6272
6999
  " kynver plan persist --operation create|add_version|update_metadata --title TITLE (--body-file PATH | --body TEXT) [--slug SLUG] [--plan PLAN_ID] [--summary TEXT] [--failure-kind approval_guard|auth|network|server|tool_interruption]",
6273
7000
  " kynver plan outbox list",
6274
7001
  " kynver plan outbox drain [--max N] [--id OUTBOX_ID]",
@@ -6280,7 +7007,8 @@ function usage(code = 0) {
6280
7007
  " kynver monitor tick --run RUN_ID [--name worker] [--agent-os-id AOS_ID] [--auto-complete] [--renew-leases]",
6281
7008
  " kynver monitor auto-complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--base-url URL] [--secret SECRET]",
6282
7009
  " kynver monitor run-loop --run RUN_ID --monitor-id ID [--name worker] [--agent-os-id AOS_ID] [--poll-ms MS] [--auto-complete] [--renew-leases]",
6283
- " kynver doctor runtime-takeover"
7010
+ " kynver doctor runtime-takeover",
7011
+ " kynver board contract [--agent-os-id ID] [--base-url URL] [--since ISO] [--limit N]"
6284
7012
  ].join("\n")
6285
7013
  );
6286
7014
  process.exit(code);
@@ -6291,7 +7019,7 @@ async function main(argv = process.argv.slice(2)) {
6291
7019
  const scope = argv.shift();
6292
7020
  let action;
6293
7021
  let rest;
6294
- if (scope === "run" || scope === "worker" || scope === "plan" || scope === "runner" || scope === "monitor" || scope === "doctor") {
7022
+ if (scope === "run" || scope === "worker" || scope === "plan" || scope === "runner" || scope === "harness" || scope === "monitor" || scope === "doctor" || scope === "board") {
6295
7023
  action = argv.shift();
6296
7024
  rest = argv;
6297
7025
  } else {
@@ -6308,6 +7036,7 @@ async function main(argv = process.argv.slice(2)) {
6308
7036
  if (scope === "daemon") return void await runDaemon(args);
6309
7037
  if (scope === "plan" && action === "progress") return void await emitPlanProgress(args);
6310
7038
  if (scope === "plan" && action === "verify") return void await verifyPlan(args);
7039
+ if (scope === "harness" && action === "verify") return runHarnessVerifyCli(args);
6311
7040
  if (scope === "plan" && action === "persist") return void await runPlanPersist(args);
6312
7041
  if (scope === "plan" && action === "outbox") {
6313
7042
  const outboxAction = rest.shift();
@@ -6317,6 +7046,9 @@ async function main(argv = process.argv.slice(2)) {
6317
7046
  }
6318
7047
  if (scope === "cleanup") return runCleanupCli(args);
6319
7048
  if (scope === "doctor" && action === "runtime-takeover") return runRuntimeTakeoverDoctorCli();
7049
+ if (scope === "board" && action === "contract") {
7050
+ return void await runCommandCenterContractCli(args);
7051
+ }
6320
7052
  if (scope === "run" && action === "create") return createRun(args);
6321
7053
  if (scope === "run" && action === "list") return listRuns();
6322
7054
  if (scope === "run" && action === "status") return runStatus(args);
@@ -6443,10 +7175,10 @@ function pickVercelStatusContext(statuses) {
6443
7175
  return 1;
6444
7176
  };
6445
7177
  let best = null;
6446
- let bestScore = -1;
7178
+ let bestScore = Infinity;
6447
7179
  for (const row of vercelRows) {
6448
7180
  const rowScore = score(normalizeGitHubStatusState(row.state));
6449
- if (rowScore > bestScore) {
7181
+ if (rowScore < bestScore) {
6450
7182
  best = row;
6451
7183
  bestScore = rowScore;
6452
7184
  }
@@ -6466,7 +7198,7 @@ function pickVercelStatusContext(statuses) {
6466
7198
  }
6467
7199
 
6468
7200
  // src/vercel/vercel-evidence.ts
6469
- import { spawnSync as spawnSync4 } from "node:child_process";
7201
+ import { spawnSync as spawnSync7 } from "node:child_process";
6470
7202
  var DEFAULT_INSPECT_WAIT_SECONDS = 120;
6471
7203
  function mapGitHubStateToEvidence(state) {
6472
7204
  if (state === "success") return "ready";
@@ -6532,7 +7264,7 @@ function evidenceFromGitHubVercelStatus(statuses, options = {}) {
6532
7264
  }
6533
7265
  function defaultRunVercelInspect(target, waitSeconds) {
6534
7266
  const args = ["inspect", target, "--wait", String(waitSeconds)];
6535
- const result = spawnSync4("vercel", args, {
7267
+ const result = spawnSync7("vercel", args, {
6536
7268
  encoding: "utf8",
6537
7269
  stdio: ["ignore", "pipe", "pipe"]
6538
7270
  });
@@ -6640,16 +7372,23 @@ function collectVercelEvidence(input) {
6640
7372
  }
6641
7373
  export {
6642
7374
  DEFAULT_DISPATCH_LEASE_MS,
7375
+ DEFAULT_HARNESS_VERIFY_COMMANDS,
7376
+ FORBIDDEN_WORKER_ENV_KEYS,
6643
7377
  PACKAGE_VERSION,
6644
7378
  assessAutoCompleteEligibility,
7379
+ assessBuildAdmission,
6645
7380
  assessExitedWorkerSalvage,
6646
7381
  assessPrHandoffRequirement,
6647
7382
  assessWorkerLanding,
6648
7383
  assessWorkerLandingContract,
7384
+ auditWorkerEnv,
6649
7385
  autoCompleteWorker,
6650
7386
  autoCompleteWorkerCli,
6651
7387
  buildDispatchTaskText,
6652
7388
  buildPrompt,
7389
+ buildSystemdRunArgv,
7390
+ classifyNpmAuditOutcome,
7391
+ classifyShellCommandOutcome,
6653
7392
  classifyVercelUrl,
6654
7393
  classifyWorkerHealth,
6655
7394
  collectVercelEvidence,
@@ -6669,16 +7408,21 @@ export {
6669
7408
  getMonitorStatus,
6670
7409
  hashPlanBody,
6671
7410
  isDashboardVercelUrl,
7411
+ isEngagementRequiredSkip,
6672
7412
  isFinishedWorkerStatus,
7413
+ isForbiddenWorkerEnvKey,
6673
7414
  isLandingBlockedWorkerStatus,
7415
+ isSystemdRunAvailable,
6674
7416
  isTerminalHeartbeatPhase,
6675
7417
  isVercelStatusContext,
6676
7418
  landingContractAttentionReason,
7419
+ listForbiddenWorkerEnvKeys,
6677
7420
  listMonitors,
6678
7421
  listOutboxItems,
6679
7422
  listRuns,
6680
7423
  loadUserConfig,
6681
7424
  main,
7425
+ mergeNodeOptionsForBuildCheck,
6682
7426
  normalizeCursorModelAlias,
6683
7427
  observeRunnerDiskGate,
6684
7428
  parseArgs,
@@ -6689,6 +7433,7 @@ export {
6689
7433
  pickVercelStatusContext,
6690
7434
  postJson,
6691
7435
  preflightCursorModel,
7436
+ readMemAvailableBytes,
6692
7437
  reconcileRunsCli,
6693
7438
  reconcileStaleWorkers,
6694
7439
  redactHarness,
@@ -6697,16 +7442,22 @@ export {
6697
7442
  resolveCallbackSecretWithMint,
6698
7443
  resolveHarnessRoot,
6699
7444
  resolveVercelInspectTarget,
7445
+ runBoundedBuildCheck,
6700
7446
  runDaemon,
7447
+ runHarnessVerifyCommands,
6701
7448
  runMonitorTick,
6702
7449
  runStatus,
6703
7450
  saveUserConfig,
7451
+ scrubClaudeEnv,
7452
+ scrubWorkerEnv,
6704
7453
  spawnCompletionSidecar,
6705
7454
  spawnMonitorSidecar,
6706
7455
  spawnWorkerProcess,
6707
7456
  startWorker,
6708
7457
  stopWorker,
6709
7458
  summarizeEvent,
7459
+ summarizeNpmAuditReport,
7460
+ summarizeShellToolCallEvent,
6710
7461
  sweepRun,
6711
7462
  tailWorker,
6712
7463
  terminalFinalResultFromHeartbeat,