@kynver-app/runtime 0.1.103 → 0.1.105

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 (45) hide show
  1. package/dist/cleanup-completion-blocker.d.ts +10 -0
  2. package/dist/cleanup-guards.d.ts +1 -6
  3. package/dist/cleanup-worktree-salvage.d.ts +7 -0
  4. package/dist/cli.js +166 -59
  5. package/dist/cli.js.map +4 -4
  6. package/dist/index.js +166 -59
  7. package/dist/index.js.map +4 -4
  8. package/dist/server/cleanup.d.ts +3 -0
  9. package/dist/server/cleanup.js +3511 -0
  10. package/dist/server/cleanup.js.map +7 -0
  11. package/dist/server/default-repo.d.ts +1 -0
  12. package/dist/server/default-repo.js +228 -0
  13. package/dist/server/default-repo.js.map +7 -0
  14. package/dist/server/harness-notice.d.ts +2 -0
  15. package/dist/server/harness-notice.js +287 -0
  16. package/dist/server/harness-notice.js.map +7 -0
  17. package/dist/server/heavy-verification.d.ts +2 -0
  18. package/dist/server/heavy-verification.js +223 -0
  19. package/dist/server/heavy-verification.js.map +7 -0
  20. package/dist/server/landing.d.ts +1 -0
  21. package/dist/server/landing.js +44 -0
  22. package/dist/server/landing.js.map +7 -0
  23. package/dist/server/memory-cost-enforce.d.ts +1 -0
  24. package/dist/server/memory-cost-enforce.js +470 -0
  25. package/dist/server/memory-cost-enforce.js.map +7 -0
  26. package/dist/server/memory-cost.d.ts +1 -0
  27. package/dist/server/memory-cost.js +184 -0
  28. package/dist/server/memory-cost.js.map +7 -0
  29. package/dist/server/monitor.d.ts +3 -0
  30. package/dist/server/monitor.js +1577 -0
  31. package/dist/server/monitor.js.map +7 -0
  32. package/dist/server/orchestration.d.ts +10 -0
  33. package/dist/server/orchestration.js +444 -0
  34. package/dist/server/orchestration.js.map +7 -0
  35. package/dist/server/pr-evidence.d.ts +2 -0
  36. package/dist/server/pr-evidence.js +163 -0
  37. package/dist/server/pr-evidence.js.map +7 -0
  38. package/dist/server/repo-search.d.ts +1 -0
  39. package/dist/server/repo-search.js +224 -0
  40. package/dist/server/repo-search.js.map +7 -0
  41. package/dist/server/worker-policy.d.ts +2 -0
  42. package/dist/server/worker-policy.js +177 -0
  43. package/dist/server/worker-policy.js.map +7 -0
  44. package/dist/status.d.ts +4 -0
  45. package/package.json +63 -3
