@gemslibe/rbo 0.2.0

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.
@@ -0,0 +1,814 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ../mcp-stdio/src/main.ts
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+
6
+ // ../mcp-stdio/src/proxy.ts
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+
9
+ // ../../packages/shared/dist/versions.js
10
+ var RBO_STDIO_ADAPTER_VERSION = "0.2.0";
11
+
12
+ // ../../packages/shared/dist/errors.js
13
+ import { z } from "zod";
14
+ var ErrorCategorySchema = z.enum([
15
+ "validation",
16
+ "no_matching_agent",
17
+ "no_capacity",
18
+ "source_scan",
19
+ "secret_blocked",
20
+ "repo_clone",
21
+ "repo_fetch",
22
+ "base_commit_missing",
23
+ "bundle_import",
24
+ "snapshot_transfer",
25
+ "snapshot_hash",
26
+ "materialization",
27
+ "workspace_changed",
28
+ "shell_missing",
29
+ "process_spawn",
30
+ "process_exit",
31
+ "timeout",
32
+ "cancelled",
33
+ "agent_lost",
34
+ "artifact_collection",
35
+ "artifact_upload",
36
+ "cleanup",
37
+ "secret_missing",
38
+ "toolchain_changed",
39
+ "agent_disconnected",
40
+ "lease_expired",
41
+ "log_spool_limit",
42
+ "internal"
43
+ ]);
44
+
45
+ // ../../packages/shared/dist/ids.js
46
+ import { ulid } from "ulid";
47
+
48
+ // ../../packages/shared/dist/paths.js
49
+ var WINDOWS_RESERVED_NAMES = /* @__PURE__ */ new Set([
50
+ "CON",
51
+ "PRN",
52
+ "AUX",
53
+ "NUL",
54
+ "COM1",
55
+ "COM2",
56
+ "COM3",
57
+ "COM4",
58
+ "COM5",
59
+ "COM6",
60
+ "COM7",
61
+ "COM8",
62
+ "COM9",
63
+ "LPT1",
64
+ "LPT2",
65
+ "LPT3",
66
+ "LPT4",
67
+ "LPT5",
68
+ "LPT6",
69
+ "LPT7",
70
+ "LPT8",
71
+ "LPT9"
72
+ ]);
73
+ function containsWindowsReservedName(pathStr) {
74
+ const normalized = pathStr.replace(/\\/g, "/");
75
+ for (const segment of normalized.split("/")) {
76
+ if (!segment)
77
+ continue;
78
+ const base = segment.includes(".") ? segment.slice(0, segment.indexOf(".")) : segment;
79
+ if (WINDOWS_RESERVED_NAMES.has(base.toUpperCase())) {
80
+ return true;
81
+ }
82
+ }
83
+ return false;
84
+ }
85
+ function isSafeRelativePath(value, options) {
86
+ const normalized = value.replace(/\\/g, "/");
87
+ if (normalized === "" || normalized === ".") {
88
+ return options?.allowDot === true;
89
+ }
90
+ if (normalized.startsWith("/") || normalized.startsWith("//") || normalized.startsWith("\\\\") || /^[a-zA-Z]:/.test(normalized) || normalized.includes("://")) {
91
+ return false;
92
+ }
93
+ const parts = normalized.split("/");
94
+ if (parts.some((part) => part === "" || part === "." || part === "..")) {
95
+ return false;
96
+ }
97
+ if (containsWindowsReservedName(normalized)) {
98
+ return false;
99
+ }
100
+ return true;
101
+ }
102
+
103
+ // ../../packages/shared/dist/controller-identity.js
104
+ import selfsigned from "selfsigned";
105
+ import { ulid as ulid2 } from "ulid";
106
+
107
+ // ../../packages/shared/dist/host-load.js
108
+ var DEFAULT_REFERENCE_CAPACITY_SCORE = 8 * 3e3;
109
+
110
+ // ../../packages/protocol/dist/schemas.js
111
+ import { z as z2 } from "zod";
112
+ var StructuredErrorSchema = z2.object({
113
+ category: ErrorCategorySchema,
114
+ message: z2.string(),
115
+ retryable: z2.boolean(),
116
+ details: z2.record(z2.string(), z2.unknown()).optional()
117
+ });
118
+ var JobStateSchema = z2.enum([
119
+ "created",
120
+ "awaiting_confirmation",
121
+ "queued",
122
+ "matching",
123
+ "leased",
124
+ "preparing_source",
125
+ "transferring_source",
126
+ "materializing",
127
+ "starting",
128
+ "running",
129
+ "orphaned",
130
+ "collecting_artifacts",
131
+ "cleaning",
132
+ "completed"
133
+ ]);
134
+ var JobOutcomeSchema = z2.enum(["succeeded", "failed", "timed_out", "cancelled", "lost"]);
135
+ var RiskLevelSchema = z2.enum(["safe", "normal", "destructive", "hardware"]);
136
+ var QueuePolicySchema = z2.enum(["local_fallback", "wait", "fail_fast"]);
137
+ var CompletionPolicySchema = z2.discriminatedUnion("type", [
138
+ z2.object({ type: z2.literal("run_to_exit") }),
139
+ z2.object({ type: z2.literal("run_for_duration"), duration_seconds: z2.number().positive() }),
140
+ z2.object({
141
+ type: z2.literal("run_until_log_match"),
142
+ success_pattern: z2.string().min(1),
143
+ failure_pattern: z2.string().min(1).optional(),
144
+ max_duration_seconds: z2.number().positive()
145
+ })
146
+ ]);
147
+ var ShellIdSchema = z2.enum(["bash", "zsh", "sh", "powershell", "pwsh", "cmd", "direct"]);
148
+ var ExecutionConfigSchema = z2.object({
149
+ shell: ShellIdSchema.default("bash"),
150
+ script: z2.string().min(1),
151
+ env: z2.record(z2.string(), z2.string()).default({}),
152
+ // §13.4: values come from the Agent-side named secret store, never through MCP.
153
+ secret_refs: z2.record(z2.string(), z2.string()).optional(),
154
+ timeout_seconds: z2.number().positive().default(3600),
155
+ idle_timeout_seconds: z2.number().positive().optional(),
156
+ cancel_grace_seconds: z2.number().positive().default(10),
157
+ cleanup_script: z2.string().optional(),
158
+ cleanup_timeout_seconds: z2.number().positive().default(60),
159
+ tty: z2.boolean().default(false),
160
+ completion: CompletionPolicySchema.default({ type: "run_to_exit" })
161
+ });
162
+ var JobAdditionalRootSchema = z2.object({
163
+ source_path: z2.string().min(1),
164
+ mount_path: z2.string().min(1).refine((value) => isSafeRelativePath(value), {
165
+ message: "mount_path must be a relative path without '..', absolute, or UNC segments"
166
+ }),
167
+ include: z2.array(z2.string()).default(["**/*"]),
168
+ exclude: z2.array(z2.string()).default([]),
169
+ mode: z2.enum(["read_only", "read_write"]).default("read_only")
170
+ });
171
+ var SourceConfigSchema = z2.object({
172
+ project_root: z2.string().min(1),
173
+ // Relative path only — no absolute paths or `..` segments (§28.2 isolation).
174
+ cwd: z2.string().default(".").refine((value) => isSafeRelativePath(value, { allowDot: true }), {
175
+ message: "cwd must be a relative path without '..' or absolute segments"
176
+ }),
177
+ additional_roots: z2.array(JobAdditionalRootSchema).default([])
178
+ });
179
+ var SourcePolicySchema = z2.object({
180
+ include_untracked: z2.boolean().default(true),
181
+ include_ignored: z2.array(z2.string()).default([]),
182
+ secret_policy: z2.enum(["block", "warn", "allow"]).default("block")
183
+ });
184
+ var RequirementsConfigSchema = z2.object({
185
+ os: z2.array(z2.string()).optional(),
186
+ arch: z2.array(z2.string()).optional(),
187
+ tools: z2.record(z2.string(), z2.string()).optional(),
188
+ labels: z2.record(z2.string(), z2.string()).optional(),
189
+ secret_refs: z2.array(z2.string()).optional(),
190
+ min_memory_mb: z2.number().positive().optional(),
191
+ min_disk_mb: z2.number().positive().optional()
192
+ });
193
+ var PreferencesConfigSchema = z2.object({
194
+ agent_ids: z2.array(z2.string()).optional(),
195
+ os_order: z2.array(z2.string()).optional(),
196
+ prefer_repo_cache: z2.boolean().default(true),
197
+ prefer_build_cache: z2.boolean().default(true),
198
+ allow_local_fallback: z2.boolean().default(true)
199
+ });
200
+ var ArtifactRuleSchema = z2.object({
201
+ glob: z2.string().min(1),
202
+ required: z2.boolean().default(false)
203
+ });
204
+ var JobRequestSchema = z2.object({
205
+ client_request_id: z2.string().min(1),
206
+ name: z2.string().optional(),
207
+ source: SourceConfigSchema,
208
+ execution: ExecutionConfigSchema,
209
+ requirements: RequirementsConfigSchema.optional(),
210
+ preferences: PreferencesConfigSchema.optional(),
211
+ queue_policy: QueuePolicySchema.default("local_fallback"),
212
+ risk_level: RiskLevelSchema.default("normal"),
213
+ intent: z2.string().nullable().optional(),
214
+ source_policy: SourcePolicySchema.optional(),
215
+ artifacts: z2.array(ArtifactRuleSchema).optional()
216
+ });
217
+ var jobEventBase = {
218
+ sequence: z2.number().int().positive(),
219
+ created_at: z2.string().min(1),
220
+ job_id: z2.string().min(1),
221
+ attempt_id: z2.string().min(1)
222
+ };
223
+ var JobEventSchema = z2.discriminatedUnion("type", [
224
+ z2.object({
225
+ type: z2.literal("state_transition"),
226
+ ...jobEventBase,
227
+ from_state: JobStateSchema,
228
+ to_state: JobStateSchema
229
+ }),
230
+ z2.object({
231
+ type: z2.literal("snapshot_captured"),
232
+ ...jobEventBase,
233
+ snapshot_id: z2.string().min(1),
234
+ content_id: z2.string().min(1)
235
+ }),
236
+ z2.object({
237
+ type: z2.literal("materialized"),
238
+ ...jobEventBase,
239
+ workspace: z2.string().min(1)
240
+ }),
241
+ z2.object({
242
+ type: z2.literal("process_started"),
243
+ ...jobEventBase,
244
+ workspace: z2.string().min(1),
245
+ pid: z2.number().int().positive().optional()
246
+ }),
247
+ z2.object({
248
+ type: z2.literal("artifact_collected"),
249
+ ...jobEventBase,
250
+ artifact_id: z2.string().min(1),
251
+ path: z2.string().min(1),
252
+ sha256: z2.string().min(1)
253
+ }),
254
+ z2.object({
255
+ type: z2.literal("artifact_skipped"),
256
+ ...jobEventBase,
257
+ path: z2.string().min(1),
258
+ reason: z2.string().min(1)
259
+ }),
260
+ z2.object({
261
+ type: z2.literal("artifact_limit_exceeded"),
262
+ ...jobEventBase,
263
+ reason: z2.enum(["file_count", "total_bytes"]),
264
+ limit: z2.number().int().positive(),
265
+ actual: z2.number().int().positive()
266
+ }),
267
+ z2.object({
268
+ type: z2.literal("secret_warning"),
269
+ ...jobEventBase,
270
+ path: z2.string().min(1),
271
+ reason: z2.string().min(1)
272
+ }),
273
+ z2.object({
274
+ type: z2.literal("env_override_ignored"),
275
+ ...jobEventBase,
276
+ name: z2.string().min(1),
277
+ reason: z2.string().min(1)
278
+ }),
279
+ z2.object({
280
+ type: z2.literal("cancel_requested"),
281
+ ...jobEventBase,
282
+ reason: z2.string().optional(),
283
+ signalled: z2.boolean()
284
+ }),
285
+ z2.object({
286
+ type: z2.literal("cleanup_error"),
287
+ ...jobEventBase,
288
+ exit_code: z2.number().int().nullable(),
289
+ timed_out: z2.boolean(),
290
+ message: z2.string().min(1)
291
+ }),
292
+ z2.object({
293
+ type: z2.literal("error"),
294
+ ...jobEventBase,
295
+ category: ErrorCategorySchema,
296
+ message: z2.string().min(1)
297
+ })
298
+ ]);
299
+ var ToolchainProfileSchema = z2.object({
300
+ id: z2.string(),
301
+ kind: z2.string(),
302
+ version: z2.string(),
303
+ platform: z2.string(),
304
+ activation: z2.object({
305
+ type: z2.enum(["source_script", "environment_variables", "path_prepend"]),
306
+ path: z2.string().optional(),
307
+ env: z2.record(z2.string(), z2.string()).optional()
308
+ }),
309
+ environment_fingerprint: z2.string()
310
+ });
311
+ var BuildCacheKindSchema = z2.enum(["ccache", "sccache", "npm", "pnpm", "pip"]);
312
+ var AgentCapabilityReportSchema = z2.object({
313
+ agent_id: z2.string(),
314
+ display_name: z2.string(),
315
+ hostname: z2.string(),
316
+ os: z2.object({
317
+ family: z2.enum(["macos", "windows", "linux"]),
318
+ version: z2.string(),
319
+ arch: z2.string()
320
+ }),
321
+ resources: z2.object({
322
+ cpu_logical: z2.number(),
323
+ memory_total_mb: z2.number(),
324
+ memory_free_mb: z2.number(),
325
+ disk_free_mb: z2.number(),
326
+ /**
327
+ * Agent-reported CPU busy fraction in [0, 1] for §19.2 scheduler scoring.
328
+ * Missing at schedule time is treated as 1 (pessimistic) by the Controller.
329
+ */
330
+ cpu_load: z2.number().min(0).max(1).optional(),
331
+ /** Additive Phase 6 capacity fields (bytes). */
332
+ disk_free_bytes: z2.number().nonnegative().optional(),
333
+ disk_min_free_bytes: z2.number().nonnegative().optional(),
334
+ disk_pressure: z2.boolean().optional(),
335
+ /**
336
+ * Primary-core clock speed (MHz) from os.cpus()[0].speed, for host-aware scheduling's
337
+ * capacity score (cpu_logical * cpu_speed_mhz). Optional — missing is treated as an
338
+ * unknown/lowest-priority capacity by the Controller, same spirit as cpu_load's pessimistic
339
+ * default above.
340
+ */
341
+ cpu_speed_mhz: z2.number().nonnegative().optional()
342
+ }),
343
+ execution: z2.object({
344
+ max_jobs: z2.number(),
345
+ shells: z2.array(z2.string()),
346
+ supports_tty: z2.boolean(),
347
+ supports_process_tree_kill: z2.boolean()
348
+ }),
349
+ tools: z2.record(z2.string(), z2.array(z2.string())),
350
+ toolchain_profiles: z2.array(ToolchainProfileSchema),
351
+ labels: z2.record(z2.string(), z2.string()),
352
+ secret_refs: z2.array(z2.string()),
353
+ /**
354
+ * Optional Phase 5 repository-cache advertisement for scheduler affinity (§19.2).
355
+ * Agents may report canonical ids (and optionally known commits) present in mirrors.
356
+ */
357
+ repository_cache: z2.array(z2.object({
358
+ canonical_id: z2.string().min(1),
359
+ /** Optional known commits present in the mirror (best-effort). */
360
+ commits: z2.array(z2.string().min(1)).optional()
361
+ })).optional(),
362
+ /**
363
+ * Optional Phase 7 named build-cache advertisement for scheduler affinity.
364
+ * Opaque cache identity keys currently present (hashes only — no secrets).
365
+ */
366
+ build_caches: z2.array(z2.object({
367
+ kind: BuildCacheKindSchema,
368
+ keys: z2.array(z2.string().min(1)).optional()
369
+ })).optional(),
370
+ /** Phase 6: false under disk/spool pressure — Agent also lease_rejects. */
371
+ accepting_jobs: z2.boolean().optional(),
372
+ /**
373
+ * Operator-configured scheduling priority (§19.2 / §19.3). When unset, the
374
+ * Controller applies OS-family defaults at schedule time.
375
+ */
376
+ configured_priority: z2.number().optional()
377
+ });
378
+
379
+ // ../../packages/protocol/dist/messages.js
380
+ import { z as z3 } from "zod";
381
+ var AgentMessageTypeSchema = z3.enum([
382
+ "hello",
383
+ "pairing_request",
384
+ "capabilities",
385
+ "heartbeat",
386
+ "lease_accept",
387
+ "lease_reject",
388
+ "source_need",
389
+ "source_ready",
390
+ "job_started",
391
+ "log_chunk",
392
+ "job_exit",
393
+ "artifact_manifest",
394
+ "cleanup_complete",
395
+ "agent_error",
396
+ "recovery_report"
397
+ ]);
398
+ var ControllerMessageTypeSchema = z3.enum([
399
+ "hello_ack",
400
+ "pairing_challenge",
401
+ "lease_offer",
402
+ "prepare_source",
403
+ "snapshot_download",
404
+ "bundle_download",
405
+ "run_job",
406
+ "cancel_job",
407
+ "artifact_upload_grant",
408
+ "pause",
409
+ "resume",
410
+ "refresh_capabilities",
411
+ "shutdown",
412
+ "log_ack",
413
+ "reconcile_decision"
414
+ ]);
415
+ var ProtocolMessageTypeSchema = z3.enum([
416
+ ...AgentMessageTypeSchema.options,
417
+ ...ControllerMessageTypeSchema.options
418
+ ]);
419
+ var JOB_SCOPED_MESSAGE_TYPES = /* @__PURE__ */ new Set([
420
+ "lease_offer",
421
+ "lease_accept",
422
+ "lease_reject",
423
+ "prepare_source",
424
+ "snapshot_download",
425
+ "bundle_download",
426
+ "run_job",
427
+ "cancel_job",
428
+ "source_need",
429
+ "source_ready",
430
+ "job_started",
431
+ "log_chunk",
432
+ "job_exit",
433
+ "artifact_manifest",
434
+ "artifact_upload_grant",
435
+ "cleanup_complete",
436
+ "log_ack",
437
+ "recovery_report",
438
+ "reconcile_decision"
439
+ ]);
440
+ var LeaseOfferPayloadSchema = z3.object({
441
+ attempt_id: z3.string().min(1),
442
+ lease_id: z3.string().min(1),
443
+ lease_epoch: z3.number().int().positive(),
444
+ /** Controller-assigned job id — injected as RBO_JOB_ID on the Agent. */
445
+ job_id: z3.string().min(1),
446
+ job_request: JobRequestSchema,
447
+ snapshot_metadata: z3.object({
448
+ snapshot_id: z3.string().min(1),
449
+ content_id: z3.string().min(1),
450
+ size_bytes: z3.number().int().nonnegative(),
451
+ sha256: z3.string().min(1)
452
+ }),
453
+ selected_toolchain_profiles: z3.array(ToolchainProfileSchema).optional(),
454
+ lease_ttl_seconds: z3.number().positive()
455
+ });
456
+ var LeaseAcceptPayloadSchema = z3.object({
457
+ attempt_id: z3.string().min(1),
458
+ lease_id: z3.string().min(1),
459
+ lease_epoch: z3.number().int().positive()
460
+ });
461
+ var LeaseRejectPayloadSchema = z3.object({
462
+ attempt_id: z3.string().min(1),
463
+ lease_id: z3.string().min(1),
464
+ lease_epoch: z3.number().int().positive(),
465
+ reason: z3.string().min(1)
466
+ });
467
+ var SourceNeedReasonSchema = z3.enum([
468
+ "base_present",
469
+ "base_commit_missing",
470
+ "bundle_required",
471
+ "full_snapshot_required",
472
+ "repo_fetch_failed"
473
+ ]);
474
+ var DataTransferDescriptorSchema = z3.object({
475
+ download_url: z3.string().min(1),
476
+ data_token: z3.string().min(1),
477
+ expected_size_bytes: z3.number().int().nonnegative(),
478
+ expected_sha256: z3.string().min(1)
479
+ });
480
+ var PrepareSourceRepoSchema = z3.object({
481
+ url: z3.string().min(1),
482
+ canonical_id: z3.string().min(1),
483
+ branch: z3.string().nullable(),
484
+ base_commit: z3.string().min(1),
485
+ fetch_refs: z3.array(z3.string().min(1)).default([])
486
+ });
487
+ var PrepareSourceFullPayloadSchema = z3.object({
488
+ source_mode: z3.literal("full"),
489
+ attempt_id: z3.string().min(1),
490
+ lease_id: z3.string().min(1),
491
+ lease_epoch: z3.number().int().positive(),
492
+ download_url: z3.string().min(1),
493
+ data_token: z3.string().min(1),
494
+ expected_size_bytes: z3.number().int().nonnegative(),
495
+ expected_sha256: z3.string().min(1),
496
+ manifest: z3.unknown().optional()
497
+ });
498
+ var PrepareSourceGitOverlayPayloadSchema = z3.object({
499
+ source_mode: z3.literal("git_overlay"),
500
+ attempt_id: z3.string().min(1),
501
+ lease_id: z3.string().min(1),
502
+ lease_epoch: z3.number().int().positive(),
503
+ repo: PrepareSourceRepoSchema,
504
+ overlay: DataTransferDescriptorSchema,
505
+ manifest: z3.unknown().optional()
506
+ });
507
+ var PrepareSourcePayloadSchema = z3.discriminatedUnion("source_mode", [
508
+ PrepareSourceFullPayloadSchema,
509
+ PrepareSourceGitOverlayPayloadSchema
510
+ ]);
511
+ var SourceNeedPayloadSchema = z3.object({
512
+ attempt_id: z3.string().min(1),
513
+ lease_id: z3.string().min(1),
514
+ lease_epoch: z3.number().int().positive(),
515
+ reason: SourceNeedReasonSchema,
516
+ detail: z3.string().optional()
517
+ });
518
+ var BundleDownloadPayloadSchema = z3.object({
519
+ attempt_id: z3.string().min(1),
520
+ lease_id: z3.string().min(1),
521
+ lease_epoch: z3.number().int().positive(),
522
+ download_url: z3.string().min(1),
523
+ data_token: z3.string().min(1),
524
+ expected_size_bytes: z3.number().int().nonnegative(),
525
+ expected_sha256: z3.string().min(1)
526
+ });
527
+ var SourceReadyPayloadSchema = z3.object({
528
+ attempt_id: z3.string().min(1),
529
+ lease_id: z3.string().min(1),
530
+ lease_epoch: z3.number().int().positive()
531
+ });
532
+ var RunJobPayloadSchema = z3.object({
533
+ attempt_id: z3.string().min(1),
534
+ lease_id: z3.string().min(1),
535
+ lease_epoch: z3.number().int().positive()
536
+ });
537
+ var CancelJobPayloadSchema = z3.object({
538
+ attempt_id: z3.string().min(1),
539
+ lease_id: z3.string().min(1),
540
+ lease_epoch: z3.number().int().positive(),
541
+ grace_seconds: z3.number().positive().default(10),
542
+ reason: z3.string().optional()
543
+ });
544
+ var JobStartedPayloadSchema = z3.object({
545
+ attempt_id: z3.string().min(1),
546
+ lease_id: z3.string().min(1),
547
+ lease_epoch: z3.number().int().positive(),
548
+ pid: z3.number().int().positive().optional()
549
+ });
550
+ var LogChunkPayloadSchema = z3.object({
551
+ attempt_id: z3.string().min(1),
552
+ lease_id: z3.string().min(1),
553
+ lease_epoch: z3.number().int().positive(),
554
+ stream: z3.enum(["stdout", "stderr"]),
555
+ sequence: z3.number().int().positive(),
556
+ bytes: z3.string()
557
+ });
558
+ var JobExitPayloadSchema = z3.object({
559
+ attempt_id: z3.string().min(1),
560
+ lease_id: z3.string().min(1),
561
+ lease_epoch: z3.number().int().positive(),
562
+ exit_code: z3.number().int().nullable(),
563
+ outcome: JobOutcomeSchema,
564
+ failure_category: ErrorCategorySchema.optional(),
565
+ failure_message: z3.string().optional()
566
+ });
567
+ var ArtifactManifestPayloadSchema = z3.object({
568
+ attempt_id: z3.string().min(1),
569
+ lease_id: z3.string().min(1),
570
+ lease_epoch: z3.number().int().positive(),
571
+ artifacts: z3.array(z3.object({
572
+ logical_name: z3.string().min(1),
573
+ path: z3.string().min(1),
574
+ size_bytes: z3.number().int().nonnegative(),
575
+ sha256: z3.string().min(1)
576
+ }))
577
+ });
578
+ var ArtifactUploadGrantPayloadSchema = z3.object({
579
+ attempt_id: z3.string().min(1),
580
+ lease_id: z3.string().min(1),
581
+ lease_epoch: z3.number().int().positive(),
582
+ artifacts: z3.array(z3.object({
583
+ logical_name: z3.string().min(1),
584
+ path: z3.string().min(1),
585
+ size_bytes: z3.number().int().nonnegative(),
586
+ sha256: z3.string().min(1),
587
+ upload_url: z3.string().min(1),
588
+ upload_token: z3.string().min(1)
589
+ }))
590
+ });
591
+ var CleanupCompletePayloadSchema = z3.object({
592
+ attempt_id: z3.string().min(1),
593
+ lease_id: z3.string().min(1),
594
+ lease_epoch: z3.number().int().positive(),
595
+ exit_code: z3.number().int().nullable(),
596
+ timed_out: z3.boolean(),
597
+ message: z3.string().optional()
598
+ });
599
+ var LogAckPayloadSchema = z3.object({
600
+ attempt_id: z3.string().min(1),
601
+ lease_id: z3.string().min(1),
602
+ lease_epoch: z3.number().int().positive(),
603
+ sequence: z3.number().int().positive()
604
+ });
605
+ var RecoveryReportStatusSchema = z3.enum([
606
+ "running",
607
+ "completed_awaiting_upload",
608
+ "orphaned"
609
+ ]);
610
+ var RecoveryReportPayloadSchema = z3.object({
611
+ attempt_id: z3.string().min(1),
612
+ lease_id: z3.string().min(1),
613
+ lease_epoch: z3.number().int().positive(),
614
+ status: RecoveryReportStatusSchema,
615
+ process_identity: z3.string().min(1),
616
+ last_sent_sequence: z3.number().int().nonnegative(),
617
+ last_acked_sequence: z3.number().int().nonnegative(),
618
+ artifact_upload_pending: z3.boolean()
619
+ });
620
+ var ReconcileDecisionPayloadSchema = z3.object({
621
+ attempt_id: z3.string().min(1),
622
+ lease_id: z3.string().min(1),
623
+ lease_epoch: z3.number().int().positive(),
624
+ action: z3.enum(["adopt", "terminate_stale"]),
625
+ resume_from_sequence: z3.number().int().nonnegative().optional(),
626
+ reason: z3.string().optional()
627
+ });
628
+ var WireMessageEnvelopeSchema = z3.object({
629
+ protocol: z3.number().int().positive(),
630
+ type: ProtocolMessageTypeSchema,
631
+ message_id: z3.string(),
632
+ sent_at: z3.string(),
633
+ attempt_id: z3.string().nullable(),
634
+ lease_id: z3.string().nullable(),
635
+ lease_epoch: z3.number().nullable(),
636
+ payload: z3.record(z3.string(), z3.unknown())
637
+ }).superRefine((msg, ctx) => {
638
+ if (JOB_SCOPED_MESSAGE_TYPES.has(msg.type)) {
639
+ if (msg.attempt_id === null || msg.lease_id === null || msg.lease_epoch === null) {
640
+ ctx.addIssue({
641
+ code: z3.ZodIssueCode.custom,
642
+ message: `job-scoped message '${msg.type}' requires attempt_id, lease_id and lease_epoch (\xA720.2)`
643
+ });
644
+ }
645
+ }
646
+ });
647
+
648
+ // ../../packages/protocol/dist/mcp-tools.js
649
+ import { z as z4 } from "zod";
650
+ var JOB_SUBMIT_INPUT = JobRequestSchema.shape;
651
+ var JOB_CONFIRM_INPUT = {
652
+ job_id: z4.string().min(1),
653
+ confirmation_token: z4.string().min(1)
654
+ };
655
+ var AGENTS_LIST_INPUT = {
656
+ include_offline: z4.boolean().default(false)
657
+ };
658
+ var JOB_GET_INPUT = {
659
+ job_id: z4.string().min(1)
660
+ };
661
+ var JOB_WAIT_INPUT = {
662
+ job_id: z4.string().min(1),
663
+ wait_seconds: z4.number().int().min(0).max(300).default(30),
664
+ include_log_tail_lines: z4.number().int().min(0).max(1e3).default(0)
665
+ };
666
+ var JOB_LOGS_INPUT = {
667
+ job_id: z4.string().min(1),
668
+ // null means "current active attempt, or terminal attempt for a terminal job" (§23.5)
669
+ attempt_id: z4.string().nullable().default(null),
670
+ cursor: z4.number().int().min(0).default(0),
671
+ max_bytes: z4.number().int().positive().max(1024 * 1024).default(65536),
672
+ streams: z4.array(z4.enum(["stdout", "stderr", "events"])).default(["stdout", "stderr"])
673
+ };
674
+ var JOB_CANCEL_INPUT = {
675
+ job_id: z4.string().min(1),
676
+ reason: z4.string().optional()
677
+ };
678
+ var JOB_ARTIFACTS_INPUT = {
679
+ job_id: z4.string().min(1)
680
+ };
681
+ var ARTIFACT_MATERIALIZE_INPUT = {
682
+ artifact_id: z4.string().min(1),
683
+ destination_path: z4.string().min(1),
684
+ overwrite: z4.boolean().default(false)
685
+ };
686
+ var AGENT_PROBE_INPUT = {
687
+ agent_id: z4.string().min(1)
688
+ };
689
+ var MCP_TOOL_DEFS = [
690
+ {
691
+ name: "agents_list",
692
+ description: "List registered worker agents and their capabilities.",
693
+ inputShape: AGENTS_LIST_INPUT
694
+ },
695
+ {
696
+ name: "job_submit",
697
+ description: "Submit a build/test job and capture an immutable workspace snapshot.",
698
+ inputShape: JOB_SUBMIT_INPUT
699
+ },
700
+ {
701
+ name: "job_confirm",
702
+ description: "Confirm a destructive or hardware-risk job after snapshot capture.",
703
+ inputShape: JOB_CONFIRM_INPUT
704
+ },
705
+ {
706
+ name: "job_get",
707
+ description: "Get current state and metadata of a job.",
708
+ inputShape: JOB_GET_INPUT
709
+ },
710
+ {
711
+ name: "job_wait",
712
+ description: "Wait up to wait_seconds for a job to reach a terminal state; returns current state otherwise.",
713
+ inputShape: JOB_WAIT_INPUT
714
+ },
715
+ {
716
+ name: "job_logs",
717
+ description: "Read incremental job logs from an attempt-scoped cursor.",
718
+ inputShape: JOB_LOGS_INPUT
719
+ },
720
+ {
721
+ name: "job_cancel",
722
+ description: "Cancel a running or queued job.",
723
+ inputShape: JOB_CANCEL_INPUT
724
+ },
725
+ {
726
+ name: "job_artifacts",
727
+ description: "List collected artifacts of a job, grouped by attempt.",
728
+ inputShape: JOB_ARTIFACTS_INPUT
729
+ },
730
+ {
731
+ name: "artifact_materialize",
732
+ description: "Copy one stored artifact into an allowed local destination path on the development PC.",
733
+ inputShape: ARTIFACT_MATERIALIZE_INPUT
734
+ },
735
+ {
736
+ name: "agent_probe",
737
+ description: "Trigger a capability re-probe of one agent.",
738
+ inputShape: AGENT_PROBE_INPUT
739
+ }
740
+ ];
741
+
742
+ // ../../packages/protocol/dist/compatibility-matrix.js
743
+ import { z as z5 } from "zod";
744
+ var CompatibilityCellSchema = z5.object({
745
+ client: z5.string().min(1),
746
+ transport: z5.enum(["stdio", "streamable_http"]),
747
+ status: z5.enum(["verified", "not_verified"]),
748
+ revision: z5.string().min(1),
749
+ os: z5.string().min(1),
750
+ client_version: z5.string().min(1),
751
+ config_ref: z5.string().min(1),
752
+ workflow: z5.string().min(1),
753
+ limitation: z5.string().optional(),
754
+ evidence_path: z5.string().optional()
755
+ });
756
+ var CompatibilityMatrixSchema = z5.object({
757
+ schema_version: z5.literal(1),
758
+ generated_at: z5.string().min(1),
759
+ policy: z5.string().min(1),
760
+ cells: z5.array(CompatibilityCellSchema).min(1)
761
+ });
762
+
763
+ // ../mcp-stdio/src/proxy.ts
764
+ function createStdioProxyServer(options) {
765
+ const server = new McpServer({
766
+ name: "rbo-mcp-stdio",
767
+ version: RBO_STDIO_ADAPTER_VERSION
768
+ });
769
+ const baseUrl = options.controllerUrl.replace(/\/+$/, "");
770
+ for (const def of MCP_TOOL_DEFS) {
771
+ server.registerTool(
772
+ def.name,
773
+ { description: def.description, inputSchema: def.inputShape },
774
+ async (args) => {
775
+ const response = await fetch(`${baseUrl}/internal/v1/tools/${def.name}`, {
776
+ method: "POST",
777
+ headers: {
778
+ "content-type": "application/json",
779
+ "x-rbo-client-id": options.clientId,
780
+ "x-rbo-client-transport": "stdio"
781
+ },
782
+ body: JSON.stringify(args ?? {})
783
+ });
784
+ const text = await response.text();
785
+ return {
786
+ content: [{ type: "text", text }],
787
+ isError: !response.ok
788
+ };
789
+ }
790
+ );
791
+ }
792
+ return server;
793
+ }
794
+
795
+ // ../mcp-stdio/src/main.ts
796
+ function argValue(flag) {
797
+ const index = process.argv.indexOf(flag);
798
+ if (index === -1 || index + 1 >= process.argv.length) {
799
+ return void 0;
800
+ }
801
+ return process.argv[index + 1];
802
+ }
803
+ async function main() {
804
+ const controllerUrl = argValue("--controller") ?? process.env.RBO_CONTROLLER_URL ?? "http://127.0.0.1:7410";
805
+ const clientId = argValue("--client-id") ?? process.env.RBO_CLIENT_ID ?? `mcp-stdio-${process.pid}`;
806
+ const server = createStdioProxyServer({ controllerUrl, clientId });
807
+ const transport = new StdioServerTransport();
808
+ await server.connect(transport);
809
+ console.error(`rbo mcp-stdio connected to ${controllerUrl} as ${clientId}`);
810
+ }
811
+ main().catch((error) => {
812
+ console.error(`rbo mcp-stdio failed: ${String(error)}`);
813
+ process.exit(1);
814
+ });