@loucompanion/forge-bridge 0.1.3-dev.ba7d36726eda → 0.1.3-dev.bca7d0ccee53

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 (73) hide show
  1. package/dist/bridge/bridge.base.d.ts +2 -1
  2. package/dist/bridge/bridge.service.d.ts +8 -0
  3. package/dist/bridge/bridge.service.js +184 -12
  4. package/dist/bridge/bridge.types.d.ts +37 -0
  5. package/dist/cli/cli.help.js +1 -1
  6. package/dist/cli/cli.service.js +1 -1
  7. package/dist/cli/local-config.js +2 -1
  8. package/dist/runtime/attempt-node-runtime-launcher.d.ts +3 -1
  9. package/dist/runtime/attempt-node-runtime-launcher.js +62 -11
  10. package/dist/runtime/attempt-process-supervisor-registry.js +1 -1
  11. package/dist/runtime/attempt-process-supervisor.d.ts +12 -0
  12. package/dist/runtime/attempt-process-supervisor.js +75 -15
  13. package/dist/runtime/generated-output-reset.d.ts +10 -0
  14. package/dist/runtime/generated-output-reset.js +103 -0
  15. package/dist/runtime/host-listener-inspector.d.ts +16 -0
  16. package/dist/runtime/host-listener-inspector.js +143 -4
  17. package/dist/runtime/host-runtime-contract.d.ts +9 -1
  18. package/dist/runtime/host-runtime-contract.js +411 -6
  19. package/dist/runtime/host-runtime-lease.d.ts +12 -1
  20. package/dist/runtime/host-runtime-lease.js +271 -50
  21. package/dist/runtime/host-runtime-promotion.d.ts +2 -0
  22. package/dist/runtime/host-runtime-promotion.js +35 -4
  23. package/dist/runtime/node-host-runtime-adapter.d.ts +7 -0
  24. package/dist/runtime/node-host-runtime-adapter.js +71 -8
  25. package/dist/runtime/playwright-host-runtime-adapter.js +84 -0
  26. package/dist/sandbox/preflight.d.ts +9 -0
  27. package/dist/sandbox/preflight.js +39 -4
  28. package/dist/sandbox/workspace.service.js +7 -2
  29. package/dist/session/managed-attempt-tools.d.ts +17 -0
  30. package/dist/session/managed-attempt-tools.js +712 -0
  31. package/dist/session/phase-completion.artifacts.js +9 -2
  32. package/dist/session/phase-completion.d.ts +11 -2
  33. package/dist/session/phase-completion.helpers.d.ts +5 -0
  34. package/dist/session/phase-completion.helpers.js +45 -9
  35. package/dist/session/phase-completion.js +12 -3
  36. package/dist/session/phase-completion.prompts.d.ts +3 -3
  37. package/dist/session/phase-completion.prompts.js +21 -6
  38. package/dist/session/phase-completion.runtime.d.ts +13 -1
  39. package/dist/session/phase-completion.runtime.js +183 -8
  40. package/dist/session/phase-completion.schemas.js +108 -3
  41. package/dist/session/phase-completion.validation.d.ts +4 -1
  42. package/dist/session/phase-completion.validation.js +144 -18
  43. package/dist/session/provider-cli/ci-repair-readiness.d.ts +8 -0
  44. package/dist/session/provider-cli/ci-repair-readiness.js +95 -0
  45. package/dist/session/provider-cli/provider-cli.deterministic.js +47 -1
  46. package/dist/session/provider-cli/provider-cli.process.d.ts +14 -0
  47. package/dist/session/provider-cli/provider-cli.process.js +176 -18
  48. package/dist/session/provider-cli/provider-cli.prompts.js +30 -8
  49. package/dist/session/provider-cli/provider-cli.qa-sidecars.js +1 -0
  50. package/dist/session/provider-cli/provider-cli.service.d.ts +19 -2
  51. package/dist/session/provider-cli/provider-cli.service.js +390 -83
  52. package/dist/session/provider-cli/provider-cli.types.d.ts +3 -0
  53. package/dist/session/provider-cli/provider-output-state.d.ts +2 -0
  54. package/dist/session/provider-cli/provider-output-state.js +30 -2
  55. package/dist/session/session.base.d.ts +2 -1
  56. package/dist/session/session.service.d.ts +2 -1
  57. package/dist/session/session.service.js +303 -30
  58. package/dist/session/session.types.d.ts +38 -0
  59. package/dist/session/session.types.js +17 -0
  60. package/dist/shared/process/host-process-supervisor.d.ts +18 -1
  61. package/dist/shared/process/host-process-supervisor.js +94 -7
  62. package/dist/shared/process/process.d.ts +1 -0
  63. package/dist/shared/process/process.js +1 -0
  64. package/dist/version.d.ts +1 -1
  65. package/dist/version.js +1 -1
  66. package/dist/worktree/artifact-injector.d.ts +3 -2
  67. package/dist/worktree/artifact-injector.js +43 -4
  68. package/dist/worktree/dependency-warmer.d.ts +10 -1
  69. package/dist/worktree/dependency-warmer.js +94 -5
  70. package/dist/worktree/worktree.service.d.ts +1 -0
  71. package/dist/worktree/worktree.service.js +12 -1
  72. package/package.json +1 -1
  73. package/runtime/windows-job-supervisor.ps1 +89 -20