@@ -0,0 +1,287 @@
1
+ // src/harness-notice/harness-notice.parse.ts
2
+ var MAX_DIAGNOSTIC_CHARS = 2400;
3
+ function tryParseJsonValue(text) {
4
+ const trimmed = text.trim();
5
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return null;
6
+ try {
7
+ return JSON.parse(trimmed);
8
+ } catch {
9
+ return null;
10
+ }
11
+ }
12
+ function diagnosticJson(value, maxChars = MAX_DIAGNOSTIC_CHARS) {
13
+ if (value === void 0 || value === null) return void 0;
14
+ const raw = typeof value === "string" ? value : JSON.stringify(value, null, 2);
15
+ const trimmed = raw.trim();
16
+ if (!trimmed) return void 0;
17
+ if (trimmed.length <= maxChars) return trimmed;
18
+ return `${trimmed.slice(0, maxChars - 1).trimEnd()}\u2026`;
19
+ }
20
+ function firstJsonFromStdout(stdout) {
21
+ const trimmed = stdout.trim();
22
+ if (!trimmed) return null;
23
+ const direct = tryParseJsonValue(trimmed);
24
+ if (direct !== null) return direct;
25
+ for (const line of trimmed.split("\n")) {
26
+ const parsed = tryParseJsonValue(line);
27
+ if (parsed !== null) return parsed;
28
+ }
29
+ return null;
30
+ }
31
+
32
+ // src/harness-notice/harness-notice.auto-complete.ts
33
+ function formatAutoCompleteOutcomeNotice(outcome) {
34
+ const lines = [];
35
+ lines.push(`Background auto-complete \xB7 ${outcome.runId} / ${outcome.worker}`);
36
+ switch (outcome.outcome) {
37
+ case "completed":
38
+ lines.push("Outcome: harness completion posted to AgentOS successfully.");
39
+ lines.push("AgentOS task should close or advance to review per completion routing.");
40
+ lines.push("Next: check Command Center \u2014 no manual complete needed unless the board still shows running.");
41
+ break;
42
+ case "blocked":
43
+ lines.push(
44
+ `Outcome: worker finished but completion was blocked${outcome.httpStatus ? ` (HTTP ${outcome.httpStatus})` : ""}.`
45
+ );
46
+ if (outcome.reason) lines.push(`Blocker: ${outcome.reason}`);
47
+ lines.push("Next: fix the blocker (auth, landing gate, dirty worktree) and replay completion from Command Center.");
48
+ break;
49
+ case "timed_out":
50
+ lines.push(`Outcome: monitor gave up waiting \u2014 ${outcome.reason ?? "worker did not finish in time"}.`);
51
+ lines.push("Next: inspect the worker process/logs; stop or unblock the worker, then retry auto-complete.");
52
+ break;
53
+ case "missing_link":
54
+ lines.push(`Outcome: cannot complete \u2014 ${outcome.reason ?? "worker missing agentOsId/taskId"}.`);
55
+ lines.push("Next: re-dispatch with board linkage or run `kynver worker complete` with --agent-os-id.");
56
+ break;
57
+ default:
58
+ lines.push(`Outcome: ${outcome.outcome}`);
59
+ }
60
+ return { primary: lines.join("\n"), diagnostic: diagnosticJson(outcome) };
61
+ }
62
+
63
+ // src/harness-notice/harness-notice.monitor-tick.ts
64
+ function formatMonitorTickNotice(tick) {
65
+ const lines = [];
66
+ const monitorId = typeof tick.monitorId === "string" ? tick.monitorId : void 0;
67
+ lines.push(
68
+ monitorId ? `Harness monitor tick \xB7 ${tick.runId} (${monitorId})` : `Harness monitor tick \xB7 ${tick.runId}`
69
+ );
70
+ if (!tick.workers.length) {
71
+ lines.push("No workers in scope for this poll.");
72
+ return { primary: lines.join("\n"), diagnostic: diagnosticJson(tick) };
73
+ }
74
+ for (const view of tick.workers) {
75
+ const auto = view.autoComplete.eligible ? "eligible for auto-complete" : "not auto-completing";
76
+ const blockers = view.autoComplete.blockers.length > 0 ? ` (${view.autoComplete.blockers.slice(0, 2).join("; ")})` : "";
77
+ lines.push(
78
+ `\u2022 ${view.worker}: ${view.workerStatus}, ${view.health}${view.healthReason ? ` \u2014 ${view.healthReason}` : ""}; ${auto}${blockers}`
79
+ );
80
+ if (view.taskStatus) {
81
+ lines.push(` Board task: ${view.taskStatus}${view.leaseOwner ? ` (lease: ${view.leaseOwner})` : ""}`);
82
+ }
83
+ }
84
+ const completed = tick.autoCompleted?.filter((a) => a.outcome === "completed" && a.ok) ?? [];
85
+ const blocked = tick.autoCompleted?.filter((a) => !a.ok && a.outcome !== "skipped") ?? [];
86
+ if (completed.length) {
87
+ lines.push(
88
+ `Auto-completed: ${completed.map((c) => c.worker).join(", ")} \u2014 AgentOS completion should be posted.`
89
+ );
90
+ }
91
+ if (blocked.length) {
92
+ lines.push(
93
+ `Auto-complete blocked: ${blocked.map((c) => `${c.worker}${c.reason ? ` (${c.reason})` : ""}`).join("; ")}`
94
+ );
95
+ }
96
+ if (tick.leaseRenewal?.failed?.length) {
97
+ lines.push(`Lease renew failed for: ${tick.leaseRenewal.failed.map((f) => f.worker).join(", ")}`);
98
+ }
99
+ const allDone = tick.workers.length > 0 && tick.workers.every((w) => w.autoComplete.terminalVerified) && (tick.autoCompleted?.every((a) => a.ok || a.outcome === "skipped") ?? true);
100
+ lines.push(
101
+ allDone ? "Next: monitor loop should stop \u2014 all workers terminal and handled." : "Next: monitor will poll again until workers are terminal-verified or max time elapses."
102
+ );
103
+ return { primary: lines.join("\n"), diagnostic: diagnosticJson(tick) };
104
+ }
105
+
106
+ // src/harness-notice/harness-notice.worker-complete.ts
107
+ function record(value) {
108
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
109
+ }
110
+ function str(value) {
111
+ return typeof value === "string" && value.trim() ? value.trim() : null;
112
+ }
113
+ function formatWorkerCompleteNotice(data) {
114
+ const rec = record(data);
115
+ if (!rec) {
116
+ return {
117
+ primary: "Harness worker complete finished with no parseable result.",
118
+ diagnostic: diagnosticJson(data)
119
+ };
120
+ }
121
+ const worker = str(rec.worker) ?? "worker";
122
+ const runId = str(rec.runId);
123
+ const skipped = str(rec.status) === "skipped";
124
+ const httpStatus = typeof rec.httpStatus === "number" ? rec.httpStatus : null;
125
+ const response = record(rec.response);
126
+ const lines = [];
127
+ lines.push(`Harness worker complete \xB7 ${worker}${runId ? ` (${runId})` : ""}`);
128
+ if (skipped) {
129
+ lines.push(`Outcome: skipped \u2014 ${str(rec.reason) ?? "worker not finished yet"}.`);
130
+ lines.push("Next: wait for the worker to exit or post a finalResult, then retry complete.");
131
+ return { primary: lines.join("\n"), diagnostic: diagnosticJson(data) };
132
+ }
133
+ const routeOutcome = str(response?.outcome);
134
+ const taskRec = record(response?.task);
135
+ const taskStatus = str(taskRec?.status);
136
+ const prUrl = str(taskRec?.prUrl) ?? str(response?.prUrl);
137
+ if (httpStatus && httpStatus >= 200 && httpStatus < 300) {
138
+ lines.push("Outcome: completion callback accepted by AgentOS.");
139
+ if (routeOutcome) lines.push(`Routing: ${routeOutcome.replace(/_/g, " ")}`);
140
+ if (taskStatus) lines.push(`AgentOS task status: ${taskStatus}`);
141
+ if (prUrl) lines.push(`PR: ${prUrl}`);
142
+ lines.push("Next: check Command Center for review scheduling or blockers.");
143
+ } else {
144
+ lines.push(
145
+ `Outcome: completion failed${httpStatus != null ? ` (HTTP ${httpStatus})` : ""}.`
146
+ );
147
+ const detail = str(response?.detail) ?? str(response?.error);
148
+ if (detail) lines.push(`Blocker: ${detail}`);
149
+ lines.push("Next: fix the reported blocker and replay completion from the board.");
150
+ }
151
+ return { primary: lines.join("\n"), diagnostic: diagnosticJson(data) };
152
+ }
153
+
154
+ // src/harness-notice/harness-notice.worker-status.ts
155
+ function str2(value) {
156
+ return typeof value === "string" && value.trim() ? value.trim() : null;
157
+ }
158
+ function record2(value) {
159
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
160
+ }
161
+ function prFromFinalResult(finalResult) {
162
+ const fr = record2(finalResult);
163
+ if (!fr) return null;
164
+ return str2(fr.prUrl) ?? str2(fr.pr);
165
+ }
166
+ function formatWorkerStatusNotice(status) {
167
+ const rec = record2(status);
168
+ if (!rec) {
169
+ return {
170
+ primary: "Harness worker status unavailable.",
171
+ diagnostic: diagnosticJson(status)
172
+ };
173
+ }
174
+ const worker = str2(rec.worker) ?? str2(rec.name) ?? "worker";
175
+ const runId = str2(rec.runId);
176
+ const workerStatus = str2(rec.status) ?? "unknown";
177
+ const alive = rec.alive === true;
178
+ const attention = record2(rec.attention);
179
+ const attentionState = str2(attention?.state) ?? str2(rec.attentionState);
180
+ const attentionReason = str2(attention?.reason) ?? str2(rec.attentionReason);
181
+ const taskId = str2(rec.taskId);
182
+ const prUrl = str2(rec.prUrl) ?? prFromFinalResult(rec.finalResult);
183
+ const branch = str2(rec.branch);
184
+ const headCommit = str2(rec.headCommit);
185
+ const lines = [];
186
+ lines.push(`Harness worker ${worker}${runId ? ` (${runId})` : ""}`);
187
+ lines.push(`Process: ${alive ? "running" : "stopped"} \xB7 harness status: ${workerStatus}`);
188
+ if (attentionState) {
189
+ lines.push(
190
+ attentionReason ? `Attention: ${attentionState} \u2014 ${attentionReason}` : `Attention: ${attentionState}`
191
+ );
192
+ }
193
+ if (taskId) lines.push(`AgentOS task: ${taskId}`);
194
+ if (prUrl) lines.push(`PR: ${prUrl}`);
195
+ if (branch) lines.push(`Branch: ${branch}`);
196
+ if (headCommit) lines.push(`Commit: ${headCommit.slice(0, 12)}`);
197
+ if (workerStatus === "done" || workerStatus === "exited") {
198
+ lines.push(
199
+ prUrl ? "Outcome: worker finished \u2014 open the PR or check Command Center for review routing." : "Outcome: worker finished \u2014 check Command Center for task status and next action."
200
+ );
201
+ } else if (attentionState === "blocked" || attentionState === "needs_attention") {
202
+ lines.push("Next: resolve the blocker on the board or wait for the monitor to auto-complete when terminal.");
203
+ } else if (alive) {
204
+ lines.push("Next: wait for completion or poll again; background monitor will auto-complete when eligible.");
205
+ }
206
+ return { primary: lines.join("\n"), diagnostic: diagnosticJson(status) };
207
+ }
208
+
209
+ // src/harness-notice/harness-notice.tool-response.ts
210
+ var DIVIDER = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Diagnostic (JSON) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
211
+ function joinHarnessNotice(notice) {
212
+ if (!notice.diagnostic?.trim()) return notice.primary;
213
+ return `${notice.primary}
214
+
215
+ ${DIVIDER}
216
+ ${notice.diagnostic}`;
217
+ }
218
+ function failureNotice(ctx) {
219
+ const lines = [`Harness ${ctx.scope} ${ctx.action} failed.`];
220
+ if (ctx.timedOut) lines.push("Reason: command timed out on the runner host.");
221
+ else if (ctx.error) lines.push(`Reason: ${ctx.error}`);
222
+ else if (ctx.exitCode != null) lines.push(`Exit code: ${ctx.exitCode}`);
223
+ const errText = ctx.stderr.trim();
224
+ if (errText) lines.push(`Stderr: ${errText.split("\n").slice(-3).join(" ")}`);
225
+ lines.push("Next: retry on the runner host or inspect harness logs.");
226
+ const parsed = firstJsonFromStdout(ctx.stdout);
227
+ return {
228
+ primary: lines.join("\n"),
229
+ diagnostic: diagnosticJson(parsed ?? { stdout: ctx.stdout, stderr: ctx.stderr })
230
+ };
231
+ }
232
+ function formatHarnessToolReadable(ctx) {
233
+ if (!ctx.ok) return failureNotice(ctx);
234
+ const parsed = firstJsonFromStdout(ctx.stdout);
235
+ if (parsed === null) {
236
+ const text = ctx.stdout.trim() || ctx.stderr.trim() || "(no output)";
237
+ return {
238
+ primary: `Harness ${ctx.scope} ${ctx.action} finished.
239
+ ${text.slice(0, 800)}`,
240
+ diagnostic: diagnosticJson({ stdout: ctx.stdout, stderr: ctx.stderr })
241
+ };
242
+ }
243
+ if (ctx.scope === "worker" && ctx.action === "status") {
244
+ return formatWorkerStatusNotice(parsed);
245
+ }
246
+ if (ctx.scope === "worker" && ctx.action === "complete") {
247
+ return formatWorkerCompleteNotice(parsed);
248
+ }
249
+ if (ctx.scope === "monitor" && (ctx.action === "tick" || ctx.action === "run-loop")) {
250
+ return formatMonitorTickNotice(parsed);
251
+ }
252
+ if (ctx.scope === "monitor" && ctx.action === "auto-complete") {
253
+ const rec = parsed;
254
+ if (rec.outcome && rec.worker && rec.runId) {
255
+ return formatAutoCompleteOutcomeNotice(parsed);
256
+ }
257
+ if (Array.isArray(rec.blockers)) {
258
+ return {
259
+ primary: [
260
+ `Monitor auto-complete blocked \xB7 ${rec.runId ?? "run"} / ${rec.worker ?? "worker"}`,
261
+ `Blockers: ${rec.blockers.join("; ")}`,
262
+ "Next: resolve blockers on the runner, then retry auto-complete."
263
+ ].join("\n"),
264
+ diagnostic: diagnosticJson(parsed)
265
+ };
266
+ }
267
+ }
268
+ if (ctx.scope === "run" && ctx.action === "status") {
269
+ const workers = parsed.workers;
270
+ if (Array.isArray(workers) && workers.length === 1) {
271
+ return formatWorkerStatusNotice(workers[0]);
272
+ }
273
+ return {
274
+ primary: `Harness run status \xB7 ${parsed.runId ?? "run"} (${Array.isArray(workers) ? workers.length : 0} workers).`,
275
+ diagnostic: diagnosticJson(parsed)
276
+ };
277
+ }
278
+ return {
279
+ primary: `Harness ${ctx.scope} ${ctx.action} completed successfully on the runner.`,
280
+ diagnostic: diagnosticJson(parsed)
281
+ };
282
+ }
283
+ export {
284
+ formatHarnessToolReadable,
285
+ joinHarnessNotice
286
+ };
287
+ //# sourceMappingURL=harness-notice.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/harness-notice/harness-notice.parse.ts", "../../src/harness-notice/harness-notice.auto-complete.ts", "../../src/harness-notice/harness-notice.monitor-tick.ts", "../../src/harness-notice/harness-notice.worker-complete.ts", "../../src/harness-notice/harness-notice.worker-status.ts", "../../src/harness-notice/harness-notice.tool-response.ts"],
4
+ "sourcesContent": ["const MAX_DIAGNOSTIC_CHARS = 2_400;\r\n\r\nexport function tryParseJsonValue(text: string): unknown | null {\r\n const trimmed = text.trim();\r\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) return null;\r\n try {\r\n return JSON.parse(trimmed) as unknown;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function diagnosticJson(value: unknown, maxChars = MAX_DIAGNOSTIC_CHARS): string | undefined {\r\n if (value === undefined || value === null) return undefined;\r\n const raw = typeof value === \"string\" ? value : JSON.stringify(value, null, 2);\r\n const trimmed = raw.trim();\r\n if (!trimmed) return undefined;\r\n if (trimmed.length <= maxChars) return trimmed;\r\n return `${trimmed.slice(0, maxChars - 1).trimEnd()}\u2026`;\r\n}\r\n\r\nexport function firstJsonFromStdout(stdout: string): unknown | null {\r\n const trimmed = stdout.trim();\r\n if (!trimmed) return null;\r\n const direct = tryParseJsonValue(trimmed);\r\n if (direct !== null) return direct;\r\n for (const line of trimmed.split(\"\\n\")) {\r\n const parsed = tryParseJsonValue(line);\r\n if (parsed !== null) return parsed;\r\n }\r\n return null;\r\n}\r\n", "import type { AutoCompleteOutcome } from \"../auto-complete.js\";\r\nimport type { HarnessReadableNotice } from \"./harness-notice.types.js\";\r\nimport { diagnosticJson } from \"./harness-notice.parse.js\";\r\n\r\nexport function formatAutoCompleteOutcomeNotice(outcome: AutoCompleteOutcome): HarnessReadableNotice {\r\n const lines: string[] = [];\r\n lines.push(`Background auto-complete \u00B7 ${outcome.runId} / ${outcome.worker}`);\r\n\r\n switch (outcome.outcome) {\r\n case \"completed\":\r\n lines.push(\"Outcome: harness completion posted to AgentOS successfully.\");\r\n lines.push(\"AgentOS task should close or advance to review per completion routing.\");\r\n lines.push(\"Next: check Command Center \u2014 no manual complete needed unless the board still shows running.\");\r\n break;\r\n case \"blocked\":\r\n lines.push(\r\n `Outcome: worker finished but completion was blocked${outcome.httpStatus ? ` (HTTP ${outcome.httpStatus})` : \"\"}.`,\r\n );\r\n if (outcome.reason) lines.push(`Blocker: ${outcome.reason}`);\r\n lines.push(\"Next: fix the blocker (auth, landing gate, dirty worktree) and replay completion from Command Center.\");\r\n break;\r\n case \"timed_out\":\r\n lines.push(`Outcome: monitor gave up waiting \u2014 ${outcome.reason ?? \"worker did not finish in time\"}.`);\r\n lines.push(\"Next: inspect the worker process/logs; stop or unblock the worker, then retry auto-complete.\");\r\n break;\r\n case \"missing_link\":\r\n lines.push(`Outcome: cannot complete \u2014 ${outcome.reason ?? \"worker missing agentOsId/taskId\"}.`);\r\n lines.push(\"Next: re-dispatch with board linkage or run `kynver worker complete` with --agent-os-id.\");\r\n break;\r\n default:\r\n lines.push(`Outcome: ${outcome.outcome}`);\r\n }\r\n\r\n return { primary: lines.join(\"\\n\"), diagnostic: diagnosticJson(outcome) };\r\n}\r\n", "import type { MonitorTickResult } from \"../monitor/monitor.types.js\";\r\nimport type { HarnessReadableNotice } from \"./harness-notice.types.js\";\r\nimport { diagnosticJson } from \"./harness-notice.parse.js\";\r\n\r\nexport function formatMonitorTickNotice(tick: MonitorTickResult & { monitorId?: string; phase?: string }): HarnessReadableNotice {\r\n const lines: string[] = [];\r\n const monitorId = typeof tick.monitorId === \"string\" ? tick.monitorId : undefined;\r\n lines.push(\r\n monitorId\r\n ? `Harness monitor tick \u00B7 ${tick.runId} (${monitorId})`\r\n : `Harness monitor tick \u00B7 ${tick.runId}`,\r\n );\r\n\r\n if (!tick.workers.length) {\r\n lines.push(\"No workers in scope for this poll.\");\r\n return { primary: lines.join(\"\\n\"), diagnostic: diagnosticJson(tick) };\r\n }\r\n\r\n for (const view of tick.workers) {\r\n const auto = view.autoComplete.eligible ? \"eligible for auto-complete\" : \"not auto-completing\";\r\n const blockers =\r\n view.autoComplete.blockers.length > 0 ? ` (${view.autoComplete.blockers.slice(0, 2).join(\"; \")})` : \"\";\r\n lines.push(\r\n `\u2022 ${view.worker}: ${view.workerStatus}, ${view.health}${view.healthReason ? ` \u2014 ${view.healthReason}` : \"\"}; ${auto}${blockers}`,\r\n );\r\n if (view.taskStatus) {\r\n lines.push(` Board task: ${view.taskStatus}${view.leaseOwner ? ` (lease: ${view.leaseOwner})` : \"\"}`);\r\n }\r\n }\r\n\r\n const completed = tick.autoCompleted?.filter((a) => a.outcome === \"completed\" && a.ok) ?? [];\r\n const blocked = tick.autoCompleted?.filter((a) => !a.ok && a.outcome !== \"skipped\") ?? [];\r\n if (completed.length) {\r\n lines.push(\r\n `Auto-completed: ${completed.map((c) => c.worker).join(\", \")} \u2014 AgentOS completion should be posted.`,\r\n );\r\n }\r\n if (blocked.length) {\r\n lines.push(\r\n `Auto-complete blocked: ${blocked.map((c) => `${c.worker}${c.reason ? ` (${c.reason})` : \"\"}`).join(\"; \")}`,\r\n );\r\n }\r\n if (tick.leaseRenewal?.failed?.length) {\r\n lines.push(`Lease renew failed for: ${tick.leaseRenewal.failed.map((f) => f.worker).join(\", \")}`);\r\n }\r\n\r\n const allDone =\r\n tick.workers.length > 0 &&\r\n tick.workers.every((w) => w.autoComplete.terminalVerified) &&\r\n (tick.autoCompleted?.every((a) => a.ok || a.outcome === \"skipped\") ?? true);\r\n lines.push(\r\n allDone\r\n ? \"Next: monitor loop should stop \u2014 all workers terminal and handled.\"\r\n : \"Next: monitor will poll again until workers are terminal-verified or max time elapses.\",\r\n );\r\n\r\n return { primary: lines.join(\"\\n\"), diagnostic: diagnosticJson(tick) };\r\n}\r\n", "import type { HarnessReadableNotice } from \"./harness-notice.types.js\";\r\nimport { diagnosticJson } from \"./harness-notice.parse.js\";\r\n\r\nfunction record(value: unknown): Record<string, unknown> | null {\r\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\r\n ? (value as Record<string, unknown>)\r\n : null;\r\n}\r\n\r\nfunction str(value: unknown): string | null {\r\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\r\n}\r\n\r\n/** Format `kynver worker complete` CLI JSON for operators. */\r\nexport function formatWorkerCompleteNotice(data: unknown): HarnessReadableNotice {\r\n const rec = record(data);\r\n if (!rec) {\r\n return {\r\n primary: \"Harness worker complete finished with no parseable result.\",\r\n diagnostic: diagnosticJson(data),\r\n };\r\n }\r\n\r\n const worker = str(rec.worker) ?? \"worker\";\r\n const runId = str(rec.runId);\r\n const skipped = str(rec.status) === \"skipped\";\r\n const httpStatus = typeof rec.httpStatus === \"number\" ? rec.httpStatus : null;\r\n const response = record(rec.response);\r\n\r\n const lines: string[] = [];\r\n lines.push(`Harness worker complete \u00B7 ${worker}${runId ? ` (${runId})` : \"\"}`);\r\n\r\n if (skipped) {\r\n lines.push(`Outcome: skipped \u2014 ${str(rec.reason) ?? \"worker not finished yet\"}.`);\r\n lines.push(\"Next: wait for the worker to exit or post a finalResult, then retry complete.\");\r\n return { primary: lines.join(\"\\n\"), diagnostic: diagnosticJson(data) };\r\n }\r\n\r\n const routeOutcome = str(response?.outcome);\r\n const taskRec = record(response?.task);\r\n const taskStatus = str(taskRec?.status);\r\n const prUrl = str(taskRec?.prUrl) ?? str(response?.prUrl);\r\n\r\n if (httpStatus && httpStatus >= 200 && httpStatus < 300) {\r\n lines.push(\"Outcome: completion callback accepted by AgentOS.\");\r\n if (routeOutcome) lines.push(`Routing: ${routeOutcome.replace(/_/g, \" \")}`);\r\n if (taskStatus) lines.push(`AgentOS task status: ${taskStatus}`);\r\n if (prUrl) lines.push(`PR: ${prUrl}`);\r\n lines.push(\"Next: check Command Center for review scheduling or blockers.\");\r\n } else {\r\n lines.push(\r\n `Outcome: completion failed${httpStatus != null ? ` (HTTP ${httpStatus})` : \"\"}.`,\r\n );\r\n const detail = str(response?.detail) ?? str(response?.error);\r\n if (detail) lines.push(`Blocker: ${detail}`);\r\n lines.push(\"Next: fix the reported blocker and replay completion from the board.\");\r\n }\r\n\r\n return { primary: lines.join(\"\\n\"), diagnostic: diagnosticJson(data) };\r\n}\r\n", "import type { HarnessReadableNotice } from \"./harness-notice.types.js\";\r\nimport { diagnosticJson } from \"./harness-notice.parse.js\";\r\n\r\nfunction str(value: unknown): string | null {\r\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\r\n}\r\n\r\nfunction record(value: unknown): Record<string, unknown> | null {\r\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\r\n ? (value as Record<string, unknown>)\r\n : null;\r\n}\r\n\r\nfunction prFromFinalResult(finalResult: unknown): string | null {\r\n const fr = record(finalResult);\r\n if (!fr) return null;\r\n return str(fr.prUrl) ?? str(fr.pr);\r\n}\r\n\r\nexport function formatWorkerStatusNotice(status: unknown): HarnessReadableNotice {\r\n const rec = record(status);\r\n if (!rec) {\r\n return {\r\n primary: \"Harness worker status unavailable.\",\r\n diagnostic: diagnosticJson(status),\r\n };\r\n }\r\n\r\n const worker = str(rec.worker) ?? str(rec.name) ?? \"worker\";\r\n const runId = str(rec.runId);\r\n const workerStatus = str(rec.status) ?? \"unknown\";\r\n const alive = rec.alive === true;\r\n const attention = record(rec.attention);\r\n const attentionState = str(attention?.state) ?? str(rec.attentionState);\r\n const attentionReason = str(attention?.reason) ?? str(rec.attentionReason);\r\n const taskId = str(rec.taskId);\r\n const prUrl = str(rec.prUrl) ?? prFromFinalResult(rec.finalResult);\r\n const branch = str(rec.branch);\r\n const headCommit = str(rec.headCommit);\r\n\r\n const lines: string[] = [];\r\n lines.push(`Harness worker ${worker}${runId ? ` (${runId})` : \"\"}`);\r\n lines.push(`Process: ${alive ? \"running\" : \"stopped\"} \u00B7 harness status: ${workerStatus}`);\r\n if (attentionState) {\r\n lines.push(\r\n attentionReason\r\n ? `Attention: ${attentionState} \u2014 ${attentionReason}`\r\n : `Attention: ${attentionState}`,\r\n );\r\n }\r\n if (taskId) lines.push(`AgentOS task: ${taskId}`);\r\n if (prUrl) lines.push(`PR: ${prUrl}`);\r\n if (branch) lines.push(`Branch: ${branch}`);\r\n if (headCommit) lines.push(`Commit: ${headCommit.slice(0, 12)}`);\r\n\r\n if (workerStatus === \"done\" || workerStatus === \"exited\") {\r\n lines.push(\r\n prUrl\r\n ? \"Outcome: worker finished \u2014 open the PR or check Command Center for review routing.\"\r\n : \"Outcome: worker finished \u2014 check Command Center for task status and next action.\",\r\n );\r\n } else if (attentionState === \"blocked\" || attentionState === \"needs_attention\") {\r\n lines.push(\"Next: resolve the blocker on the board or wait for the monitor to auto-complete when terminal.\");\r\n } else if (alive) {\r\n lines.push(\"Next: wait for completion or poll again; background monitor will auto-complete when eligible.\");\r\n }\r\n\r\n return { primary: lines.join(\"\\n\"), diagnostic: diagnosticJson(status) };\r\n}\r\n", "import type { AutoCompleteOutcome } from \"../auto-complete.js\";\r\nimport type { MonitorTickResult } from \"../monitor/monitor.types.js\";\r\nimport type { HarnessReadableNotice, HarnessToolFormatContext } from \"./harness-notice.types.js\";\r\nimport { firstJsonFromStdout, diagnosticJson } from \"./harness-notice.parse.js\";\r\nimport { formatAutoCompleteOutcomeNotice } from \"./harness-notice.auto-complete.js\";\r\nimport { formatMonitorTickNotice } from \"./harness-notice.monitor-tick.js\";\r\nimport { formatWorkerCompleteNotice } from \"./harness-notice.worker-complete.js\";\r\nimport { formatWorkerStatusNotice } from \"./harness-notice.worker-status.js\";\r\n\r\nconst DIVIDER = \"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Diagnostic (JSON) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\";\r\n\r\nexport function joinHarnessNotice(notice: HarnessReadableNotice): string {\r\n if (!notice.diagnostic?.trim()) return notice.primary;\r\n return `${notice.primary}\\n\\n${DIVIDER}\\n${notice.diagnostic}`;\r\n}\r\n\r\nfunction failureNotice(ctx: HarnessToolFormatContext): HarnessReadableNotice {\r\n const lines = [`Harness ${ctx.scope} ${ctx.action} failed.`];\r\n if (ctx.timedOut) lines.push(\"Reason: command timed out on the runner host.\");\r\n else if (ctx.error) lines.push(`Reason: ${ctx.error}`);\r\n else if (ctx.exitCode != null) lines.push(`Exit code: ${ctx.exitCode}`);\r\n const errText = ctx.stderr.trim();\r\n if (errText) lines.push(`Stderr: ${errText.split(\"\\n\").slice(-3).join(\" \")}`);\r\n lines.push(\"Next: retry on the runner host or inspect harness logs.\");\r\n const parsed = firstJsonFromStdout(ctx.stdout);\r\n return {\r\n primary: lines.join(\"\\n\"),\r\n diagnostic: diagnosticJson(parsed ?? { stdout: ctx.stdout, stderr: ctx.stderr }),\r\n };\r\n}\r\n\r\nexport function formatHarnessToolReadable(ctx: HarnessToolFormatContext): HarnessReadableNotice {\r\n if (!ctx.ok) return failureNotice(ctx);\r\n\r\n const parsed = firstJsonFromStdout(ctx.stdout);\r\n if (parsed === null) {\r\n const text = ctx.stdout.trim() || ctx.stderr.trim() || \"(no output)\";\r\n return {\r\n primary: `Harness ${ctx.scope} ${ctx.action} finished.\\n${text.slice(0, 800)}`,\r\n diagnostic: diagnosticJson({ stdout: ctx.stdout, stderr: ctx.stderr }),\r\n };\r\n }\r\n\r\n if (ctx.scope === \"worker\" && ctx.action === \"status\") {\r\n return formatWorkerStatusNotice(parsed);\r\n }\r\n if (ctx.scope === \"worker\" && ctx.action === \"complete\") {\r\n return formatWorkerCompleteNotice(parsed);\r\n }\r\n if (ctx.scope === \"monitor\" && (ctx.action === \"tick\" || ctx.action === \"run-loop\")) {\r\n return formatMonitorTickNotice(parsed as MonitorTickResult);\r\n }\r\n if (ctx.scope === \"monitor\" && ctx.action === \"auto-complete\") {\r\n const rec = parsed as Record<string, unknown>;\r\n if (rec.outcome && rec.worker && rec.runId) {\r\n return formatAutoCompleteOutcomeNotice(parsed as AutoCompleteOutcome);\r\n }\r\n if (Array.isArray(rec.blockers)) {\r\n return {\r\n primary: [\r\n `Monitor auto-complete blocked \u00B7 ${rec.runId ?? \"run\"} / ${rec.worker ?? \"worker\"}`,\r\n `Blockers: ${(rec.blockers as string[]).join(\"; \")}`,\r\n \"Next: resolve blockers on the runner, then retry auto-complete.\",\r\n ].join(\"\\n\"),\r\n diagnostic: diagnosticJson(parsed),\r\n };\r\n }\r\n }\r\n\r\n if (ctx.scope === \"run\" && ctx.action === \"status\") {\r\n const workers = (parsed as Record<string, unknown>).workers;\r\n if (Array.isArray(workers) && workers.length === 1) {\r\n return formatWorkerStatusNotice(workers[0]);\r\n }\r\n return {\r\n primary: `Harness run status \u00B7 ${(parsed as Record<string, unknown>).runId ?? \"run\"} (${Array.isArray(workers) ? workers.length : 0} workers).`,\r\n diagnostic: diagnosticJson(parsed),\r\n };\r\n }\r\n\r\n return {\r\n primary: `Harness ${ctx.scope} ${ctx.action} completed successfully on the runner.`,\r\n diagnostic: diagnosticJson(parsed),\r\n };\r\n}\r\n"],
5
+ "mappings": ";AAAA,IAAM,uBAAuB;AAEtB,SAAS,kBAAkB,MAA8B;AAC9D,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,CAAC,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,GAAG,EAAG,QAAO;AACjE,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe,OAAgB,WAAW,sBAA0C;AAClG,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,QAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,OAAO,MAAM,CAAC;AAC7E,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,QAAQ,UAAU,SAAU,QAAO;AACvC,SAAO,GAAG,QAAQ,MAAM,GAAG,WAAW,CAAC,EAAE,QAAQ,CAAC;AACpD;AAEO,SAAS,oBAAoB,QAAgC;AAClE,QAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,SAAS,kBAAkB,OAAO;AACxC,MAAI,WAAW,KAAM,QAAO;AAC5B,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAM,SAAS,kBAAkB,IAAI;AACrC,QAAI,WAAW,KAAM,QAAO;AAAA,EAC9B;AACA,SAAO;AACT;;;AC3BO,SAAS,gCAAgC,SAAqD;AACnG,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,iCAA8B,QAAQ,KAAK,MAAM,QAAQ,MAAM,EAAE;AAE5E,UAAQ,QAAQ,SAAS;AAAA,IACvB,KAAK;AACH,YAAM,KAAK,6DAA6D;AACxE,YAAM,KAAK,wEAAwE;AACnF,YAAM,KAAK,mGAA8F;AACzG;AAAA,IACF,KAAK;AACH,YAAM;AAAA,QACJ,sDAAsD,QAAQ,aAAa,UAAU,QAAQ,UAAU,MAAM,EAAE;AAAA,MACjH;AACA,UAAI,QAAQ,OAAQ,OAAM,KAAK,YAAY,QAAQ,MAAM,EAAE;AAC3D,YAAM,KAAK,uGAAuG;AAClH;AAAA,IACF,KAAK;AACH,YAAM,KAAK,2CAAsC,QAAQ,UAAU,+BAA+B,GAAG;AACrG,YAAM,KAAK,8FAA8F;AACzG;AAAA,IACF,KAAK;AACH,YAAM,KAAK,mCAA8B,QAAQ,UAAU,iCAAiC,GAAG;AAC/F,YAAM,KAAK,0FAA0F;AACrG;AAAA,IACF;AACE,YAAM,KAAK,YAAY,QAAQ,OAAO,EAAE;AAAA,EAC5C;AAEA,SAAO,EAAE,SAAS,MAAM,KAAK,IAAI,GAAG,YAAY,eAAe,OAAO,EAAE;AAC1E;;;AC9BO,SAAS,wBAAwB,MAAyF;AAC/H,QAAM,QAAkB,CAAC;AACzB,QAAM,YAAY,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY;AACxE,QAAM;AAAA,IACJ,YACI,6BAA0B,KAAK,KAAK,KAAK,SAAS,MAClD,6BAA0B,KAAK,KAAK;AAAA,EAC1C;AAEA,MAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,UAAM,KAAK,oCAAoC;AAC/C,WAAO,EAAE,SAAS,MAAM,KAAK,IAAI,GAAG,YAAY,eAAe,IAAI,EAAE;AAAA,EACvE;AAEA,aAAW,QAAQ,KAAK,SAAS;AAC/B,UAAM,OAAO,KAAK,aAAa,WAAW,+BAA+B;AACzE,UAAM,WACJ,KAAK,aAAa,SAAS,SAAS,IAAI,KAAK,KAAK,aAAa,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM;AACtG,UAAM;AAAA,MACJ,UAAK,KAAK,MAAM,KAAK,KAAK,YAAY,KAAK,KAAK,MAAM,GAAG,KAAK,eAAe,WAAM,KAAK,YAAY,KAAK,EAAE,KAAK,IAAI,GAAG,QAAQ;AAAA,IACjI;AACA,QAAI,KAAK,YAAY;AACnB,YAAM,KAAK,iBAAiB,KAAK,UAAU,GAAG,KAAK,aAAa,YAAY,KAAK,UAAU,MAAM,EAAE,EAAE;AAAA,IACvG;AAAA,EACF;AAEA,QAAM,YAAY,KAAK,eAAe,OAAO,CAAC,MAAM,EAAE,YAAY,eAAe,EAAE,EAAE,KAAK,CAAC;AAC3F,QAAM,UAAU,KAAK,eAAe,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,SAAS,KAAK,CAAC;AACxF,MAAI,UAAU,QAAQ;AACpB,UAAM;AAAA,MACJ,mBAAmB,UAAU,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF;AACA,MAAI,QAAQ,QAAQ;AAClB,UAAM;AAAA,MACJ,0BAA0B,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IAC3G;AAAA,EACF;AACA,MAAI,KAAK,cAAc,QAAQ,QAAQ;AACrC,UAAM,KAAK,2BAA2B,KAAK,aAAa,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EAClG;AAEA,QAAM,UACJ,KAAK,QAAQ,SAAS,KACtB,KAAK,QAAQ,MAAM,CAAC,MAAM,EAAE,aAAa,gBAAgB,MACxD,KAAK,eAAe,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,SAAS,KAAK;AACxE,QAAM;AAAA,IACJ,UACI,4EACA;AAAA,EACN;AAEA,SAAO,EAAE,SAAS,MAAM,KAAK,IAAI,GAAG,YAAY,eAAe,IAAI,EAAE;AACvE;;;ACtDA,SAAS,OAAO,OAAgD;AAC9D,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IACrE,QACD;AACN;AAEA,SAAS,IAAI,OAA+B;AAC1C,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI;AACpE;AAGO,SAAS,2BAA2B,MAAsC;AAC/E,QAAM,MAAM,OAAO,IAAI;AACvB,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,MACL,SAAS;AAAA,MACT,YAAY,eAAe,IAAI;AAAA,IACjC;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,IAAI,MAAM,KAAK;AAClC,QAAM,QAAQ,IAAI,IAAI,KAAK;AAC3B,QAAM,UAAU,IAAI,IAAI,MAAM,MAAM;AACpC,QAAM,aAAa,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AACzE,QAAM,WAAW,OAAO,IAAI,QAAQ;AAEpC,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,gCAA6B,MAAM,GAAG,QAAQ,KAAK,KAAK,MAAM,EAAE,EAAE;AAE7E,MAAI,SAAS;AACX,UAAM,KAAK,2BAAsB,IAAI,IAAI,MAAM,KAAK,yBAAyB,GAAG;AAChF,UAAM,KAAK,+EAA+E;AAC1F,WAAO,EAAE,SAAS,MAAM,KAAK,IAAI,GAAG,YAAY,eAAe,IAAI,EAAE;AAAA,EACvE;AAEA,QAAM,eAAe,IAAI,UAAU,OAAO;AAC1C,QAAM,UAAU,OAAO,UAAU,IAAI;AACrC,QAAM,aAAa,IAAI,SAAS,MAAM;AACtC,QAAM,QAAQ,IAAI,SAAS,KAAK,KAAK,IAAI,UAAU,KAAK;AAExD,MAAI,cAAc,cAAc,OAAO,aAAa,KAAK;AACvD,UAAM,KAAK,mDAAmD;AAC9D,QAAI,aAAc,OAAM,KAAK,YAAY,aAAa,QAAQ,MAAM,GAAG,CAAC,EAAE;AAC1E,QAAI,WAAY,OAAM,KAAK,wBAAwB,UAAU,EAAE;AAC/D,QAAI,MAAO,OAAM,KAAK,OAAO,KAAK,EAAE;AACpC,UAAM,KAAK,+DAA+D;AAAA,EAC5E,OAAO;AACL,UAAM;AAAA,MACJ,6BAA6B,cAAc,OAAO,UAAU,UAAU,MAAM,EAAE;AAAA,IAChF;AACA,UAAM,SAAS,IAAI,UAAU,MAAM,KAAK,IAAI,UAAU,KAAK;AAC3D,QAAI,OAAQ,OAAM,KAAK,YAAY,MAAM,EAAE;AAC3C,UAAM,KAAK,sEAAsE;AAAA,EACnF;AAEA,SAAO,EAAE,SAAS,MAAM,KAAK,IAAI,GAAG,YAAY,eAAe,IAAI,EAAE;AACvE;;;ACxDA,SAASA,KAAI,OAA+B;AAC1C,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI;AACpE;AAEA,SAASC,QAAO,OAAgD;AAC9D,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IACrE,QACD;AACN;AAEA,SAAS,kBAAkB,aAAqC;AAC9D,QAAM,KAAKA,QAAO,WAAW;AAC7B,MAAI,CAAC,GAAI,QAAO;AAChB,SAAOD,KAAI,GAAG,KAAK,KAAKA,KAAI,GAAG,EAAE;AACnC;AAEO,SAAS,yBAAyB,QAAwC;AAC/E,QAAM,MAAMC,QAAO,MAAM;AACzB,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,MACL,SAAS;AAAA,MACT,YAAY,eAAe,MAAM;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,SAASD,KAAI,IAAI,MAAM,KAAKA,KAAI,IAAI,IAAI,KAAK;AACnD,QAAM,QAAQA,KAAI,IAAI,KAAK;AAC3B,QAAM,eAAeA,KAAI,IAAI,MAAM,KAAK;AACxC,QAAM,QAAQ,IAAI,UAAU;AAC5B,QAAM,YAAYC,QAAO,IAAI,SAAS;AACtC,QAAM,iBAAiBD,KAAI,WAAW,KAAK,KAAKA,KAAI,IAAI,cAAc;AACtE,QAAM,kBAAkBA,KAAI,WAAW,MAAM,KAAKA,KAAI,IAAI,eAAe;AACzE,QAAM,SAASA,KAAI,IAAI,MAAM;AAC7B,QAAM,QAAQA,KAAI,IAAI,KAAK,KAAK,kBAAkB,IAAI,WAAW;AACjE,QAAM,SAASA,KAAI,IAAI,MAAM;AAC7B,QAAM,aAAaA,KAAI,IAAI,UAAU;AAErC,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,kBAAkB,MAAM,GAAG,QAAQ,KAAK,KAAK,MAAM,EAAE,EAAE;AAClE,QAAM,KAAK,YAAY,QAAQ,YAAY,SAAS,yBAAsB,YAAY,EAAE;AACxF,MAAI,gBAAgB;AAClB,UAAM;AAAA,MACJ,kBACI,cAAc,cAAc,WAAM,eAAe,KACjD,cAAc,cAAc;AAAA,IAClC;AAAA,EACF;AACA,MAAI,OAAQ,OAAM,KAAK,iBAAiB,MAAM,EAAE;AAChD,MAAI,MAAO,OAAM,KAAK,OAAO,KAAK,EAAE;AACpC,MAAI,OAAQ,OAAM,KAAK,WAAW,MAAM,EAAE;AAC1C,MAAI,WAAY,OAAM,KAAK,WAAW,WAAW,MAAM,GAAG,EAAE,CAAC,EAAE;AAE/D,MAAI,iBAAiB,UAAU,iBAAiB,UAAU;AACxD,UAAM;AAAA,MACJ,QACI,4FACA;AAAA,IACN;AAAA,EACF,WAAW,mBAAmB,aAAa,mBAAmB,mBAAmB;AAC/E,UAAM,KAAK,gGAAgG;AAAA,EAC7G,WAAW,OAAO;AAChB,UAAM,KAAK,+FAA+F;AAAA,EAC5G;AAEA,SAAO,EAAE,SAAS,MAAM,KAAK,IAAI,GAAG,YAAY,eAAe,MAAM,EAAE;AACzE;;;AC3DA,IAAM,UAAU;AAET,SAAS,kBAAkB,QAAuC;AACvE,MAAI,CAAC,OAAO,YAAY,KAAK,EAAG,QAAO,OAAO;AAC9C,SAAO,GAAG,OAAO,OAAO;AAAA;AAAA,EAAO,OAAO;AAAA,EAAK,OAAO,UAAU;AAC9D;AAEA,SAAS,cAAc,KAAsD;AAC3E,QAAM,QAAQ,CAAC,WAAW,IAAI,KAAK,IAAI,IAAI,MAAM,UAAU;AAC3D,MAAI,IAAI,SAAU,OAAM,KAAK,+CAA+C;AAAA,WACnE,IAAI,MAAO,OAAM,KAAK,WAAW,IAAI,KAAK,EAAE;AAAA,WAC5C,IAAI,YAAY,KAAM,OAAM,KAAK,cAAc,IAAI,QAAQ,EAAE;AACtE,QAAM,UAAU,IAAI,OAAO,KAAK;AAChC,MAAI,QAAS,OAAM,KAAK,WAAW,QAAQ,MAAM,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG,CAAC,EAAE;AAC5E,QAAM,KAAK,yDAAyD;AACpE,QAAM,SAAS,oBAAoB,IAAI,MAAM;AAC7C,SAAO;AAAA,IACL,SAAS,MAAM,KAAK,IAAI;AAAA,IACxB,YAAY,eAAe,UAAU,EAAE,QAAQ,IAAI,QAAQ,QAAQ,IAAI,OAAO,CAAC;AAAA,EACjF;AACF;AAEO,SAAS,0BAA0B,KAAsD;AAC9F,MAAI,CAAC,IAAI,GAAI,QAAO,cAAc,GAAG;AAErC,QAAM,SAAS,oBAAoB,IAAI,MAAM;AAC7C,MAAI,WAAW,MAAM;AACnB,UAAM,OAAO,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,KAAK;AACvD,WAAO;AAAA,MACL,SAAS,WAAW,IAAI,KAAK,IAAI,IAAI,MAAM;AAAA,EAAe,KAAK,MAAM,GAAG,GAAG,CAAC;AAAA,MAC5E,YAAY,eAAe,EAAE,QAAQ,IAAI,QAAQ,QAAQ,IAAI,OAAO,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,MAAI,IAAI,UAAU,YAAY,IAAI,WAAW,UAAU;AACrD,WAAO,yBAAyB,MAAM;AAAA,EACxC;AACA,MAAI,IAAI,UAAU,YAAY,IAAI,WAAW,YAAY;AACvD,WAAO,2BAA2B,MAAM;AAAA,EAC1C;AACA,MAAI,IAAI,UAAU,cAAc,IAAI,WAAW,UAAU,IAAI,WAAW,aAAa;AACnF,WAAO,wBAAwB,MAA2B;AAAA,EAC5D;AACA,MAAI,IAAI,UAAU,aAAa,IAAI,WAAW,iBAAiB;AAC7D,UAAM,MAAM;AACZ,QAAI,IAAI,WAAW,IAAI,UAAU,IAAI,OAAO;AAC1C,aAAO,gCAAgC,MAA6B;AAAA,IACtE;AACA,QAAI,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAC/B,aAAO;AAAA,QACL,SAAS;AAAA,UACP,sCAAmC,IAAI,SAAS,KAAK,MAAM,IAAI,UAAU,QAAQ;AAAA,UACjF,aAAc,IAAI,SAAsB,KAAK,IAAI,CAAC;AAAA,UAClD;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,QACX,YAAY,eAAe,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,IAAI,UAAU,SAAS,IAAI,WAAW,UAAU;AAClD,UAAM,UAAW,OAAmC;AACpD,QAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAAG;AAClD,aAAO,yBAAyB,QAAQ,CAAC,CAAC;AAAA,IAC5C;AACA,WAAO;AAAA,MACL,SAAS,2BAAyB,OAAmC,SAAS,KAAK,KAAK,MAAM,QAAQ,OAAO,IAAI,QAAQ,SAAS,CAAC;AAAA,MACnI,YAAY,eAAe,MAAM;AAAA,IACnC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,WAAW,IAAI,KAAK,IAAI,IAAI,MAAM;AAAA,IAC3C,YAAY,eAAe,MAAM;AAAA,EACnC;AACF;",
6
+ "names": ["str", "record"]
7
+ }
@@ -0,0 +1,2 @@
1
+ export { assessHeavyVerificationGate, countActiveHeavyVerificationSlots, isHeavyVerificationGateSkipped, resolveHeavyVerificationMaxConcurrent, } from "../heavy-verification/slot.js";
2
+ export { compareSemver } from "../memory-cost-package-version-guard.js";
@@ -0,0 +1,223 @@
1
+ // src/heavy-verification/slot.ts
2
+ import {
3
+ closeSync,
4
+ existsSync,
5
+ mkdirSync as mkdirSync2,
6
+ openSync,
7
+ readdirSync,
8
+ readFileSync,
9
+ unlinkSync,
10
+ writeFileSync
11
+ } from "node:fs";
12
+ import path3 from "node:path";
13
+
14
+ // src/util.ts
15
+ function isPidAlive(pid) {
16
+ if (!pid) return false;
17
+ try {
18
+ process.kill(pid, 0);
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ // src/heavy-verification/paths.ts
26
+ import { mkdirSync } from "node:fs";
27
+ import path2 from "node:path";
28
+
29
+ // src/plan-persist/paths.ts
30
+ import { homedir } from "node:os";
31
+ import path from "node:path";
32
+ function resolveKynverStateRoot() {
33
+ const env = process.env.KYNVER_STATE_ROOT;
34
+ if (env) return path.resolve(env);
35
+ return path.join(homedir(), ".kynver", "state");
36
+ }
37
+
38
+ // src/heavy-verification/paths.ts
39
+ function resolveHeavyVerificationRoot() {
40
+ return path2.join(resolveKynverStateRoot(), "heavy-verification");
41
+ }
42
+ function heavyVerificationSlotsDir() {
43
+ return path2.join(resolveHeavyVerificationRoot(), "slots");
44
+ }
45
+ function ensureHeavyVerificationDirs() {
46
+ const dir = heavyVerificationSlotsDir();
47
+ mkdirSync(dir, { recursive: true });
48
+ return dir;
49
+ }
50
+
51
+ // src/heavy-verification/slot.ts
52
+ var DEFAULT_HEAVY_VERIFICATION_STALE_MS = 2 * 60 * 6e4;
53
+ var DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT = 1;
54
+ function positiveInt(value, fallback) {
55
+ const n = Number(value);
56
+ if (!Number.isFinite(n) || n <= 0) return fallback;
57
+ return Math.floor(n);
58
+ }
59
+ function isHeavyVerificationGateSkipped() {
60
+ const v = process.env.KYNVER_HEAVY_VERIFICATION_SKIP?.trim().toLowerCase();
61
+ return v === "1" || v === "true" || v === "yes";
62
+ }
63
+ function resolveHeavyVerificationMaxConcurrent() {
64
+ const env = process.env.KYNVER_HEAVY_VERIFICATION_MAX_CONCURRENT;
65
+ if (env) return positiveInt(env, DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT);
66
+ return DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT;
67
+ }
68
+ function readSlotRecord(filePath) {
69
+ if (!existsSync(filePath)) return null;
70
+ try {
71
+ const parsed = JSON.parse(readFileSync(filePath, "utf8"));
72
+ if (typeof parsed.slotId === "string" && typeof parsed.pid === "number" && typeof parsed.acquiredAt === "string" && typeof parsed.command === "string") {
73
+ return parsed;
74
+ }
75
+ } catch {
76
+ return null;
77
+ }
78
+ return null;
79
+ }
80
+ function slotIsStale(record, staleMs = DEFAULT_HEAVY_VERIFICATION_STALE_MS) {
81
+ if (!record) return true;
82
+ if (!isPidAlive(record.pid)) return true;
83
+ const atMs = Date.parse(record.acquiredAt);
84
+ if (Number.isNaN(atMs)) return true;
85
+ return Date.now() - atMs > staleMs;
86
+ }
87
+ function reclaimStaleSlot(filePath, staleMs) {
88
+ const record = readSlotRecord(filePath);
89
+ if (!slotIsStale(record, staleMs)) return;
90
+ try {
91
+ unlinkSync(filePath);
92
+ } catch {
93
+ }
94
+ }
95
+ function ensureSlotsDir(slotsDir) {
96
+ mkdirSync2(slotsDir, { recursive: true });
97
+ return slotsDir;
98
+ }
99
+ function reclaimStaleHeavyVerificationSlots(opts = {}) {
100
+ const slotsDir = ensureSlotsDir(opts.slotsDir ?? ensureHeavyVerificationDirs());
101
+ const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;
102
+ let reclaimed = 0;
103
+ for (const name of readdirSync(slotsDir)) {
104
+ if (!name.endsWith(".json")) continue;
105
+ const filePath = path3.join(slotsDir, name);
106
+ const before = existsSync(filePath);
107
+ reclaimStaleSlot(filePath, staleMs);
108
+ if (before && !existsSync(filePath)) reclaimed += 1;
109
+ }
110
+ return reclaimed;
111
+ }
112
+ function listActiveHeavyVerificationSlots(opts = {}) {
113
+ const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();
114
+ const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;
115
+ reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });
116
+ const active = [];
117
+ for (const name of readdirSync(slotsDir)) {
118
+ if (!name.endsWith(".json")) continue;
119
+ const record = readSlotRecord(path3.join(slotsDir, name));
120
+ if (record && !slotIsStale(record, staleMs)) active.push(record);
121
+ }
122
+ return active;
123
+ }
124
+ function countActiveHeavyVerificationSlots(opts = {}) {
125
+ return listActiveHeavyVerificationSlots(opts).length;
126
+ }
127
+ function assessHeavyVerificationGate(command, opts = {}) {
128
+ if (isHeavyVerificationGateSkipped()) {
129
+ return {
130
+ admitted: true,
131
+ slotId: null,
132
+ activeSlots: 0,
133
+ maxSlots: resolveHeavyVerificationMaxConcurrent(),
134
+ reason: null
135
+ };
136
+ }
137
+ const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();
138
+ const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;
139
+ const maxSlots = opts.maxSlots ?? resolveHeavyVerificationMaxConcurrent();
140
+ reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });
141
+ const activeSlots = countActiveHeavyVerificationSlots({ slotsDir, staleMs });
142
+ const admitted = activeSlots < maxSlots;
143
+ return {
144
+ admitted,
145
+ slotId: null,
146
+ activeSlots,
147
+ maxSlots,
148
+ reason: admitted ? null : `heavy verification at capacity (${activeSlots}/${maxSlots} slots); waiting for ${command}`
149
+ };
150
+ }
151
+
152
+ // src/worker-env.ts
153
+ var FORBIDDEN_WORKER_ENV_KEYS = [
154
+ "ANTHROPIC_API_KEY",
155
+ "ANALYST_API_KEY",
156
+ "RECRUITER_API_KEY",
157
+ "AUTH_SECRET",
158
+ "NEXTAUTH_SECRET",
159
+ "DATABASE_URL",
160
+ "PRODUCTION_DATABASE_URL",
161
+ "KYNVER_PRODUCTION_DATABASE_URL",
162
+ "REDIS_URL",
163
+ "GOOGLE_CLIENT_SECRET",
164
+ "GITHUB_CLIENT_SECRET",
165
+ "KYNVER_API_KEY",
166
+ "KYNVER_SERVICE_SECRET",
167
+ "KYNVER_RUNTIME_SECRET",
168
+ "KYNVER_CRON_SECRET",
169
+ "OPENCLAW_CRON_SECRET",
170
+ "QSTASH_TOKEN",
171
+ "QSTASH_CURRENT_SIGNING_KEY",
172
+ "QSTASH_NEXT_SIGNING_KEY",
173
+ "TOOL_SECRETS_KEK",
174
+ "TOOL_EXECUTOR_DISPATCH_SECRET",
175
+ "CLOUDFLARE_API_TOKEN",
176
+ "STRIPE_SECRET_KEY",
177
+ "STRIPE_WEBHOOK_SECRET",
178
+ "STRIPE_IDENTITY_WEBHOOK_SECRET",
179
+ "VOYAGE_API_KEY",
180
+ "PERPLEXITY_API_KEY",
181
+ "FRED_API_KEY",
182
+ "FMP_API_KEY",
183
+ "CURSOR_API_KEY"
184
+ ];
185
+ var FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
186
+
187
+ // src/memory-cost-package-version-guard.ts
188
+ var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
189
+ "@kynver-app/runtime": "0.1.83",
190
+ "@kynver-app/openclaw-agent-os": "0.1.43",
191
+ "@kynver-app/mcp-agent-os": "0.3.34"
192
+ };
193
+ var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
194
+ MEMORY_COST_PACKAGE_MIN_VERSIONS
195
+ );
196
+ function parseSemverParts(version) {
197
+ const core = version.trim().split("-")[0]?.split("+")[0];
198
+ if (!core) return null;
199
+ const parts = core.split(".");
200
+ if (parts.length < 1 || parts.length > 3) return null;
201
+ const nums = parts.map((p) => Number.parseInt(p, 10));
202
+ if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
203
+ while (nums.length < 3) nums.push(0);
204
+ return [nums[0], nums[1], nums[2]];
205
+ }
206
+ function compareSemver(a, b) {
207
+ const pa = parseSemverParts(a);
208
+ const pb = parseSemverParts(b);
209
+ if (!pa || !pb) return 0;
210
+ for (let i = 0; i < 3; i += 1) {
211
+ if (pa[i] > pb[i]) return 1;
212
+ if (pa[i] < pb[i]) return -1;
213
+ }
214
+ return 0;
215
+ }
216
+ export {
217
+ assessHeavyVerificationGate,
218
+ compareSemver,
219
+ countActiveHeavyVerificationSlots,
220
+ isHeavyVerificationGateSkipped,
221
+ resolveHeavyVerificationMaxConcurrent
222
+ };
223
+ //# sourceMappingURL=heavy-verification.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/heavy-verification/slot.ts", "../../src/util.ts", "../../src/heavy-verification/paths.ts", "../../src/plan-persist/paths.ts", "../../src/worker-env.ts", "../../src/memory-cost-package-version-guard.ts"],
4
+ "sourcesContent": ["import {\r\n closeSync,\r\n existsSync,\r\n mkdirSync,\r\n openSync,\r\n readdirSync,\r\n readFileSync,\r\n unlinkSync,\r\n writeFileSync,\r\n} from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { isPidAlive } from \"../util.js\";\r\nimport { ensureHeavyVerificationDirs, heavyVerificationSlotsDir } from \"./paths.js\";\r\n\r\n/** Reclaim slots held by dead PIDs or long-running orphans. */\r\nexport const DEFAULT_HEAVY_VERIFICATION_STALE_MS = 2 * 60 * 60_000;\r\n\r\n/** Default global cap \u2014 serialize typecheck/build across harness workers. */\r\nexport const DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT = 1;\r\n\r\nexport interface HeavyVerificationSlotRecord {\r\n slotId: string;\r\n pid: number;\r\n acquiredAt: string;\r\n command: string;\r\n}\r\n\r\nexport interface HeavyVerificationGateVerdict {\r\n admitted: boolean;\r\n slotId: string | null;\r\n activeSlots: number;\r\n maxSlots: number;\r\n reason: string | null;\r\n}\r\n\r\nfunction positiveInt(value: unknown, fallback: number): number {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || n <= 0) return fallback;\r\n return Math.floor(n);\r\n}\r\n\r\nexport function isHeavyVerificationGateSkipped(): boolean {\r\n const v = process.env.KYNVER_HEAVY_VERIFICATION_SKIP?.trim().toLowerCase();\r\n return v === \"1\" || v === \"true\" || v === \"yes\";\r\n}\r\n\r\nexport function resolveHeavyVerificationMaxConcurrent(): number {\r\n const env = process.env.KYNVER_HEAVY_VERIFICATION_MAX_CONCURRENT;\r\n if (env) return positiveInt(env, DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT);\r\n return DEFAULT_HEAVY_VERIFICATION_MAX_CONCURRENT;\r\n}\r\n\r\nfunction indexedSlotId(index: number): string {\r\n return `slot-${index}`;\r\n}\r\n\r\nfunction slotFilePath(slotId: string, slotsDir = heavyVerificationSlotsDir()): string {\r\n return path.join(slotsDir, `${slotId}.json`);\r\n}\r\n\r\nfunction readSlotRecord(filePath: string): HeavyVerificationSlotRecord | null {\r\n if (!existsSync(filePath)) return null;\r\n try {\r\n const parsed = JSON.parse(readFileSync(filePath, \"utf8\")) as HeavyVerificationSlotRecord;\r\n if (\r\n typeof parsed.slotId === \"string\" &&\r\n typeof parsed.pid === \"number\" &&\r\n typeof parsed.acquiredAt === \"string\" &&\r\n typeof parsed.command === \"string\"\r\n ) {\r\n return parsed;\r\n }\r\n } catch {\r\n return null;\r\n }\r\n return null;\r\n}\r\n\r\nfunction slotIsStale(\r\n record: HeavyVerificationSlotRecord | null,\r\n staleMs = DEFAULT_HEAVY_VERIFICATION_STALE_MS,\r\n): boolean {\r\n if (!record) return true;\r\n if (!isPidAlive(record.pid)) return true;\r\n const atMs = Date.parse(record.acquiredAt);\r\n if (Number.isNaN(atMs)) return true;\r\n return Date.now() - atMs > staleMs;\r\n}\r\n\r\nfunction reclaimStaleSlot(filePath: string, staleMs: number): void {\r\n const record = readSlotRecord(filePath);\r\n if (!slotIsStale(record, staleMs)) return;\r\n try {\r\n unlinkSync(filePath);\r\n } catch {\r\n /* best-effort */\r\n }\r\n}\r\n\r\nfunction ensureSlotsDir(slotsDir: string): string {\r\n mkdirSync(slotsDir, { recursive: true });\r\n return slotsDir;\r\n}\r\n\r\n/** Remove dead/orphan slot files before admission attempts. */\r\nexport function reclaimStaleHeavyVerificationSlots(\r\n opts: { slotsDir?: string; staleMs?: number } = {},\r\n): number {\r\n const slotsDir = ensureSlotsDir(opts.slotsDir ?? ensureHeavyVerificationDirs());\r\n const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;\r\n let reclaimed = 0;\r\n for (const name of readdirSync(slotsDir)) {\r\n if (!name.endsWith(\".json\")) continue;\r\n const filePath = path.join(slotsDir, name);\r\n const before = existsSync(filePath);\r\n reclaimStaleSlot(filePath, staleMs);\r\n if (before && !existsSync(filePath)) reclaimed += 1;\r\n }\r\n return reclaimed;\r\n}\r\n\r\nexport function listActiveHeavyVerificationSlots(\r\n opts: { slotsDir?: string; staleMs?: number } = {},\r\n): HeavyVerificationSlotRecord[] {\r\n const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();\r\n const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;\r\n reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });\r\n const active: HeavyVerificationSlotRecord[] = [];\r\n for (const name of readdirSync(slotsDir)) {\r\n if (!name.endsWith(\".json\")) continue;\r\n const record = readSlotRecord(path.join(slotsDir, name));\r\n if (record && !slotIsStale(record, staleMs)) active.push(record);\r\n }\r\n return active;\r\n}\r\n\r\nexport function countActiveHeavyVerificationSlots(\r\n opts: { slotsDir?: string; staleMs?: number } = {},\r\n): number {\r\n return listActiveHeavyVerificationSlots(opts).length;\r\n}\r\n\r\n/**\r\n * Try to acquire one heavy-verification slot using fixed index files (`slot-0.json`, \u2026)\r\n * and exclusive `wx` create. Avoids count-then-UUID TOCTOU races under burst dispatch.\r\n */\r\nexport function tryAcquireHeavyVerificationSlot(\r\n command: string,\r\n opts: { slotsDir?: string; staleMs?: number; maxSlots?: number } = {},\r\n): HeavyVerificationGateVerdict {\r\n if (isHeavyVerificationGateSkipped()) {\r\n return {\r\n admitted: true,\r\n slotId: null,\r\n activeSlots: 0,\r\n maxSlots: resolveHeavyVerificationMaxConcurrent(),\r\n reason: null,\r\n };\r\n }\r\n\r\n const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();\r\n const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;\r\n const maxSlots = opts.maxSlots ?? resolveHeavyVerificationMaxConcurrent();\r\n reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });\r\n\r\n for (let index = 0; index < maxSlots; index += 1) {\r\n const slotId = indexedSlotId(index);\r\n const filePath = slotFilePath(slotId, slotsDir);\r\n const existing = readSlotRecord(filePath);\r\n if (existing && slotIsStale(existing, staleMs)) {\r\n try {\r\n unlinkSync(filePath);\r\n } catch {\r\n /* best-effort */\r\n }\r\n } else if (existing && !slotIsStale(existing, staleMs)) {\r\n continue;\r\n }\r\n\r\n const record: HeavyVerificationSlotRecord = {\r\n slotId,\r\n pid: process.pid,\r\n acquiredAt: new Date().toISOString(),\r\n command,\r\n };\r\n\r\n try {\r\n const fd = openSync(filePath, \"wx\");\r\n writeFileSync(fd, JSON.stringify(record, null, 2), \"utf8\");\r\n closeSync(fd);\r\n const activeSlots = countActiveHeavyVerificationSlots({ slotsDir, staleMs });\r\n return {\r\n admitted: true,\r\n slotId,\r\n activeSlots,\r\n maxSlots,\r\n reason: null,\r\n };\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\r\n continue;\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n const activeSlots = countActiveHeavyVerificationSlots({ slotsDir, staleMs });\r\n return {\r\n admitted: false,\r\n slotId: null,\r\n activeSlots,\r\n maxSlots,\r\n reason: `heavy verification at capacity (${activeSlots}/${maxSlots} slots)`,\r\n };\r\n}\r\n\r\nexport function releaseHeavyVerificationSlot(\r\n slotId: string | null | undefined,\r\n opts: { slotsDir?: string } = {},\r\n): void {\r\n if (!slotId) return;\r\n const filePath = slotFilePath(slotId, opts.slotsDir ?? heavyVerificationSlotsDir());\r\n try {\r\n unlinkSync(filePath);\r\n } catch {\r\n /* ignore */\r\n }\r\n}\r\n\r\nexport function assessHeavyVerificationGate(\r\n command: string,\r\n opts: { slotsDir?: string; staleMs?: number; maxSlots?: number } = {},\r\n): HeavyVerificationGateVerdict {\r\n if (isHeavyVerificationGateSkipped()) {\r\n return {\r\n admitted: true,\r\n slotId: null,\r\n activeSlots: 0,\r\n maxSlots: resolveHeavyVerificationMaxConcurrent(),\r\n reason: null,\r\n };\r\n }\r\n const slotsDir = opts.slotsDir ?? ensureHeavyVerificationDirs();\r\n const staleMs = opts.staleMs ?? DEFAULT_HEAVY_VERIFICATION_STALE_MS;\r\n const maxSlots = opts.maxSlots ?? resolveHeavyVerificationMaxConcurrent();\r\n reclaimStaleHeavyVerificationSlots({ slotsDir, staleMs });\r\n const activeSlots = countActiveHeavyVerificationSlots({ slotsDir, staleMs });\r\n const admitted = activeSlots < maxSlots;\r\n return {\r\n admitted,\r\n slotId: null,\r\n activeSlots,\r\n maxSlots,\r\n reason: admitted\r\n ? null\r\n : `heavy verification at capacity (${activeSlots}/${maxSlots} slots); waiting for ${command}`,\r\n };\r\n}\r\n", "import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from \"node:fs\";\r\nimport path from \"node:path\";\r\n\r\nexport function fail(message: string): never {\r\n console.error(message);\r\n process.exit(1);\r\n}\r\n\r\n/** Avoid flashing a visible console on Windows when spawning worker/sidecar children. */\r\nexport function hiddenSpawnOptions<T extends Record<string, unknown>>(opts: T): T {\r\n if (process.platform !== \"win32\") return opts;\r\n return { windowsHide: true, ...opts };\r\n}\r\n\r\nexport function required(value: string | undefined, name: string): string {\r\n if (!value) fail(`missing ${name}`);\r\n return value;\r\n}\r\n\r\nexport function safeJson(line: string): unknown {\r\n try {\r\n return JSON.parse(line);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function readJson<T>(file: string, fallback?: T): T {\r\n try {\r\n return JSON.parse(readFileSync(file, \"utf8\")) as T;\r\n } catch (error) {\r\n if (arguments.length > 1) return fallback as T;\r\n fail(`failed to read ${file}: ${(error as Error).message}`);\r\n }\r\n}\r\n\r\nexport function writeJson(file: string, value: unknown): void {\r\n mkdirSync(path.dirname(file), { recursive: true });\r\n writeFileSync(file, `${JSON.stringify(value, null, 2)}\\n`);\r\n}\r\n\r\nexport function safeSlug(value: string | undefined): string {\r\n return (\r\n String(value || \"\")\r\n .toLowerCase()\r\n .replace(/[^a-z0-9._-]+/g, \"-\")\r\n .replace(/^-+|-+$/g, \"\") || \"worker\"\r\n );\r\n}\r\n\r\nexport function timestampSlug(name: string): string {\r\n return safeSlug(`${new Date().toISOString().replace(/[-:]/g, \"\").replace(/\\..+/, \"Z\")}-${name}`);\r\n}\r\n\r\nexport function splitCsv(value: string | undefined): string[] {\r\n return value ? String(value).split(\",\").map((item) => item.trim()).filter(Boolean) : [];\r\n}\r\n\r\nexport function trimTrailingSlash(url: string): string {\r\n return String(url).replace(/\\/+$/, \"\");\r\n}\r\n\r\nexport function oneLine(value: string): string {\r\n return String(value || \"\")\r\n .replace(/\\s+/g, \" \")\r\n .trim();\r\n}\r\n\r\nexport function fileSize(file: string): number {\r\n try {\r\n return statSync(file).size;\r\n } catch {\r\n return 0;\r\n }\r\n}\r\n\r\nexport function fileMtime(file: string): string | null {\r\n try {\r\n return statSync(file).mtime.toISOString();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function tailFile(file: string, lines: number): string {\r\n if (!existsSync(file)) return \"\";\r\n const data = readFileSync(file, \"utf8\");\r\n return data.split(\"\\n\").slice(-lines).join(\"\\n\");\r\n}\r\n\r\nexport function readMaybeFile(file: string | undefined): string {\r\n return file ? readFileSync(path.resolve(file), \"utf8\") : \"\";\r\n}\r\n\r\nexport function listRunIds(runsDir: string): string[] {\r\n if (!existsSync(runsDir)) return [];\r\n return readdirSync(runsDir, { withFileTypes: true })\r\n .filter((entry) => entry.isDirectory())\r\n .map((entry) => entry.name);\r\n}\r\n\r\nexport function sleepMs(ms: number): void {\r\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\r\n}\r\n\r\n/** Non-blocking sleep for async loops (daemon backoff, interruptible shutdown). */\r\nexport function sleepMsAsync(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\nexport function isPidAlive(pid: number | undefined): boolean {\r\n if (!pid) return false;\r\n try {\r\n process.kill(pid, 0);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport function killWorkerProcess(pid: number, signal: NodeJS.Signals): void {\r\n try {\r\n process.kill(-pid, signal);\r\n } catch {\r\n process.kill(pid, signal);\r\n }\r\n}\r\n\r\nexport function latestIso(values: Array<string | null | undefined>): string | null {\r\n let best: string | null = null;\r\n let bestMs = -Infinity;\r\n for (const value of values) {\r\n if (!value) continue;\r\n const ms = Date.parse(value);\r\n if (Number.isFinite(ms) && ms > bestMs) {\r\n bestMs = ms;\r\n best = value;\r\n }\r\n }\r\n return best;\r\n}\r\n\r\nexport function secsAgo(ms: number): number {\r\n return Math.max(0, Math.round((Date.now() - ms) / 1000));\r\n}\r\n", "import { mkdirSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport path from \"node:path\";\r\nimport { resolveKynverStateRoot } from \"../plan-persist/paths.js\";\r\n\r\nexport function resolveHeavyVerificationRoot(): string {\r\n return path.join(resolveKynverStateRoot(), \"heavy-verification\");\r\n}\r\n\r\nexport function heavyVerificationSlotsDir(): string {\r\n return path.join(resolveHeavyVerificationRoot(), \"slots\");\r\n}\r\n\r\nexport function ensureHeavyVerificationDirs(): string {\r\n const dir = heavyVerificationSlotsDir();\r\n mkdirSync(dir, { recursive: true });\r\n return dir;\r\n}\r\n", "import { existsSync, mkdirSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport path from \"node:path\";\r\n\r\nexport function resolveKynverStateRoot(): string {\r\n const env = process.env.KYNVER_STATE_ROOT;\r\n if (env) return path.resolve(env);\r\n return path.join(homedir(), \".kynver\", \"state\");\r\n}\r\n\r\nexport function planOutboxDir(): string {\r\n return path.join(resolveKynverStateRoot(), \"plan-outbox\");\r\n}\r\n\r\nexport function planOutboxArchiveDir(): string {\r\n return path.join(resolveKynverStateRoot(), \"plan-outbox-archive\");\r\n}\r\n\r\nexport function ensurePlanOutboxDirs(): { outboxDir: string; archiveDir: string } {\r\n const outboxDir = planOutboxDir();\r\n const archiveDir = planOutboxArchiveDir();\r\n mkdirSync(outboxDir, { recursive: true });\r\n mkdirSync(archiveDir, { recursive: true });\r\n return { outboxDir, archiveDir };\r\n}\r\n\r\nexport function isTmpOnlyPath(filePath: string): boolean {\r\n // Detect literal POSIX temp paths first \u2014 on Windows, path.resolve(\"/tmp/x\")\r\n // rewrites to \"C:\\tmp\\x\" and would no longer match, so a /tmp-only path would\r\n // wrongly read as durable. Check the raw string before resolving.\r\n if (filePath.startsWith(\"/tmp/\") || filePath.startsWith(\"/var/folders/\")) return true;\r\n const resolved = path.resolve(filePath);\r\n return resolved.startsWith(\"/tmp/\") || resolved.startsWith(path.join(\"/var\", \"folders\"));\r\n}\r\n", "/**\r\n * Worker spawn env scrub \u2014 harness workers must not inherit host deployment secrets.\r\n */\r\n\r\n/** Exact env keys that must never reach a worker child process. */\r\nexport const FORBIDDEN_WORKER_ENV_KEYS = [\r\n \"ANTHROPIC_API_KEY\",\r\n \"ANALYST_API_KEY\",\r\n \"RECRUITER_API_KEY\",\r\n \"AUTH_SECRET\",\r\n \"NEXTAUTH_SECRET\",\r\n \"DATABASE_URL\",\r\n \"PRODUCTION_DATABASE_URL\",\r\n \"KYNVER_PRODUCTION_DATABASE_URL\",\r\n \"REDIS_URL\",\r\n \"GOOGLE_CLIENT_SECRET\",\r\n \"GITHUB_CLIENT_SECRET\",\r\n \"KYNVER_API_KEY\",\r\n \"KYNVER_SERVICE_SECRET\",\r\n \"KYNVER_RUNTIME_SECRET\",\r\n \"KYNVER_CRON_SECRET\",\r\n \"OPENCLAW_CRON_SECRET\",\r\n \"QSTASH_TOKEN\",\r\n \"QSTASH_CURRENT_SIGNING_KEY\",\r\n \"QSTASH_NEXT_SIGNING_KEY\",\r\n \"TOOL_SECRETS_KEK\",\r\n \"TOOL_EXECUTOR_DISPATCH_SECRET\",\r\n \"CLOUDFLARE_API_TOKEN\",\r\n \"STRIPE_SECRET_KEY\",\r\n \"STRIPE_WEBHOOK_SECRET\",\r\n \"STRIPE_IDENTITY_WEBHOOK_SECRET\",\r\n \"VOYAGE_API_KEY\",\r\n \"PERPLEXITY_API_KEY\",\r\n \"FRED_API_KEY\",\r\n \"FMP_API_KEY\",\r\n \"CURSOR_API_KEY\",\r\n] as const;\r\n\r\nconst FORBIDDEN_KEY_SET = new Set<string>(FORBIDDEN_WORKER_ENV_KEYS);\r\n\r\n/** Keys matching these suffixes are stripped (case-sensitive). */\r\nconst FORBIDDEN_SUFFIXES = [\"_SECRET\", \"_API_KEY\"] as const;\r\n\r\nexport function isForbiddenWorkerEnvKey(key: string): boolean {\r\n if (FORBIDDEN_KEY_SET.has(key)) return true;\r\n return FORBIDDEN_SUFFIXES.some((suffix) => key.endsWith(suffix));\r\n}\r\n\r\nexport function listForbiddenWorkerEnvKeys(env: NodeJS.ProcessEnv): string[] {\r\n return Object.keys(env).filter(isForbiddenWorkerEnvKey).sort();\r\n}\r\n\r\nexport function scrubWorkerEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\r\n const next = { ...env };\r\n for (const key of Object.keys(next)) {\r\n if (isForbiddenWorkerEnvKey(key)) delete next[key];\r\n }\r\n return next;\r\n}\r\n\r\nexport interface WorkerEnvAudit {\r\n forbiddenPresent: string[];\r\n safe: boolean;\r\n}\r\n\r\nexport function auditWorkerEnv(env: NodeJS.ProcessEnv): WorkerEnvAudit {\r\n const forbiddenPresent = listForbiddenWorkerEnvKeys(env);\r\n return { forbiddenPresent, safe: forbiddenPresent.length === 0 };\r\n}\r\n\r\n/** @deprecated Use {@link scrubWorkerEnv} \u2014 kept for existing imports from git.ts */\r\nexport function scrubClaudeEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\r\n return scrubWorkerEnv(env);\r\n}\r\n", "import { existsSync, readFileSync } from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { discoverDefaultRepo } from \"./default-repo-discovery.js\";\r\n\r\n/** Minimum versions that ship MARM memory cost controls (PR #1159). */\r\nexport const MEMORY_COST_PACKAGE_MIN_VERSIONS = {\r\n \"@kynver-app/runtime\": \"0.1.83\",\r\n \"@kynver-app/openclaw-agent-os\": \"0.1.43\",\r\n \"@kynver-app/mcp-agent-os\": \"0.3.34\",\r\n} as const;\r\n\r\nexport type MemoryCostManagedPackageName = keyof typeof MEMORY_COST_PACKAGE_MIN_VERSIONS;\r\n\r\nexport const MEMORY_COST_MANAGED_PACKAGES = Object.keys(\r\n MEMORY_COST_PACKAGE_MIN_VERSIONS,\r\n) as MemoryCostManagedPackageName[];\r\n\r\nexport type MemoryCostVersionSource = \"self\" | \"installed\" | \"repo\" | \"unknown\";\r\n\r\nexport interface MemoryCostPackageVersionCandidate {\r\n version: string;\r\n source: MemoryCostVersionSource;\r\n path?: string;\r\n}\r\n\r\nexport interface MemoryCostPackageGuardRow {\r\n packageName: MemoryCostManagedPackageName;\r\n displayName: string;\r\n minimumVersion: string;\r\n effectiveVersion: string | null;\r\n effectiveSource: MemoryCostVersionSource;\r\n ok: boolean;\r\n summary: string;\r\n remediation: string[];\r\n}\r\n\r\nexport interface MemoryCostPackageGuardResult {\r\n ok: boolean;\r\n summary: string;\r\n packages: MemoryCostPackageGuardRow[];\r\n}\r\n\r\nconst DISPLAY_NAMES: Record<MemoryCostManagedPackageName, string> = {\r\n \"@kynver-app/runtime\": \"Kynver runtime\",\r\n \"@kynver-app/openclaw-agent-os\": \"OpenClaw AgentOS plugin\",\r\n \"@kynver-app/mcp-agent-os\": \"AgentOS MCP server\",\r\n};\r\n\r\nconst REPO_PACKAGE_JSON_RELATIVE: Record<MemoryCostManagedPackageName, string> = {\r\n \"@kynver-app/runtime\": \"packages/kynver-runtime/package.json\",\r\n \"@kynver-app/openclaw-agent-os\": \"packages/kynver-openclaw-agent-os/package.json\",\r\n \"@kynver-app/mcp-agent-os\": \"packages/kynver-mcp-agent-os/package.json\",\r\n};\r\n\r\n/** Parse `major.minor.patch`; pre-release/build suffixes are ignored. */\r\nexport function parseSemverParts(version: string): [number, number, number] | null {\r\n const core = version.trim().split(\"-\")[0]?.split(\"+\")[0];\r\n if (!core) return null;\r\n const parts = core.split(\".\");\r\n if (parts.length < 1 || parts.length > 3) return null;\r\n const nums = parts.map((p) => Number.parseInt(p, 10));\r\n if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;\r\n while (nums.length < 3) nums.push(0);\r\n return [nums[0]!, nums[1]!, nums[2]!];\r\n}\r\n\r\n/** Returns 1 if a > b, -1 if a < b, 0 if equal or either unparsable. */\r\nexport function compareSemver(a: string, b: string): number {\r\n const pa = parseSemverParts(a);\r\n const pb = parseSemverParts(b);\r\n if (!pa || !pb) return 0;\r\n for (let i = 0; i < 3; i += 1) {\r\n if (pa[i]! > pb[i]!) return 1;\r\n if (pa[i]! < pb[i]!) return -1;\r\n }\r\n return 0;\r\n}\r\n\r\nexport function semverAtLeast(version: string, minimum: string): boolean {\r\n return compareSemver(version, minimum) >= 0;\r\n}\r\n\r\nfunction maxSemver(versions: readonly string[]): string | null {\r\n let best: string | null = null;\r\n for (const version of versions) {\r\n if (!best || compareSemver(version, best) > 0) best = version;\r\n }\r\n return best;\r\n}\r\n\r\nfunction readPackageJsonVersion(packageJsonPath: string): string | null {\r\n try {\r\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { version?: unknown };\r\n return typeof parsed.version === \"string\" && parsed.version.trim() ? parsed.version.trim() : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction resolveRepoRoot(cwd: string, explicitRepoRoot?: string): string | null {\r\n const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(\r\n (value): value is string => Boolean(value?.trim()),\r\n );\r\n for (const candidate of candidates) {\r\n const resolved = path.resolve(candidate);\r\n if (\r\n existsSync(path.join(resolved, \"packages/kynver-runtime/package.json\")) &&\r\n existsSync(path.join(resolved, \"package.json\"))\r\n ) {\r\n return resolved;\r\n }\r\n }\r\n const discovered = discoverDefaultRepo({ cwd });\r\n return discovered?.repo ?? null;\r\n}\r\n\r\nexport function probeRepoPackageVersions(input: {\r\n cwd?: string;\r\n repoRoot?: string;\r\n} = {}): Partial<Record<MemoryCostManagedPackageName, MemoryCostPackageVersionCandidate>> {\r\n const cwd = input.cwd ?? process.cwd();\r\n const repoRoot = resolveRepoRoot(cwd, input.repoRoot);\r\n if (!repoRoot) return {};\r\n\r\n const out: Partial<Record<MemoryCostManagedPackageName, MemoryCostPackageVersionCandidate>> = {};\r\n for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {\r\n const packageJsonPath = path.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);\r\n const version = readPackageJsonVersion(packageJsonPath);\r\n if (!version) continue;\r\n out[packageName] = { version, source: \"repo\", path: packageJsonPath };\r\n }\r\n return out;\r\n}\r\n\r\nfunction repoSourceCommands(packageName: MemoryCostManagedPackageName): string[] {\r\n if (packageName === \"@kynver-app/runtime\") {\r\n return [\"npm run kynver:build\", \"npm run kynver\"];\r\n }\r\n return [`npm run build -w ${packageName}`];\r\n}\r\n\r\nfunction buildRemediation(input: {\r\n packageName: MemoryCostManagedPackageName;\r\n minimumVersion: string;\r\n effectiveVersion: string | null;\r\n effectiveSource: MemoryCostVersionSource;\r\n repoVersion: string | null;\r\n}): string[] {\r\n const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;\r\n const lines: string[] = [];\r\n if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {\r\n lines.push(\r\n `Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join(\"; \")}.`,\r\n );\r\n lines.push(\"Do not publish npm packages or wait on an operator release.\");\r\n return lines;\r\n }\r\n if (effectiveVersion) {\r\n lines.push(\r\n `Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`,\r\n );\r\n } else {\r\n lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);\r\n }\r\n if (packageName === \"@kynver-app/runtime\") {\r\n lines.push(\"Repo-source alternative: npm run kynver:build && npm run kynver\");\r\n }\r\n if (effectiveSource === \"installed\" && repoVersion) {\r\n lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);\r\n }\r\n return lines;\r\n}\r\n\r\nfunction pickEffectiveCandidate(\r\n candidates: MemoryCostPackageVersionCandidate[],\r\n): { version: string | null; source: MemoryCostVersionSource } {\r\n if (candidates.length === 0) return { version: null, source: \"unknown\" };\r\n const best = maxSemver(candidates.map((candidate) => candidate.version));\r\n if (!best) return { version: null, source: \"unknown\" };\r\n const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0]!;\r\n return { version: winner.version, source: winner.source };\r\n}\r\n\r\nexport function evaluateMemoryCostPackageVersionGuard(input: {\r\n installed?: Partial<Record<MemoryCostManagedPackageName, string | MemoryCostPackageVersionCandidate>>;\r\n repo?: Partial<Record<MemoryCostManagedPackageName, string | MemoryCostPackageVersionCandidate>>;\r\n self?: Partial<Record<MemoryCostManagedPackageName, string | MemoryCostPackageVersionCandidate>>;\r\n} = {}): MemoryCostPackageGuardResult {\r\n const normalize = (\r\n value: string | MemoryCostPackageVersionCandidate | undefined,\r\n fallbackSource: MemoryCostVersionSource,\r\n ): MemoryCostPackageVersionCandidate | null => {\r\n if (!value) return null;\r\n if (typeof value === \"string\") return { version: value, source: fallbackSource };\r\n return value;\r\n };\r\n\r\n const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName): MemoryCostPackageGuardRow => {\r\n const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];\r\n const candidates: MemoryCostPackageVersionCandidate[] = [];\r\n const installed = normalize(input.installed?.[packageName], \"installed\");\r\n const repo = normalize(input.repo?.[packageName], \"repo\");\r\n const self = normalize(input.self?.[packageName], \"self\");\r\n if (installed) candidates.push(installed);\r\n if (repo) candidates.push(repo);\r\n if (self) candidates.push(self);\r\n\r\n const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);\r\n const repoVersion = repo?.version ?? null;\r\n const ok = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;\r\n const remediation = ok\r\n ? []\r\n : buildRemediation({\r\n packageName,\r\n minimumVersion,\r\n effectiveVersion,\r\n effectiveSource,\r\n repoVersion,\r\n });\r\n\r\n const summary = ok\r\n ? `${DISPLAY_NAMES[packageName]} ${effectiveVersion} meets memory-cost minimum ${minimumVersion} (${effectiveSource}).`\r\n : `${DISPLAY_NAMES[packageName]} is below memory-cost minimum ${minimumVersion}` +\r\n (effectiveVersion ? ` (effective ${effectiveVersion} via ${effectiveSource})` : \" (no version detected)\") +\r\n \".\";\r\n\r\n return {\r\n packageName,\r\n displayName: DISPLAY_NAMES[packageName],\r\n minimumVersion,\r\n effectiveVersion,\r\n effectiveSource,\r\n ok,\r\n summary,\r\n remediation,\r\n };\r\n });\r\n\r\n const violations = packages.filter((row) => !row.ok);\r\n const ok = violations.length === 0;\r\n const summary = ok\r\n ? \"All managed AgentOS packages meet memory-cost minimum versions.\"\r\n : `Memory-cost package guard blocked ${violations.length} stale package(s): ${violations\r\n .map((row) => `${row.packageName} < ${row.minimumVersion}`)\r\n .join(\"; \")}.`;\r\n\r\n return { ok, summary, packages };\r\n}\r\n\r\nexport class MemoryCostPackageVersionGuardError extends Error {\r\n readonly result: MemoryCostPackageGuardResult;\r\n\r\n constructor(result: MemoryCostPackageGuardResult) {\r\n const lines = [\r\n result.summary,\r\n ...result.packages\r\n .filter((row) => !row.ok)\r\n .flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)]),\r\n ];\r\n super(lines.join(\"\\n\"));\r\n this.name = \"MemoryCostPackageVersionGuardError\";\r\n this.result = result;\r\n }\r\n}\r\n\r\nexport function assertMemoryCostPackageVersionGuard(\r\n input: Parameters<typeof evaluateMemoryCostPackageVersionGuard>[0] = {},\r\n): MemoryCostPackageGuardResult {\r\n const result = evaluateMemoryCostPackageVersionGuard(input);\r\n if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);\r\n return result;\r\n}\r\n\r\nexport function formatMemoryCostPackageGuardError(result: MemoryCostPackageGuardResult): string {\r\n return new MemoryCostPackageVersionGuardError(result).message;\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["mkdirSync", "path", "path", "path", "mkdirSync", "path"]
7
+ }