@loucompanion/forge-bridge 0.1.3-dev.b3bce6ba65a6 → 0.1.3-dev.ba293ccf876b

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 (189) hide show
  1. package/README.md +127 -0
  2. package/dist/bridge/bridge.base.d.ts +8 -1
  3. package/dist/bridge/bridge.service.d.ts +98 -3
  4. package/dist/bridge/bridge.service.js +1425 -45
  5. package/dist/bridge/bridge.types.d.ts +205 -1
  6. package/dist/bridge/readiness-result-outbox.d.ts +21 -0
  7. package/dist/bridge/readiness-result-outbox.js +54 -0
  8. package/dist/bridge/readiness-result-worker.d.ts +2 -0
  9. package/dist/bridge/readiness-result-worker.js +100 -0
  10. package/dist/bridge/runner-host-capabilities.d.ts +15 -0
  11. package/dist/bridge/runner-host-capabilities.js +93 -0
  12. package/dist/cleanup/cleanup.service.d.ts +14 -2
  13. package/dist/cleanup/cleanup.service.js +496 -3
  14. package/dist/cleanup/cleanup.types.d.ts +10 -0
  15. package/dist/cleanup/index.d.ts +1 -1
  16. package/dist/cleanup/index.js +1 -1
  17. package/dist/cleanup/internals.d.ts +2 -2
  18. package/dist/cleanup/internals.js +1 -1
  19. package/dist/cli/cli.help.js +47 -1
  20. package/dist/cli/cli.service.d.ts +45 -2
  21. package/dist/cli/cli.service.js +377 -27
  22. package/dist/cli/local-config.d.ts +5 -0
  23. package/dist/cli/local-config.js +45 -1
  24. package/dist/runtime/aspnet-runtime-prebuild.d.ts +36 -0
  25. package/dist/runtime/aspnet-runtime-prebuild.js +340 -0
  26. package/dist/runtime/attempt-node-runtime-launcher.d.ts +17 -0
  27. package/dist/runtime/attempt-node-runtime-launcher.js +105 -0
  28. package/dist/runtime/attempt-path-operation.d.ts +21 -0
  29. package/dist/runtime/attempt-path-operation.js +94 -0
  30. package/dist/runtime/attempt-private-directory.d.ts +6 -0
  31. package/dist/runtime/attempt-private-directory.js +54 -0
  32. package/dist/runtime/attempt-process-supervisor-registry.d.ts +20 -0
  33. package/dist/runtime/attempt-process-supervisor-registry.js +64 -0
  34. package/dist/runtime/attempt-process-supervisor.d.ts +97 -0
  35. package/dist/runtime/attempt-process-supervisor.js +386 -0
  36. package/dist/runtime/canonical-source-file.d.ts +3 -0
  37. package/dist/runtime/canonical-source-file.js +54 -0
  38. package/dist/runtime/docker-engine-probe.d.ts +83 -0
  39. package/dist/runtime/docker-engine-probe.js +300 -0
  40. package/dist/runtime/generated-output-reset.d.ts +10 -0
  41. package/dist/runtime/generated-output-reset.js +103 -0
  42. package/dist/runtime/host-diagnostics.d.ts +4 -0
  43. package/dist/runtime/host-diagnostics.js +95 -0
  44. package/dist/runtime/host-listener-inspector.d.ts +46 -0
  45. package/dist/runtime/host-listener-inspector.js +349 -0
  46. package/dist/runtime/host-port-broker.d.ts +76 -0
  47. package/dist/runtime/host-port-broker.js +333 -0
  48. package/dist/runtime/host-runtime-contract.d.ts +56 -0
  49. package/dist/runtime/host-runtime-contract.js +709 -0
  50. package/dist/runtime/host-runtime-lease.d.ts +201 -0
  51. package/dist/runtime/host-runtime-lease.js +2314 -0
  52. package/dist/runtime/host-runtime-promotion.d.ts +32 -0
  53. package/dist/runtime/host-runtime-promotion.js +206 -0
  54. package/dist/runtime/memory-capacity.d.ts +68 -0
  55. package/dist/runtime/memory-capacity.js +121 -0
  56. package/dist/runtime/node-host-runtime-adapter.d.ts +54 -0
  57. package/dist/runtime/node-host-runtime-adapter.js +284 -0
  58. package/dist/runtime/pinned-directory-process.d.ts +4 -0
  59. package/dist/runtime/pinned-directory-process.js +20 -0
  60. package/dist/runtime/pinned-source-directory.d.ts +9 -0
  61. package/dist/runtime/pinned-source-directory.js +56 -0
  62. package/dist/runtime/playwright-host-runtime-adapter.d.ts +21 -0
  63. package/dist/runtime/playwright-host-runtime-adapter.js +268 -0
  64. package/dist/runtime/prepared-runtime-identity.d.ts +3 -0
  65. package/dist/runtime/prepared-runtime-identity.js +191 -0
  66. package/dist/runtime/prepared-runtime-readiness.d.ts +22 -0
  67. package/dist/runtime/prepared-runtime-readiness.js +191 -0
  68. package/dist/runtime/runtime-isolation-lease.d.ts +67 -0
  69. package/dist/runtime/runtime-isolation-lease.js +158 -0
  70. package/dist/runtime/workspace-resource-estimator.d.ts +17 -0
  71. package/dist/runtime/workspace-resource-estimator.js +174 -0
  72. package/dist/sandbox/command-runner.d.ts +4 -0
  73. package/dist/sandbox/command-runner.js +47 -0
  74. package/dist/sandbox/contract.d.ts +5 -0
  75. package/dist/sandbox/contract.js +276 -0
  76. package/dist/sandbox/event-budget.d.ts +11 -0
  77. package/dist/sandbox/event-budget.js +27 -0
  78. package/dist/sandbox/image-policy.d.ts +35 -0
  79. package/dist/sandbox/image-policy.js +247 -0
  80. package/dist/sandbox/index.d.ts +5 -0
  81. package/dist/sandbox/index.js +5 -0
  82. package/dist/sandbox/lease-watchdog.d.ts +18 -0
  83. package/dist/sandbox/lease-watchdog.js +67 -0
  84. package/dist/sandbox/preflight.d.ts +84 -0
  85. package/dist/sandbox/preflight.js +521 -0
  86. package/dist/sandbox/process.d.ts +20 -0
  87. package/dist/sandbox/process.js +209 -0
  88. package/dist/sandbox/provider-auth/codex.d.ts +26 -0
  89. package/dist/sandbox/provider-auth/codex.js +212 -0
  90. package/dist/sandbox/repository-lock.d.ts +5 -0
  91. package/dist/sandbox/repository-lock.js +121 -0
  92. package/dist/sandbox/runtime.d.ts +297 -0
  93. package/dist/sandbox/runtime.js +2338 -0
  94. package/dist/sandbox/sandbox.types.d.ts +93 -0
  95. package/dist/sandbox/sandbox.types.js +1 -0
  96. package/dist/sandbox/smoke.d.ts +76 -0
  97. package/dist/sandbox/smoke.js +380 -0
  98. package/dist/sandbox/worker-supervisor.d.ts +13 -0
  99. package/dist/sandbox/worker-supervisor.js +36 -0
  100. package/dist/sandbox/worker.d.ts +1 -0
  101. package/dist/sandbox/worker.js +225 -0
  102. package/dist/sandbox/workspace.service.d.ts +13 -0
  103. package/dist/sandbox/workspace.service.js +72 -0
  104. package/dist/session/managed-attempt-tools.d.ts +21 -0
  105. package/dist/session/managed-attempt-tools.js +912 -0
  106. package/dist/session/managed-build-coordinator.d.ts +5 -0
  107. package/dist/session/managed-build-coordinator.js +105 -0
  108. package/dist/session/managed-build-receipt.d.ts +21 -0
  109. package/dist/session/managed-build-receipt.js +335 -0
  110. package/dist/session/phase-completion.artifacts.d.ts +17 -0
  111. package/dist/session/phase-completion.artifacts.js +256 -26
  112. package/dist/session/phase-completion.d.ts +12 -2
  113. package/dist/session/phase-completion.helpers.d.ts +5 -0
  114. package/dist/session/phase-completion.helpers.js +51 -10
  115. package/dist/session/phase-completion.js +14 -3
  116. package/dist/session/phase-completion.prompts.d.ts +3 -3
  117. package/dist/session/phase-completion.prompts.js +24 -8
  118. package/dist/session/phase-completion.runtime.d.ts +13 -1
  119. package/dist/session/phase-completion.runtime.js +189 -8
  120. package/dist/session/phase-completion.schemas.js +117 -4
  121. package/dist/session/phase-completion.validation.d.ts +4 -1
  122. package/dist/session/phase-completion.validation.js +153 -22
  123. package/dist/session/pre-publication-validation.d.ts +47 -0
  124. package/dist/session/pre-publication-validation.js +249 -0
  125. package/dist/session/provider-cli/ci-repair-readiness.d.ts +16 -0
  126. package/dist/session/provider-cli/ci-repair-readiness.js +110 -0
  127. package/dist/session/provider-cli/provider-cli.artifacts.d.ts +3 -2
  128. package/dist/session/provider-cli/provider-cli.artifacts.js +65 -7
  129. package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
  130. package/dist/session/provider-cli/provider-cli.deterministic.d.ts +2 -0
  131. package/dist/session/provider-cli/provider-cli.deterministic.js +68 -9
  132. package/dist/session/provider-cli/provider-cli.process.d.ts +26 -0
  133. package/dist/session/provider-cli/provider-cli.process.js +474 -23
  134. package/dist/session/provider-cli/provider-cli.prompts.d.ts +14 -2
  135. package/dist/session/provider-cli/provider-cli.prompts.js +147 -25
  136. package/dist/session/provider-cli/provider-cli.qa-sidecars.js +1 -0
  137. package/dist/session/provider-cli/provider-cli.repair-epoch.d.ts +6 -0
  138. package/dist/session/provider-cli/provider-cli.repair-epoch.js +11 -0
  139. package/dist/session/provider-cli/provider-cli.runtime.d.ts +1 -1
  140. package/dist/session/provider-cli/provider-cli.runtime.js +6 -3
  141. package/dist/session/provider-cli/provider-cli.service.d.ts +25 -2
  142. package/dist/session/provider-cli/provider-cli.service.js +636 -84
  143. package/dist/session/provider-cli/provider-cli.types.d.ts +5 -0
  144. package/dist/session/provider-cli/provider-output-state.d.ts +2 -0
  145. package/dist/session/provider-cli/provider-output-state.js +91 -16
  146. package/dist/session/provider-cli/provider-usage.d.ts +7 -0
  147. package/dist/session/provider-cli/provider-usage.js +28 -5
  148. package/dist/session/session-redaction.d.ts +3 -0
  149. package/dist/session/session-redaction.js +38 -0
  150. package/dist/session/session.base.d.ts +6 -1
  151. package/dist/session/session.service.d.ts +8 -2
  152. package/dist/session/session.service.js +531 -42
  153. package/dist/session/session.types.d.ts +115 -1
  154. package/dist/session/session.types.js +194 -3
  155. package/dist/shared/format/format-bytes.d.ts +1 -0
  156. package/dist/shared/format/format-bytes.js +9 -0
  157. package/dist/shared/git/git.js +2 -1
  158. package/dist/shared/path/path.d.ts +1 -0
  159. package/dist/shared/path/path.js +21 -1
  160. package/dist/shared/process/dotnet-toolchain.d.ts +14 -0
  161. package/dist/shared/process/dotnet-toolchain.js +179 -0
  162. package/dist/shared/process/host-process-recovery.d.ts +12 -0
  163. package/dist/shared/process/host-process-recovery.js +78 -0
  164. package/dist/shared/process/host-process-supervisor.d.ts +59 -0
  165. package/dist/shared/process/host-process-supervisor.js +330 -0
  166. package/dist/shared/process/process.d.ts +2 -0
  167. package/dist/shared/process/process.js +11 -6
  168. package/dist/shared/provider-capabilities.d.ts +1 -0
  169. package/dist/shared/provider-capabilities.js +3 -0
  170. package/dist/shared/redaction/redaction.js +12 -2
  171. package/dist/version.d.ts +1 -1
  172. package/dist/version.js +1 -1
  173. package/dist/worktree/artifact-injector.d.ts +3 -2
  174. package/dist/worktree/artifact-injector.js +43 -4
  175. package/dist/worktree/dependency-warmer.d.ts +28 -1
  176. package/dist/worktree/dependency-warmer.js +308 -9
  177. package/dist/worktree/index.d.ts +2 -1
  178. package/dist/worktree/index.js +1 -0
  179. package/dist/worktree/prior-phase-artifact-hydrator.d.ts +2 -0
  180. package/dist/worktree/prior-phase-artifact-hydrator.js +136 -0
  181. package/dist/worktree/worktree-paths.d.ts +4 -0
  182. package/dist/worktree/worktree-paths.js +30 -0
  183. package/dist/worktree/worktree.base.d.ts +3 -0
  184. package/dist/worktree/worktree.service.d.ts +14 -2
  185. package/dist/worktree/worktree.service.js +296 -47
  186. package/dist/worktree/worktree.types.d.ts +5 -1
  187. package/package.json +8 -4
  188. package/runtime/windows-job-supervisor.ps1 +444 -0
  189. package/runtime/windows-listener-owner.ps1 +33 -0
