patchwarden 0.4.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.
Files changed (153) hide show
  1. package/Check-PatchWarden-Health.cmd +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +526 -0
  4. package/Reset-PatchWarden-Tunnel-Key.cmd +6 -0
  5. package/Restart-PatchWarden.cmd +19 -0
  6. package/Start-PatchWarden-Tunnel.cmd +7 -0
  7. package/dist/config.d.ts +24 -0
  8. package/dist/config.js +131 -0
  9. package/dist/doctor.d.ts +10 -0
  10. package/dist/doctor.js +388 -0
  11. package/dist/errors.d.ts +16 -0
  12. package/dist/errors.js +27 -0
  13. package/dist/httpServer.d.ts +17 -0
  14. package/dist/httpServer.js +255 -0
  15. package/dist/index.d.ts +9 -0
  16. package/dist/index.js +24 -0
  17. package/dist/runner/changeCapture.d.ts +43 -0
  18. package/dist/runner/changeCapture.js +245 -0
  19. package/dist/runner/cli.d.ts +9 -0
  20. package/dist/runner/cli.js +26 -0
  21. package/dist/runner/runTask.d.ts +8 -0
  22. package/dist/runner/runTask.js +821 -0
  23. package/dist/runner/watch.d.ts +19 -0
  24. package/dist/runner/watch.js +136 -0
  25. package/dist/security/commandGuard.d.ts +22 -0
  26. package/dist/security/commandGuard.js +56 -0
  27. package/dist/security/contentRedaction.d.ts +12 -0
  28. package/dist/security/contentRedaction.js +65 -0
  29. package/dist/security/pathGuard.d.ts +3 -0
  30. package/dist/security/pathGuard.js +98 -0
  31. package/dist/security/planGuard.d.ts +1 -0
  32. package/dist/security/planGuard.js +65 -0
  33. package/dist/security/sensitiveGuard.d.ts +2 -0
  34. package/dist/security/sensitiveGuard.js +60 -0
  35. package/dist/smoke-test.d.ts +15 -0
  36. package/dist/smoke-test.js +989 -0
  37. package/dist/taskProgress.d.ts +6 -0
  38. package/dist/taskProgress.js +36 -0
  39. package/dist/taskRuntime.d.ts +10 -0
  40. package/dist/taskRuntime.js +25 -0
  41. package/dist/tools/auditTask.d.ts +19 -0
  42. package/dist/tools/auditTask.js +307 -0
  43. package/dist/tools/cancelTask.d.ts +30 -0
  44. package/dist/tools/cancelTask.js +64 -0
  45. package/dist/tools/createTask.d.ts +42 -0
  46. package/dist/tools/createTask.js +188 -0
  47. package/dist/tools/getPlan.d.ts +12 -0
  48. package/dist/tools/getPlan.js +29 -0
  49. package/dist/tools/getTaskFile.d.ts +24 -0
  50. package/dist/tools/getTaskFile.js +84 -0
  51. package/dist/tools/getTaskProgress.d.ts +1 -0
  52. package/dist/tools/getTaskProgress.js +4 -0
  53. package/dist/tools/getTaskStatus.d.ts +46 -0
  54. package/dist/tools/getTaskStatus.js +36 -0
  55. package/dist/tools/getTaskStdoutTail.d.ts +9 -0
  56. package/dist/tools/getTaskStdoutTail.js +56 -0
  57. package/dist/tools/getTaskSummary.d.ts +66 -0
  58. package/dist/tools/getTaskSummary.js +237 -0
  59. package/dist/tools/healthCheck.d.ts +79 -0
  60. package/dist/tools/healthCheck.js +230 -0
  61. package/dist/tools/killTask.d.ts +15 -0
  62. package/dist/tools/killTask.js +4 -0
  63. package/dist/tools/listAgents.d.ts +12 -0
  64. package/dist/tools/listAgents.js +42 -0
  65. package/dist/tools/listTasks.d.ts +36 -0
  66. package/dist/tools/listTasks.js +94 -0
  67. package/dist/tools/listWorkspace.d.ts +10 -0
  68. package/dist/tools/listWorkspace.js +54 -0
  69. package/dist/tools/readWorkspaceFile.d.ts +8 -0
  70. package/dist/tools/readWorkspaceFile.js +26 -0
  71. package/dist/tools/registry.d.ts +24 -0
  72. package/dist/tools/registry.js +566 -0
  73. package/dist/tools/retryTask.d.ts +8 -0
  74. package/dist/tools/retryTask.js +45 -0
  75. package/dist/tools/savePlan.d.ts +10 -0
  76. package/dist/tools/savePlan.js +28 -0
  77. package/dist/tools/taskOutputs.d.ts +49 -0
  78. package/dist/tools/taskOutputs.js +136 -0
  79. package/dist/tools/taskTemplates.d.ts +15 -0
  80. package/dist/tools/taskTemplates.js +116 -0
  81. package/dist/tools/toolCatalog.d.ts +19 -0
  82. package/dist/tools/toolCatalog.js +71 -0
  83. package/dist/tools/waitForTask.d.ts +25 -0
  84. package/dist/tools/waitForTask.js +59 -0
  85. package/dist/version.d.ts +2 -0
  86. package/dist/version.js +2 -0
  87. package/dist/watcherStatus.d.ts +20 -0
  88. package/dist/watcherStatus.js +77 -0
  89. package/docs/assets/patchwarden-chatgpt-demo.svg +30 -0
  90. package/docs/demo.md +58 -0
  91. package/docs/migration-from-safe-bifrost.md +31 -0
  92. package/docs/release-v0.3.0.md +43 -0
  93. package/docs/release-v0.4.0.md +74 -0
  94. package/examples/config.example.json +40 -0
  95. package/examples/openai-tunnel/README.md +48 -0
  96. package/examples/openai-tunnel/chatgpt-test-prompt.md +53 -0
  97. package/examples/openai-tunnel/tunnel-client.example.yaml +39 -0
  98. package/package.json +73 -0
  99. package/scripts/brand-check.js +44 -0
  100. package/scripts/doctor-smoke.js +52 -0
  101. package/scripts/get-patchwarden-health.ps1 +114 -0
  102. package/scripts/http-mcp-smoke.js +351 -0
  103. package/scripts/lifecycle-smoke.js +453 -0
  104. package/scripts/mcp-manifest-check.js +120 -0
  105. package/scripts/mcp-smoke.js +336 -0
  106. package/scripts/pack-clean.js +142 -0
  107. package/scripts/patchwarden-mcp-stdio.cmd +7 -0
  108. package/scripts/restart-patchwarden.ps1 +242 -0
  109. package/scripts/start-patchwarden-tunnel.ps1 +503 -0
  110. package/scripts/tunnel-supervisor-smoke.js +77 -0
  111. package/scripts/watcher-supervisor-smoke.js +195 -0
  112. package/src/config.ts +165 -0
  113. package/src/doctor.ts +438 -0
  114. package/src/errors.ts +26 -0
  115. package/src/httpServer.ts +277 -0
  116. package/src/index.ts +34 -0
  117. package/src/runner/changeCapture.ts +304 -0
  118. package/src/runner/cli.ts +34 -0
  119. package/src/runner/runTask.ts +935 -0
  120. package/src/runner/watch.ts +152 -0
  121. package/src/security/commandGuard.ts +97 -0
  122. package/src/security/contentRedaction.ts +85 -0
  123. package/src/security/pathGuard.ts +175 -0
  124. package/src/security/planGuard.ts +93 -0
  125. package/src/security/sensitiveGuard.ts +72 -0
  126. package/src/smoke-test.ts +1078 -0
  127. package/src/taskProgress.ts +41 -0
  128. package/src/taskRuntime.ts +37 -0
  129. package/src/tools/auditTask.ts +340 -0
  130. package/src/tools/cancelTask.ts +70 -0
  131. package/src/tools/createTask.ts +337 -0
  132. package/src/tools/getPlan.ts +48 -0
  133. package/src/tools/getTaskFile.ts +111 -0
  134. package/src/tools/getTaskProgress.ts +5 -0
  135. package/src/tools/getTaskStatus.ts +85 -0
  136. package/src/tools/getTaskStdoutTail.ts +61 -0
  137. package/src/tools/getTaskSummary.ts +307 -0
  138. package/src/tools/healthCheck.ts +234 -0
  139. package/src/tools/killTask.ts +5 -0
  140. package/src/tools/listAgents.ts +54 -0
  141. package/src/tools/listTasks.ts +139 -0
  142. package/src/tools/listWorkspace.ts +71 -0
  143. package/src/tools/readWorkspaceFile.ts +41 -0
  144. package/src/tools/registry.ts +666 -0
  145. package/src/tools/retryTask.ts +53 -0
  146. package/src/tools/savePlan.ts +46 -0
  147. package/src/tools/taskOutputs.ts +155 -0
  148. package/src/tools/taskTemplates.ts +162 -0
  149. package/src/tools/toolCatalog.ts +92 -0
  150. package/src/tools/waitForTask.ts +90 -0
  151. package/src/version.ts +2 -0
  152. package/src/watcherStatus.ts +102 -0
  153. package/tsconfig.json +17 -0