@@ -4,7 +4,7 @@ param(
4
4
  [string]$Mode,
5
5
 
6
6
  [Parameter(Mandatory = $true)]
7
- [string]$Payload,
7
+ [string]$PayloadPath,
8
8
 
9
9
  [string]$GateName
10
10
  )
@@ -159,8 +159,10 @@ public static class ForgeWindowsJob
159
159
  "@
160
160
 
161
161
  function Read-ForgeSupervisorPayload {
162
- $bytes = [Convert]::FromBase64String($Payload)
163
- $json = [Text.Encoding]::UTF8.GetString($bytes)
162
+ if (-not [IO.Path]::IsPathRooted($PayloadPath)) {
163
+ throw "The supervisor payload path must be absolute."
164
+ }
165
+ $json = [IO.File]::ReadAllText($PayloadPath, [Text.Encoding]::UTF8)
164
166
  return $json | ConvertFrom-Json
165
167
  }
166
168
 
@@ -170,22 +172,85 @@ function New-ForgeChildProcess(
170
172
  [string]$workingDirectory,
171
173
  [bool]$redirectStreams
172
174
  ) {
173
- $startInfo = New-Object System.Diagnostics.ProcessStartInfo
174
- $startInfo.FileName = $command
175
- $startInfo.Arguments = [ForgeWindowsJob]::BuildArguments($arguments)
176
- $startInfo.WorkingDirectory = $workingDirectory
177
- $startInfo.UseShellExecute = $false
178
- $startInfo.CreateNoWindow = $true
179
- $startInfo.RedirectStandardInput = $redirectStreams
180
- $startInfo.RedirectStandardOutput = $redirectStreams
181
- $startInfo.RedirectStandardError = $redirectStreams
182
-
183
- $child = New-Object System.Diagnostics.Process
184
- $child.StartInfo = $startInfo
185
- if (-not $child.Start()) {
186
- throw "Failed to start supervised process '$command'."
175
+ $maximumAttempts = 3
176
+ for ($attempt = 1; $attempt -le $maximumAttempts; $attempt += 1) {
177
+ $startInfo = New-Object System.Diagnostics.ProcessStartInfo
178
+ $startInfo.FileName = $command
179
+ $startInfo.Arguments = [ForgeWindowsJob]::BuildArguments($arguments)
180
+ $startInfo.WorkingDirectory = $workingDirectory
181
+ $startInfo.UseShellExecute = $false
182
+ $startInfo.CreateNoWindow = $true
183
+ $startInfo.RedirectStandardInput = $redirectStreams
184
+ $startInfo.RedirectStandardOutput = $redirectStreams
185
+ $startInfo.RedirectStandardError = $redirectStreams
186
+
187
+ $child = New-Object System.Diagnostics.Process
188
+ $child.StartInfo = $startInfo
189
+ try {
190
+ if (-not $child.Start()) {
191
+ throw "Failed to start supervised process '$command'."
192
+ }
193
+ $child | Add-Member -NotePropertyName ForgeStartAttempt -NotePropertyValue $attempt
194
+ return $child
195
+ }
196
+ catch {
197
+ $nativeError = $_.Exception
198
+ while ($nativeError.InnerException) {
199
+ $nativeError = $nativeError.InnerException
200
+ }
201
+ $retryable = $nativeError -is [ComponentModel.Win32Exception] -and $nativeError.NativeErrorCode -in @(5, 32, 33)
202
+ $child.Dispose()
203
+ if (-not $retryable -or $attempt -eq $maximumAttempts) {
204
+ throw
205
+ }
206
+ Start-Sleep -Milliseconds (100 * $attempt)
207
+ }
208
+ }
209
+ }
210
+
211
+ function Write-ForgeProviderReady([object]$request, [Diagnostics.Process]$provider) {
212
+ $readyPath = [string]$request.readyPath
213
+ if ([string]::IsNullOrWhiteSpace($readyPath) -or -not [IO.Path]::IsPathRooted($readyPath)) {
214
+ throw "The provider-ready path must be absolute."
215
+ }
216
+ $payloadDirectory = [IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($PayloadPath))
217
+ $readyDirectory = [IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($readyPath))
218
+ if (-not [string]::Equals($payloadDirectory, $readyDirectory, [StringComparison]::OrdinalIgnoreCase)) {
219
+ throw "The provider-ready path must be beside the supervisor payload."
220
+ }
221
+
222
+ $ready = @{
223
+ schemaVersion = 1
224
+ supervisorId = [string]$request.supervisorId
225
+ rootPid = [int]$env:FORGE_SUPERVISOR_ROOT_PID
226
+ rootIdentity = [string]$env:FORGE_SUPERVISOR_ROOT_IDENTITY
227
+ providerPid = $provider.Id
228
+ providerCreatedAt = $provider.StartTime.ToUniversalTime().ToString("O")
229
+ providerIdentity = "win32:$($provider.StartTime.ToUniversalTime().Ticks)"
230
+ startAttempt = [int]$provider.ForgeStartAttempt
231
+ } | ConvertTo-Json -Compress
232
+ $temporaryPath = "$readyPath.$([Guid]::NewGuid().ToString('N')).tmp"
233
+ [IO.File]::WriteAllText($temporaryPath, "$ready`n", (New-Object Text.UTF8Encoding($false)))
234
+ [IO.File]::Move($temporaryPath, $readyPath)
235
+ }
236
+
237
+ function Wait-ForgeProviderStartGrant([object]$request) {
238
+ $grantPath = [string]$request.startGrantPath
239
+ if ([string]::IsNullOrWhiteSpace($grantPath) -or -not [IO.Path]::IsPathRooted($grantPath)) {
240
+ throw "The provider start-grant path must be absolute."
241
+ }
242
+ $payloadDirectory = [IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($PayloadPath))
243
+ $grantDirectory = [IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($grantPath))
244
+ if (-not [string]::Equals($payloadDirectory, $grantDirectory, [StringComparison]::OrdinalIgnoreCase)) {
245
+ throw "The provider start-grant path must be beside the supervisor payload."
246
+ }
247
+ for ($attempt = 0; $attempt -lt 1200; $attempt += 1) {
248
+ if ([IO.File]::Exists($grantPath)) {
249
+ return
250
+ }
251
+ Start-Sleep -Milliseconds 25
187
252
  }
188
- return $child
253
+ throw "Timed out waiting for the provider start grant."
189
254
  }
190
255
 
191
256
  function Start-ForgeOutputCopies([Diagnostics.Process]$child) {
@@ -220,7 +285,9 @@ if ($Mode -eq "Inner") {
220
285
  }
221
286
 
222
287
  $provider = New-ForgeChildProcess ([string]$request.command) @($request.args) ([string]$request.cwd) $true
288
+ Write-ForgeProviderReady $request $provider
223
289
  $copies = Start-ForgeOutputCopies $provider
290
+ Wait-ForgeProviderStartGrant $request
224
291
  Write-ForgeStandardInput $provider $inputText
225
292
  $provider.WaitForExit()
226
293
  if (-not [Threading.Tasks.Task]::WaitAll([Threading.Tasks.Task[]]$copies, 1000)) {
@@ -232,6 +299,8 @@ if ($Mode -eq "Inner") {
232
299
 
233
300
  $inputText = [Console]::In.ReadToEnd()
234
301
  $request = Read-ForgeSupervisorPayload
302
+ $env:FORGE_SUPERVISOR_ROOT_PID = [string]$PID
303
+ $env:FORGE_SUPERVISOR_ROOT_IDENTITY = "win32:$([Diagnostics.Process]::GetCurrentProcess().StartTime.ToUniversalTime().Ticks)"
235
304
  $parent = [Diagnostics.Process]::GetProcessById([int]$request.parentPid)
236
305
  $jobName = "Local\Forge-$([string]$request.supervisorId)"
237
306
  $job = [ForgeWindowsJob]::CreateKillOnCloseJob($jobName)
@@ -252,8 +321,8 @@ try {
252
321
  $PSCommandPath,
253
322
  "-Mode",
254
323
  "Inner",
255
- "-Payload",
256
- $Payload,
324
+ "-PayloadPath",
325
+ $PayloadPath,
257
326
  "-GateName",
258
327
  $gateNameValue
259
328
  )