@@ -1,5 +1,5 @@
1
1
  export interface RunOnceDispatchPacket {
2
- readonly schemaVersion: 1;
2
+ readonly schemaVersion: 1 | 2;
3
3
  readonly userId: string;
4
4
  readonly workItem: DispatchWorkItem;
5
5
  readonly repo: DispatchRepo;
@@ -7,10 +7,14 @@ export interface RunOnceDispatchPacket {
7
7
  readonly session: DispatchSession;
8
8
  readonly lease: DispatchLease;
9
9
  readonly execution: DispatchExecution;
10
+ readonly runtimeIntent: DispatchRuntimeIntent;
10
11
  readonly serverLocal: DispatchServerLocalConfig;
12
+ readonly sandbox?: DispatchSandboxContext | null;
11
13
  readonly pullRequest?: DispatchPullRequestContext | null;
12
14
  readonly apiKeySecretGrant?: ApiKeySecretGrant | null;
15
+ readonly apiKeySecretGrantHandle?: ApiKeySecretGrantHandle | null;
13
16
  readonly artifacts: readonly DispatchResolvedArtifact[];
17
+ readonly priorPhaseArtifacts?: readonly DispatchPriorPhaseArtifact[];
14
18
  readonly warmPathOverrides?: readonly string[];
15
19
  readonly qaBrowser?: DispatchQaBrowserContext | null;
16
20
  readonly qaScope?: DispatchQaScope | null;
@@ -22,6 +26,46 @@ export interface RunOnceDispatchPacket {
22
26
  readonly designerRefs?: DispatchDesignerRefHandoffContext | null;
23
27
  readonly draft?: DispatchDraftPrompt | null;
24
28
  }
29
+ export interface DispatchRuntimeIntent {
30
+ readonly executionClass: "analysis_only" | "managed_runtime";
31
+ readonly applicationRuntimeRequired: boolean;
32
+ }
33
+ export interface DispatchSandboxContext {
34
+ readonly dispatchAttemptId: string;
35
+ readonly executionLeaseId: string;
36
+ readonly runnerInstanceId: string;
37
+ readonly executionMode: "host" | "docker";
38
+ readonly executionPolicy: "host_allowed" | "sandbox_preferred" | "sandbox_required";
39
+ readonly networkPolicy: DispatchSandboxNetworkPolicy;
40
+ readonly requestedResources: DispatchSandboxResourceRequest;
41
+ readonly runtime?: string | null;
42
+ readonly sandboxConfigCommitSha?: string | null;
43
+ readonly inputCommitSha?: string | null;
44
+ readonly contractDigest?: string | null;
45
+ readonly imageDigest?: string | null;
46
+ readonly publicationMode: "bridge_push" | "shared_filesystem";
47
+ readonly publishGrantHandle?: DispatchPublishGrantHandle | null;
48
+ }
49
+ export interface DispatchPublishGrantHandle {
50
+ readonly grantId: string;
51
+ readonly branch: string;
52
+ readonly expiresAt: string;
53
+ }
54
+ export interface DispatchSandboxResourceRequest {
55
+ readonly sandboxSlots: number;
56
+ readonly cpuMillis: number;
57
+ readonly workerMemoryLimitBytes: number;
58
+ readonly serviceMemoryLimitBytes: number;
59
+ readonly runtimeOverheadBytes: number;
60
+ readonly memoryBytes: number;
61
+ readonly workspaceBytes: number;
62
+ readonly pids: number;
63
+ readonly buildSlots: number;
64
+ }
65
+ export interface DispatchSandboxNetworkPolicy {
66
+ readonly mode: "offline" | "public_allowlist" | "open_public";
67
+ readonly allowedHosts: readonly string[];
68
+ }
25
69
  export interface DispatchDraftPrompt {
26
70
  readonly kind: string;
27
71
  readonly systemPrompt: string;
@@ -50,6 +94,7 @@ export interface DispatchQaScope {
50
94
  readonly schema_version: number;
51
95
  readonly surface: readonly string[];
52
96
  readonly required_evidence: readonly string[];
97
+ readonly required_capabilities?: readonly string[];
53
98
  readonly not_applicable: readonly string[];
54
99
  readonly browser_required: boolean;
55
100
  readonly api_required: boolean;
@@ -66,6 +111,7 @@ export interface DispatchQaAppLaunchTarget {
66
111
  readonly command?: string | null;
67
112
  readonly working_directory?: string | null;
68
113
  readonly ready_url?: string | null;
114
+ readonly managed_runtime_port?: string | null;
69
115
  readonly routes: readonly string[];
70
116
  readonly notes?: string | null;
71
117
  }
@@ -154,6 +200,19 @@ export interface DispatchStoryQaDependencyContext {
154
200
  readonly fromWorkItemId: string;
155
201
  readonly toWorkItemId: string;
156
202
  }
203
+ export interface DispatchPriorPhaseArtifact {
204
+ readonly workItemId: string;
205
+ readonly artifactId: string;
206
+ readonly cycleRunId: string;
207
+ readonly phase: "implementation" | "self_review" | "validation";
208
+ readonly status: string;
209
+ readonly producedAt: string;
210
+ readonly sourcePath: string;
211
+ readonly verdictJson: string;
212
+ readonly report: string;
213
+ readonly verdictContentHash: string;
214
+ readonly reportContentHash: string;
215
+ }
157
216
  export interface DispatchDesignerRefHandoffContext {
158
217
  readonly schemaVersion: number;
159
218
  readonly kind: string;
@@ -243,6 +302,7 @@ export interface DispatchCycleRun {
243
302
  readonly requestedBase: string;
244
303
  readonly baseBranch: string;
245
304
  readonly expectedCurrentBranch?: string | null;
305
+ readonly repairHeadSha?: string | null;
246
306
  readonly attempt: number;
247
307
  readonly model: string;
248
308
  }
@@ -250,6 +310,8 @@ export interface DispatchSession {
250
310
  readonly id: string;
251
311
  readonly model: string;
252
312
  readonly lane: string;
313
+ readonly resumedFromSessionId?: string | null;
314
+ readonly resumeProviderThreadId?: string | null;
253
315
  }
254
316
  export interface DispatchLease {
255
317
  readonly id: string;
@@ -279,11 +341,18 @@ export interface ApiKeySecretGrant {
279
341
  readonly secret: string;
280
342
  readonly expiresAt: string;
281
343
  }
344
+ export interface ApiKeySecretGrantHandle {
345
+ readonly grantId: string;
346
+ readonly provider: string;
347
+ readonly expiresAt: string;
348
+ }
282
349
  export interface DispatchServerLocalConfig {
283
350
  readonly repoRoot: string;
284
351
  readonly cleanupWorktrees: boolean;
285
352
  }
286
353
  export interface RunnerDispatchEvent {
354
+ /** Stable across callback retries; persisted atomically with the session event. */
355
+ readonly eventId?: string | null;
287
356
  readonly role: string;
288
357
  readonly kind: string;
289
358
  readonly content: string;
@@ -313,6 +382,19 @@ export interface RunnerDispatchArtifact {
313
382
  readonly producedBy: string;
314
383
  readonly status: string;
315
384
  readonly phase?: string | null;
385
+ /**
386
+ * QA sidecars are transported with the terminal result because managed
387
+ * worktrees may be released before the API mirrors the result. The API
388
+ * validates these bytes against the canonical evidence metadata and stores
389
+ * only that metadata.
390
+ */
391
+ readonly sidecars?: readonly RunnerDispatchSidecar[] | null;
392
+ }
393
+ export interface RunnerDispatchSidecar {
394
+ readonly path: string;
395
+ readonly contentBase64: string;
396
+ readonly contentHash: string;
397
+ readonly bytes: number;
316
398
  }
317
399
  export interface RunOnceResultPacket {
318
400
  readonly schemaVersion: 1;
@@ -328,4 +410,36 @@ export interface RunnerEventLine {
328
410
  readonly event: RunnerDispatchEvent;
329
411
  }
330
412
  export declare function parseRunOnceDispatchPacket(value: unknown): RunOnceDispatchPacket;
413
+ export interface HostRuntimeReadinessProbeRequest {
414
+ readonly requestId: string;
415
+ readonly fencingToken: string;
416
+ readonly userId: string;
417
+ readonly projectId: string;
418
+ readonly repoId: string;
419
+ readonly runnerId: string;
420
+ readonly runnerInstanceId: string;
421
+ readonly attempt: number;
422
+ readonly repoName: string;
423
+ readonly remoteUrl: string;
424
+ readonly defaultBranch: string;
425
+ readonly cloneOnDemand: boolean;
426
+ readonly runnerRepoLocalPath: string;
427
+ readonly revision: string;
428
+ readonly expiresAt: string;
429
+ readonly repoRoot: string;
430
+ readonly cleanupWorktrees: boolean;
431
+ }
432
+ export interface HostRuntimeReadinessProbeResult {
433
+ readonly status: "parallel_ready" | "serialized" | "failed";
434
+ readonly runtimeContractFingerprint?: string | null;
435
+ readonly runtimeContractSource?: string | null;
436
+ readonly reasonCode?: string | null;
437
+ readonly reasonMessage?: string | null;
438
+ readonly qaAppLaunchTarget?: HostRuntimeReadinessQaLaunchTarget | null;
439
+ readonly checkedAt: string;
440
+ }
441
+ export interface HostRuntimeReadinessQaLaunchTarget {
442
+ readonly managedRuntimePort: string;
443
+ readonly routes: readonly string[];
444
+ }
331
445
  export declare function failureResult(summary: string, events?: readonly RunnerDispatchEvent[]): RunOnceResultPacket;
@@ -2,11 +2,11 @@ import path from "node:path";
2
2
  export function parseRunOnceDispatchPacket(value) {
3
3
  const packet = asObject(value, "dispatch packet");
4
4
  const schemaVersion = requiredNumber(packet, "schemaVersion");
5
- if (schemaVersion !== 1) {
5
+ if (schemaVersion !== 1 && schemaVersion !== 2) {
6
6
  throw new Error(`Unsupported dispatch schemaVersion: ${schemaVersion}`);
7
7
  }
8
8
  return {
9
- schemaVersion: 1,
9
+ schemaVersion,
10
10
  userId: requiredString(packet, "userId"),
11
11
  workItem: parseWorkItem(packet.workItem),
12
12
  repo: parseRepo(packet.repo),
@@ -14,10 +14,14 @@ export function parseRunOnceDispatchPacket(value) {
14
14
  session: parseSession(packet.session),
15
15
  lease: parseLease(packet.lease),
16
16
  execution: parseExecution(packet.execution),
17
+ runtimeIntent: parseRuntimeIntent(packet.runtimeIntent),
17
18
  serverLocal: parseServerLocal(packet.serverLocal),
19
+ sandbox: parseSandbox(packet.sandbox, schemaVersion),
18
20
  pullRequest: parsePullRequest(packet.pullRequest),
19
21
  apiKeySecretGrant: parseApiKeySecretGrant(packet.apiKeySecretGrant),
22
+ apiKeySecretGrantHandle: parseApiKeySecretGrantHandle(packet.apiKeySecretGrantHandle),
20
23
  artifacts: parseArtifacts(packet.artifacts),
24
+ priorPhaseArtifacts: parsePriorPhaseArtifacts(packet.priorPhaseArtifacts),
21
25
  warmPathOverrides: parseWarmPathOverrides(packet.warmPathOverrides),
22
26
  qaBrowser: parseQaBrowser(packet.qaBrowser),
23
27
  qaScope: parseQaScope(packet.qaScope ?? packet.qa_scope),
@@ -30,6 +34,143 @@ export function parseRunOnceDispatchPacket(value) {
30
34
  draft: parseDraftPrompt(packet.draft)
31
35
  };
32
36
  }
37
+ function parseRuntimeIntent(value) {
38
+ if (value === undefined || value === null) {
39
+ return { executionClass: "managed_runtime", applicationRuntimeRequired: true };
40
+ }
41
+ const intent = asObject(value, "runtimeIntent");
42
+ const executionClass = requiredString(intent, "executionClass").trim().toLowerCase();
43
+ if (executionClass !== "analysis_only" && executionClass !== "managed_runtime") {
44
+ throw new Error("runtimeIntent.executionClass must be analysis_only or managed_runtime.");
45
+ }
46
+ const applicationRuntimeRequired = requiredBoolean(intent, "applicationRuntimeRequired");
47
+ if ((executionClass === "analysis_only") === applicationRuntimeRequired) {
48
+ throw new Error("runtimeIntent execution class and application runtime requirement are inconsistent.");
49
+ }
50
+ return { executionClass, applicationRuntimeRequired };
51
+ }
52
+ function parseSandbox(value, schemaVersion) {
53
+ if (value === undefined || value === null) {
54
+ if (schemaVersion === 2) {
55
+ throw new Error("sandbox is required for dispatch schemaVersion 2.");
56
+ }
57
+ return null;
58
+ }
59
+ const sandbox = asObject(value, "sandbox");
60
+ const executionMode = requiredString(sandbox, "executionMode");
61
+ if (executionMode !== "host" && executionMode !== "docker") {
62
+ throw new Error("sandbox.executionMode must be host or docker.");
63
+ }
64
+ const executionPolicy = requiredString(sandbox, "executionPolicy");
65
+ if (executionPolicy !== "host_allowed" && executionPolicy !== "sandbox_preferred" && executionPolicy !== "sandbox_required") {
66
+ throw new Error("sandbox.executionPolicy is invalid.");
67
+ }
68
+ return {
69
+ dispatchAttemptId: requiredString(sandbox, "dispatchAttemptId"),
70
+ executionLeaseId: requiredString(sandbox, "executionLeaseId"),
71
+ runnerInstanceId: requiredString(sandbox, "runnerInstanceId"),
72
+ executionMode,
73
+ executionPolicy,
74
+ networkPolicy: parseSandboxNetworkPolicy(sandbox.networkPolicy),
75
+ requestedResources: parseSandboxResourceRequest(sandbox.requestedResources),
76
+ runtime: optionalString(sandbox, "runtime"),
77
+ sandboxConfigCommitSha: optionalString(sandbox, "sandboxConfigCommitSha"),
78
+ inputCommitSha: optionalString(sandbox, "inputCommitSha"),
79
+ contractDigest: optionalString(sandbox, "contractDigest"),
80
+ imageDigest: optionalString(sandbox, "imageDigest"),
81
+ publicationMode: parsePublicationMode(sandbox.publicationMode),
82
+ publishGrantHandle: parsePublishGrantHandle(sandbox.publishGrantHandle)
83
+ };
84
+ }
85
+ function parsePublicationMode(value) {
86
+ if (value === undefined || value === null)
87
+ return "shared_filesystem";
88
+ if (value !== "bridge_push" && value !== "shared_filesystem")
89
+ throw new Error("sandbox.publicationMode is invalid.");
90
+ return value;
91
+ }
92
+ function parsePublishGrantHandle(value) {
93
+ if (value === undefined || value === null)
94
+ return null;
95
+ const handle = asObject(value, "sandbox.publishGrantHandle");
96
+ const grantId = requiredString(handle, "grantId");
97
+ const branch = requiredString(handle, "branch");
98
+ const expiresAt = requiredString(handle, "expiresAt");
99
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(grantId)) {
100
+ throw new Error("sandbox.publishGrantHandle.grantId is invalid.");
101
+ }
102
+ if (branch.length > 240)
103
+ throw new Error("sandbox.publishGrantHandle.branch is too long.");
104
+ if (!Number.isFinite(Date.parse(expiresAt)))
105
+ throw new Error("sandbox.publishGrantHandle.expiresAt is invalid.");
106
+ return { grantId, branch, expiresAt };
107
+ }
108
+ function parseSandboxResourceRequest(value) {
109
+ if (value === undefined || value === null) {
110
+ return {
111
+ sandboxSlots: 1,
112
+ cpuMillis: 2000,
113
+ workerMemoryLimitBytes: 2 * 1024 ** 3,
114
+ serviceMemoryLimitBytes: 0,
115
+ runtimeOverheadBytes: 128 * 1024 ** 2,
116
+ memoryBytes: 2 * 1024 ** 3 + 128 * 1024 ** 2,
117
+ workspaceBytes: 10 * 1024 ** 3,
118
+ pids: 512,
119
+ buildSlots: 1
120
+ };
121
+ }
122
+ const resources = asObject(value, "sandbox.requestedResources");
123
+ const memoryBytes = boundedInteger(resources, "memoryBytes", 128 * 1024 ** 2, 512 * 1024 ** 3);
124
+ const hasMemoryBreakdown = ["workerMemoryLimitBytes", "serviceMemoryLimitBytes", "runtimeOverheadBytes"]
125
+ .some(key => resources[key] !== undefined && resources[key] !== null);
126
+ const workerMemoryLimitBytes = hasMemoryBreakdown
127
+ ? boundedInteger(resources, "workerMemoryLimitBytes", 128 * 1024 ** 2, 512 * 1024 ** 3)
128
+ : memoryBytes;
129
+ const serviceMemoryLimitBytes = hasMemoryBreakdown
130
+ ? boundedInteger(resources, "serviceMemoryLimitBytes", 0, 512 * 1024 ** 3)
131
+ : 0;
132
+ const runtimeOverheadBytes = hasMemoryBreakdown
133
+ ? boundedInteger(resources, "runtimeOverheadBytes", 0, 64 * 1024 ** 3)
134
+ : 0;
135
+ if (workerMemoryLimitBytes + serviceMemoryLimitBytes + runtimeOverheadBytes !== memoryBytes) {
136
+ throw new Error("sandbox.requestedResources memory breakdown must equal memoryBytes.");
137
+ }
138
+ return {
139
+ sandboxSlots: boundedInteger(resources, "sandboxSlots", 1, 4),
140
+ cpuMillis: boundedInteger(resources, "cpuMillis", 100, 64_000),
141
+ workerMemoryLimitBytes,
142
+ serviceMemoryLimitBytes,
143
+ runtimeOverheadBytes,
144
+ memoryBytes,
145
+ workspaceBytes: boundedInteger(resources, "workspaceBytes", 1024 ** 3, 10 * 1024 ** 4),
146
+ pids: boundedInteger(resources, "pids", 32, 65_536),
147
+ buildSlots: boundedInteger(resources, "buildSlots", 0, 4)
148
+ };
149
+ }
150
+ function parseSandboxNetworkPolicy(value) {
151
+ if (value === undefined || value === null)
152
+ return { mode: "offline", allowedHosts: [] };
153
+ const policy = asObject(value, "sandbox.networkPolicy");
154
+ const mode = requiredString(policy, "mode");
155
+ if (mode !== "offline" && mode !== "public_allowlist" && mode !== "open_public") {
156
+ throw new Error("sandbox.networkPolicy.mode is invalid.");
157
+ }
158
+ const rawHosts = policy.allowedHosts ?? [];
159
+ if (!Array.isArray(rawHosts) || rawHosts.some((host) => typeof host !== "string")) {
160
+ throw new Error("sandbox.networkPolicy.allowedHosts must be a string array.");
161
+ }
162
+ const allowedHosts = [...new Set(rawHosts.map(host => host.trim().toLowerCase()).filter(Boolean))];
163
+ if (allowedHosts.length > 128 || allowedHosts.some(host => !/^(?:\*\.)?(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/u.test(host))) {
164
+ throw new Error("sandbox.networkPolicy.allowedHosts contains an invalid hostname.");
165
+ }
166
+ if (mode !== "public_allowlist" && allowedHosts.length > 0) {
167
+ throw new Error("sandbox.networkPolicy.allowedHosts requires public_allowlist mode.");
168
+ }
169
+ if (mode === "public_allowlist" && allowedHosts.length === 0) {
170
+ return { mode: "offline", allowedHosts: [] };
171
+ }
172
+ return { mode, allowedHosts };
173
+ }
33
174
  export function failureResult(summary, events = []) {
34
175
  return {
35
176
  schemaVersion: 1,
@@ -73,6 +214,7 @@ function parseCycleRun(value) {
73
214
  requestedBase: optionalString(cycle, "requestedBase") ?? "develop",
74
215
  baseBranch: optionalString(cycle, "baseBranch") ?? "develop",
75
216
  expectedCurrentBranch: optionalString(cycle, "expectedCurrentBranch"),
217
+ repairHeadSha: optionalString(cycle, "repairHeadSha"),
76
218
  attempt: requiredNumber(cycle, "attempt"),
77
219
  model: requiredString(cycle, "model")
78
220
  };
@@ -82,7 +224,9 @@ function parseSession(value) {
82
224
  return {
83
225
  id: requiredString(session, "id"),
84
226
  model: requiredString(session, "model"),
85
- lane: requiredString(session, "lane")
227
+ lane: requiredString(session, "lane"),
228
+ resumedFromSessionId: optionalString(session, "resumedFromSessionId"),
229
+ resumeProviderThreadId: optionalString(session, "resumeProviderThreadId")
86
230
  };
87
231
  }
88
232
  function parseLease(value) {
@@ -172,6 +316,16 @@ function parseApiKeySecretGrant(value) {
172
316
  expiresAt: requiredString(grant, "expiresAt")
173
317
  };
174
318
  }
319
+ function parseApiKeySecretGrantHandle(value) {
320
+ if (value === undefined || value === null)
321
+ return null;
322
+ const grant = asObject(value, "apiKeySecretGrantHandle");
323
+ return {
324
+ grantId: requiredString(grant, "grantId"),
325
+ provider: requiredString(grant, "provider"),
326
+ expiresAt: requiredString(grant, "expiresAt")
327
+ };
328
+ }
175
329
  function parseServerLocal(value) {
176
330
  const serverLocal = asObject(value, "serverLocal");
177
331
  return {
@@ -245,6 +399,7 @@ function parseQaScope(value) {
245
399
  schema_version: requiredNumber(qaScope, "schema_version"),
246
400
  surface: parseOptionalStringArray(qaScope.surface, "qaScope.surface"),
247
401
  required_evidence: parseOptionalStringArray(qaScope.required_evidence, "qaScope.required_evidence"),
402
+ required_capabilities: parseOptionalStringArray(qaScope.required_capabilities ?? qaScope.requiredCapabilities, "qaScope.required_capabilities"),
248
403
  not_applicable: parseOptionalStringArray(qaScope.not_applicable, "qaScope.not_applicable"),
249
404
  browser_required: optionalBoolean(qaScope, "browser_required") ?? optionalBoolean(qaScope, "browserRequired") ?? false,
250
405
  api_required: optionalBoolean(qaScope, "api_required") ?? optionalBoolean(qaScope, "apiRequired") ?? false,
@@ -271,6 +426,7 @@ function parseQaAppLaunchTarget(value) {
271
426
  command: optionalString(launchTarget, "command"),
272
427
  working_directory: optionalString(launchTarget, "working_directory"),
273
428
  ready_url: optionalString(launchTarget, "ready_url"),
429
+ managed_runtime_port: optionalString(launchTarget, "managed_runtime_port"),
274
430
  routes: Array.isArray(routes)
275
431
  ? routes.map((entry, index) => {
276
432
  if (typeof entry !== "string") {
@@ -549,6 +705,34 @@ function parseArtifacts(value) {
549
705
  };
550
706
  });
551
707
  }
708
+ function parsePriorPhaseArtifacts(value) {
709
+ if (value === undefined || value === null) {
710
+ return [];
711
+ }
712
+ if (!Array.isArray(value)) {
713
+ throw new Error("priorPhaseArtifacts must be an array when provided.");
714
+ }
715
+ return value.map((entry, index) => {
716
+ const artifact = asObject(entry, `priorPhaseArtifacts[${index}]`);
717
+ const phase = requiredString(artifact, "phase").trim().toLowerCase().replace(/-/g, "_");
718
+ if (phase !== "implementation" && phase !== "self_review" && phase !== "validation") {
719
+ throw new Error(`priorPhaseArtifacts[${index}].phase must be implementation, self_review, or validation.`);
720
+ }
721
+ return {
722
+ workItemId: requiredString(artifact, "workItemId"),
723
+ artifactId: requiredString(artifact, "artifactId"),
724
+ cycleRunId: requiredString(artifact, "cycleRunId"),
725
+ phase,
726
+ status: requiredString(artifact, "status"),
727
+ producedAt: requiredString(artifact, "producedAt"),
728
+ sourcePath: requiredString(artifact, "sourcePath"),
729
+ verdictJson: requiredString(artifact, "verdictJson"),
730
+ report: optionalString(artifact, "report") ?? "",
731
+ verdictContentHash: requiredString(artifact, "verdictContentHash").toLowerCase(),
732
+ reportContentHash: requiredString(artifact, "reportContentHash").toLowerCase()
733
+ };
734
+ });
735
+ }
552
736
  function asObject(value, label) {
553
737
  if (!value || typeof value !== "object" || Array.isArray(value)) {
554
738
  throw new Error(`${label} must be an object.`);
@@ -616,3 +800,10 @@ function requiredNumber(source, key) {
616
800
  }
617
801
  return value;
618
802
  }
803
+ function boundedInteger(source, key, minimum, maximum) {
804
+ const value = requiredNumber(source, key);
805
+ if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
806
+ throw new Error(`${key} must be an integer from ${minimum} through ${maximum}.`);
807
+ }
808
+ return value;
809
+ }
@@ -0,0 +1 @@
1
+ export declare function formatBytes(bytes: number): string;
@@ -0,0 +1,9 @@
1
+ export function formatBytes(bytes) {
2
+ if (!Number.isFinite(bytes) || bytes <= 0)
3
+ return "0 B";
4
+ const units = ["B", "KiB", "MiB", "GiB", "TiB"];
5
+ const power = Math.max(0, Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(1024))));
6
+ const value = bytes / 1024 ** power;
7
+ const precision = power === 0 || value >= 100 ? 0 : 1;
8
+ return `${value.toFixed(precision)} ${units[power]}`;
9
+ }
@@ -8,7 +8,8 @@ export class GitClient {
8
8
  const result = await this.processRunner.run({
9
9
  command: "git",
10
10
  args,
11
- cwd
11
+ cwd,
12
+ ...(args.includes("-z") ? { rawOutput: true } : {}),
12
13
  });
13
14
  if (result.exitCode !== 0) {
14
15
  throw new Error(`git ${args.join(" ")} failed: ${result.stderr.trim() || result.stdout.trim()}`);
@@ -1,4 +1,5 @@
1
1
  export declare function isSubPath(root: string, candidate: string): boolean;
2
2
  export declare function resolveExistingDirectoryPath(inputPath: string): Promise<string>;
3
+ export declare function resolvePathIdentity(inputPath: string): Promise<string>;
3
4
  export declare function ensureDirectory(inputPath: string): Promise<string>;
4
5
  export declare function safeSegment(value: string, fallback: string): string;
@@ -4,7 +4,9 @@ export function isSubPath(root, candidate) {
4
4
  const normalizedRoot = path.resolve(root);
5
5
  const normalizedCandidate = path.resolve(candidate);
6
6
  const relative = path.relative(normalizedRoot, normalizedCandidate);
7
- return relative === "" || (!!relative && !relative.startsWith("..") && !path.isAbsolute(relative));
7
+ return relative === "" || (relative !== ".."
8
+ && !relative.startsWith(`..${path.sep}`)
9
+ && !path.isAbsolute(relative));
8
10
  }
9
11
  export async function resolveExistingDirectoryPath(inputPath) {
10
12
  const stat = await fs.stat(inputPath);
@@ -13,6 +15,24 @@ export async function resolveExistingDirectoryPath(inputPath) {
13
15
  }
14
16
  return await fs.realpath(inputPath);
15
17
  }
18
+ export async function resolvePathIdentity(inputPath) {
19
+ let existingAncestor = path.resolve(inputPath);
20
+ const missingSegments = [];
21
+ while (true) {
22
+ try {
23
+ return path.join(await fs.realpath(existingAncestor), ...missingSegments);
24
+ }
25
+ catch (error) {
26
+ if (error.code !== "ENOENT")
27
+ throw error;
28
+ const parent = path.dirname(existingAncestor);
29
+ if (parent === existingAncestor)
30
+ throw error;
31
+ missingSegments.unshift(path.basename(existingAncestor));
32
+ existingAncestor = parent;
33
+ }
34
+ }
35
+ }
16
36
  export async function ensureDirectory(inputPath) {
17
37
  await fs.mkdir(inputPath, { recursive: true });
18
38
  return await resolveExistingDirectoryPath(inputPath);
@@ -0,0 +1,14 @@
1
+ export interface DotNetToolchainSelection {
2
+ readonly executablePath: string;
3
+ readonly rootPath: string;
4
+ readonly sdkVersion: string;
5
+ readonly requiredMajor: number;
6
+ }
7
+ export interface DotNetToolchainOptions {
8
+ readonly environment?: NodeJS.ProcessEnv;
9
+ readonly platform?: NodeJS.Platform;
10
+ readonly homeDirectory?: string;
11
+ readonly fileExists?: (candidate: string) => Promise<boolean>;
12
+ readonly listSdks?: (candidate: string) => Promise<string>;
13
+ }
14
+ export declare function configureDotNetToolchain(repoRoots: readonly string[], options?: DotNetToolchainOptions): Promise<DotNetToolchainSelection | null>;