@@ -0,0 +1,242 @@
1
+ param(
2
+ [switch]$SkipBuild,
3
+ [switch]$SkipWatcher,
4
+ [switch]$WhatIf,
5
+ [int]$KillTimeoutSeconds = 10
6
+ )
7
+
8
+ $ErrorActionPreference = "Stop"
9
+ $ProgressPreference = "SilentlyContinue"
10
+
11
+ $ProjectRoot = Split-Path -Parent $PSScriptRoot
12
+ $ConfigPath = Join-Path $ProjectRoot "patchwarden.config.json"
13
+ $RuntimeDirectory = Join-Path $env:LOCALAPPDATA "patchwarden\runtime"
14
+
15
+ Write-Host ""
16
+ Write-Host "========================================" -ForegroundColor Cyan
17
+ Write-Host " PatchWarden One-Click Restart" -ForegroundColor Cyan
18
+ Write-Host "========================================" -ForegroundColor Cyan
19
+ Write-Host ""
20
+
21
+ # -- 1. Find PatchWarden processes ----------------------------------
22
+
23
+ Write-Host "[1/4] Scanning for PatchWarden processes..." -ForegroundColor Yellow
24
+
25
+ $processesToKill = @()
26
+ try {
27
+ $allProcesses = Get-CimInstance Win32_Process
28
+ $byPid = @{}
29
+ foreach ($process in $allProcesses) { $byPid[[int]$process.ProcessId] = $process }
30
+ $seedIds = New-Object System.Collections.Generic.HashSet[int]
31
+ $tunnelStatusPath = Join-Path $RuntimeDirectory "tunnel-status.json"
32
+ $watcherStatusPath = Join-Path $RuntimeDirectory "watcher-status.json"
33
+ if (Test-Path -LiteralPath $tunnelStatusPath) {
34
+ $state = Get-Content -LiteralPath $tunnelStatusPath -Raw | ConvertFrom-Json
35
+ $candidate = $byPid[[int]$state.pid]
36
+ if ($candidate -and [string]$candidate.CommandLine -match '(?i)tunnel-client\.exe.*run.*patchwarden') {
37
+ [void]$seedIds.Add([int]$candidate.ProcessId)
38
+ }
39
+ }
40
+ if (Test-Path -LiteralPath $watcherStatusPath) {
41
+ $state = Get-Content -LiteralPath $watcherStatusPath -Raw | ConvertFrom-Json
42
+ $watcherCandidate = $byPid[[int]$state.pid]
43
+ if ($watcherCandidate -and [string]$watcherCandidate.CommandLine -like "*$ProjectRoot*dist*runner*watch.js*") {
44
+ [void]$seedIds.Add([int]$watcherCandidate.ProcessId)
45
+ }
46
+ $launcherCandidate = $byPid[[int]$state.launcher_pid]
47
+ if ($launcherCandidate -and [string]$launcherCandidate.CommandLine -like "*$ProjectRoot*start-patchwarden-tunnel.ps1*") {
48
+ [void]$seedIds.Add([int]$launcherCandidate.ProcessId)
49
+ }
50
+ }
51
+ foreach ($seed in @($seedIds)) {
52
+ $current = $byPid[$seed]
53
+ while ($current -and [int]$current.ParentProcessId -gt 0) {
54
+ $parent = $byPid[[int]$current.ParentProcessId]
55
+ if (-not $parent) { break }
56
+ if ([string]$parent.CommandLine -like "*$ProjectRoot*start-patchwarden-tunnel.ps1*") {
57
+ [void]$seedIds.Add([int]$parent.ProcessId)
58
+ }
59
+ $current = $parent
60
+ }
61
+ }
62
+ $ownedIds = New-Object System.Collections.Generic.HashSet[int]
63
+ foreach ($seed in $seedIds) { [void]$ownedIds.Add($seed) }
64
+ $changed = $true
65
+ while ($changed) {
66
+ $changed = $false
67
+ foreach ($process in $allProcesses) {
68
+ if ($ownedIds.Contains([int]$process.ParentProcessId) -and -not $ownedIds.Contains([int]$process.ProcessId)) {
69
+ [void]$ownedIds.Add([int]$process.ProcessId)
70
+ $changed = $true
71
+ }
72
+ }
73
+ }
74
+ foreach ($ownedId in $ownedIds) {
75
+ $process = $byPid[$ownedId]
76
+ if (-not $process -or $process.ProcessId -eq $PID) { continue }
77
+ $commandLine = [string]$process.CommandLine
78
+ $processesToKill += [ordered]@{
79
+ pid = $process.ProcessId
80
+ name = $process.Name
81
+ label = if ($seedIds.Contains([int]$process.ProcessId)) { "owned runtime" } else { "owned child" }
82
+ command = $commandLine.Substring(0, [Math]::Min(200, $commandLine.Length))
83
+ }
84
+ }
85
+ } catch {
86
+ Write-Warning "Could not enumerate processes: $_"
87
+ }
88
+
89
+ if ($processesToKill.Count -eq 0) {
90
+ Write-Host " No PatchWarden processes found." -ForegroundColor Green
91
+ } else {
92
+ Write-Host " Found $($processesToKill.Count) PatchWarden process(es):" -ForegroundColor White
93
+ foreach ($proc in $processesToKill) {
94
+ Write-Host " PID $($proc.pid) - $($proc.label) ($($proc.name))" -ForegroundColor Gray
95
+ }
96
+ }
97
+
98
+ # -- 2. Kill processes -----------------------------------------------
99
+
100
+ if ($processesToKill.Count -gt 0) {
101
+ Write-Host ""
102
+ Write-Host "[2/4] Stopping PatchWarden processes..." -ForegroundColor Yellow
103
+
104
+ if ($WhatIf) {
105
+ Write-Host " WHAT-IF: Would stop $($processesToKill.Count) process(es)." -ForegroundColor Magenta
106
+ } else {
107
+ foreach ($proc in $processesToKill) {
108
+ try {
109
+ $process = Get-Process -Id $proc.pid -ErrorAction Stop
110
+ Write-Host " Stopping PID $($proc.pid) ($($proc.label))..." -ForegroundColor Gray
111
+ $process.Kill()
112
+ $exited = $process.WaitForExit($KillTimeoutSeconds * 1000)
113
+ if ($exited) {
114
+ Write-Host " Stopped." -ForegroundColor Green
115
+ } else {
116
+ Write-Host " Kill sent but process did not exit within ${KillTimeoutSeconds}s." -ForegroundColor Yellow
117
+ }
118
+ } catch {
119
+ Write-Host " PID $($proc.pid) already exited or inaccessible - skipped." -ForegroundColor DarkGray
120
+ }
121
+ }
122
+
123
+ }
124
+ }
125
+
126
+ # -- 3. Rebuild ------------------------------------------------------
127
+
128
+ Write-Host ""
129
+ if ($SkipBuild) {
130
+ Write-Host "[3/4] Skipping build (--SkipBuild)." -ForegroundColor DarkYellow
131
+ } else {
132
+ Write-Host "[3/4] Rebuilding PatchWarden..." -ForegroundColor Yellow
133
+
134
+ if ($WhatIf) {
135
+ Write-Host " WHAT-IF: Would run npm.cmd run build." -ForegroundColor Magenta
136
+ } else {
137
+ Push-Location $ProjectRoot
138
+ try {
139
+ $buildResult = npm.cmd run build 2>&1
140
+ if ($LASTEXITCODE -ne 0) {
141
+ Write-Warning "Build completed with warnings (exit code $LASTEXITCODE)."
142
+ Write-Host ($buildResult -join "`n") -ForegroundColor DarkGray
143
+ } else {
144
+ Write-Host " Build successful." -ForegroundColor Green
145
+ }
146
+ } catch {
147
+ Write-Warning "Build failed: $_"
148
+ Write-Host " Continuing anyway - dist may be stale." -ForegroundColor DarkRed
149
+ } finally {
150
+ Pop-Location
151
+ }
152
+ }
153
+ }
154
+
155
+ # -- Clear stale runtime state ----------------------------------------
156
+
157
+ if (-not $WhatIf) {
158
+ # LOCALAPPDATA runtime files (launcher-managed supervision state)
159
+ if (Test-Path -LiteralPath $RuntimeDirectory) {
160
+ try {
161
+ $staleFiles = @(
162
+ Join-Path $RuntimeDirectory "tunnel-health-url.txt",
163
+ Join-Path $RuntimeDirectory "tunnel-client.pid",
164
+ Join-Path $RuntimeDirectory "watcher-status.json",
165
+ Join-Path $RuntimeDirectory "tunnel-status.json"
166
+ )
167
+ foreach ($file in $staleFiles) {
168
+ if (Test-Path -LiteralPath $file) {
169
+ Remove-Item -LiteralPath $file -Force -ErrorAction SilentlyContinue
170
+ }
171
+ }
172
+ } catch {}
173
+ }
174
+
175
+ # Workspace watcher heartbeat - CRITICAL: the killed watcher stops
176
+ # writing this file, but the stale record can fool a fresh launcher
177
+ # into treating it as an "external_healthy" watcher (age < stale
178
+ # threshold right after kill), which prevents the launcher from
179
+ # starting its own watcher. Removing it forces a clean start.
180
+ try {
181
+ if (Test-Path -LiteralPath $ConfigPath) {
182
+ $cfg = Get-Content -LiteralPath $ConfigPath -Raw | ConvertFrom-Json
183
+ $tasksDir = Join-Path $cfg.workspaceRoot $cfg.tasksDir
184
+ $heartbeatFile = Join-Path (Split-Path -Parent $tasksDir) "watcher-heartbeat.json"
185
+ if (Test-Path -LiteralPath $heartbeatFile) {
186
+ Remove-Item -LiteralPath $heartbeatFile -Force -ErrorAction SilentlyContinue
187
+ Write-Host " Cleared stale watcher heartbeat." -ForegroundColor Green
188
+ }
189
+ }
190
+ } catch {}
191
+ }
192
+
193
+ # -- 4. Relaunch tunnel ----------------------------------------------
194
+
195
+ Write-Host ""
196
+ Write-Host "[4/4] Launching PatchWarden tunnel..." -ForegroundColor Yellow
197
+
198
+ if ($WhatIf) {
199
+ Write-Host " WHAT-IF: Would launch Start-PatchWarden-Tunnel.cmd." -ForegroundColor Magenta
200
+ Write-Host ""
201
+ Write-Host "========================================" -ForegroundColor Cyan
202
+ Write-Host " Restart plan complete (--WhatIf)." -ForegroundColor Cyan
203
+ Write-Host "========================================" -ForegroundColor Cyan
204
+ Write-Host ""
205
+ exit 0
206
+ }
207
+
208
+ # Relaunch the tunnel in a new PowerShell window.
209
+ # Prefer Start-PatchWarden-Tunnel.local.cmd (your saved config) over the generic launcher.
210
+ $localLauncher = Join-Path $ProjectRoot "Start-PatchWarden-Tunnel.local.cmd"
211
+ $genericLauncher = Join-Path $ProjectRoot "Start-PatchWarden-Tunnel.cmd"
212
+ $launcherPath = if (Test-Path -LiteralPath $localLauncher) { $localLauncher } else { $genericLauncher }
213
+
214
+ if (-not (Test-Path -LiteralPath $launcherPath)) {
215
+ Write-Error "Launcher not found: $launcherPath"
216
+ exit 1
217
+ }
218
+
219
+ $launcherName = Split-Path -Leaf $launcherPath
220
+ Write-Host " Using launcher: $launcherName" -ForegroundColor White
221
+ if ($launcherPath -eq $localLauncher) {
222
+ Write-Host " (local config with pre-set TUNNEL_ID / TUNNEL_CLIENT_EXE)" -ForegroundColor DarkGray
223
+ }
224
+ Write-Host ""
225
+
226
+ $args = @(
227
+ "-NoProfile",
228
+ "-NoExit",
229
+ "-Command",
230
+ "Set-Location '$ProjectRoot'; & '$launcherPath'"
231
+ )
232
+ if ($SkipWatcher) {
233
+ $args[3] = "Set-Location '$ProjectRoot'; `$env:PATCHWARDEN_SKIP_WATCHER='1'; & '$launcherPath'"
234
+ }
235
+
236
+ Start-Process powershell.exe -ArgumentList $args
237
+
238
+ Write-Host "========================================" -ForegroundColor Cyan
239
+ Write-Host " Restart complete. Tunnel launcher window opened." -ForegroundColor Cyan
240
+ Write-Host " Use Check-PatchWarden-Health.cmd to verify." -ForegroundColor Cyan
241
+ Write-Host "========================================" -ForegroundColor Cyan
242
+ Write-Host ""