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.
- package/Check-PatchWarden-Health.cmd +6 -0
- package/LICENSE +21 -0
- package/README.md +526 -0
- package/Reset-PatchWarden-Tunnel-Key.cmd +6 -0
- package/Restart-PatchWarden.cmd +19 -0
- package/Start-PatchWarden-Tunnel.cmd +7 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +131 -0
- package/dist/doctor.d.ts +10 -0
- package/dist/doctor.js +388 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.js +27 -0
- package/dist/httpServer.d.ts +17 -0
- package/dist/httpServer.js +255 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +24 -0
- package/dist/runner/changeCapture.d.ts +43 -0
- package/dist/runner/changeCapture.js +245 -0
- package/dist/runner/cli.d.ts +9 -0
- package/dist/runner/cli.js +26 -0
- package/dist/runner/runTask.d.ts +8 -0
- package/dist/runner/runTask.js +821 -0
- package/dist/runner/watch.d.ts +19 -0
- package/dist/runner/watch.js +136 -0
- package/dist/security/commandGuard.d.ts +22 -0
- package/dist/security/commandGuard.js +56 -0
- package/dist/security/contentRedaction.d.ts +12 -0
- package/dist/security/contentRedaction.js +65 -0
- package/dist/security/pathGuard.d.ts +3 -0
- package/dist/security/pathGuard.js +98 -0
- package/dist/security/planGuard.d.ts +1 -0
- package/dist/security/planGuard.js +65 -0
- package/dist/security/sensitiveGuard.d.ts +2 -0
- package/dist/security/sensitiveGuard.js +60 -0
- package/dist/smoke-test.d.ts +15 -0
- package/dist/smoke-test.js +989 -0
- package/dist/taskProgress.d.ts +6 -0
- package/dist/taskProgress.js +36 -0
- package/dist/taskRuntime.d.ts +10 -0
- package/dist/taskRuntime.js +25 -0
- package/dist/tools/auditTask.d.ts +19 -0
- package/dist/tools/auditTask.js +307 -0
- package/dist/tools/cancelTask.d.ts +30 -0
- package/dist/tools/cancelTask.js +64 -0
- package/dist/tools/createTask.d.ts +42 -0
- package/dist/tools/createTask.js +188 -0
- package/dist/tools/getPlan.d.ts +12 -0
- package/dist/tools/getPlan.js +29 -0
- package/dist/tools/getTaskFile.d.ts +24 -0
- package/dist/tools/getTaskFile.js +84 -0
- package/dist/tools/getTaskProgress.d.ts +1 -0
- package/dist/tools/getTaskProgress.js +4 -0
- package/dist/tools/getTaskStatus.d.ts +46 -0
- package/dist/tools/getTaskStatus.js +36 -0
- package/dist/tools/getTaskStdoutTail.d.ts +9 -0
- package/dist/tools/getTaskStdoutTail.js +56 -0
- package/dist/tools/getTaskSummary.d.ts +66 -0
- package/dist/tools/getTaskSummary.js +237 -0
- package/dist/tools/healthCheck.d.ts +79 -0
- package/dist/tools/healthCheck.js +230 -0
- package/dist/tools/killTask.d.ts +15 -0
- package/dist/tools/killTask.js +4 -0
- package/dist/tools/listAgents.d.ts +12 -0
- package/dist/tools/listAgents.js +42 -0
- package/dist/tools/listTasks.d.ts +36 -0
- package/dist/tools/listTasks.js +94 -0
- package/dist/tools/listWorkspace.d.ts +10 -0
- package/dist/tools/listWorkspace.js +54 -0
- package/dist/tools/readWorkspaceFile.d.ts +8 -0
- package/dist/tools/readWorkspaceFile.js +26 -0
- package/dist/tools/registry.d.ts +24 -0
- package/dist/tools/registry.js +566 -0
- package/dist/tools/retryTask.d.ts +8 -0
- package/dist/tools/retryTask.js +45 -0
- package/dist/tools/savePlan.d.ts +10 -0
- package/dist/tools/savePlan.js +28 -0
- package/dist/tools/taskOutputs.d.ts +49 -0
- package/dist/tools/taskOutputs.js +136 -0
- package/dist/tools/taskTemplates.d.ts +15 -0
- package/dist/tools/taskTemplates.js +116 -0
- package/dist/tools/toolCatalog.d.ts +19 -0
- package/dist/tools/toolCatalog.js +71 -0
- package/dist/tools/waitForTask.d.ts +25 -0
- package/dist/tools/waitForTask.js +59 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/dist/watcherStatus.d.ts +20 -0
- package/dist/watcherStatus.js +77 -0
- package/docs/assets/patchwarden-chatgpt-demo.svg +30 -0
- package/docs/demo.md +58 -0
- package/docs/migration-from-safe-bifrost.md +31 -0
- package/docs/release-v0.3.0.md +43 -0
- package/docs/release-v0.4.0.md +74 -0
- package/examples/config.example.json +40 -0
- package/examples/openai-tunnel/README.md +48 -0
- package/examples/openai-tunnel/chatgpt-test-prompt.md +53 -0
- package/examples/openai-tunnel/tunnel-client.example.yaml +39 -0
- package/package.json +73 -0
- package/scripts/brand-check.js +44 -0
- package/scripts/doctor-smoke.js +52 -0
- package/scripts/get-patchwarden-health.ps1 +114 -0
- package/scripts/http-mcp-smoke.js +351 -0
- package/scripts/lifecycle-smoke.js +453 -0
- package/scripts/mcp-manifest-check.js +120 -0
- package/scripts/mcp-smoke.js +336 -0
- package/scripts/pack-clean.js +142 -0
- package/scripts/patchwarden-mcp-stdio.cmd +7 -0
- package/scripts/restart-patchwarden.ps1 +242 -0
- package/scripts/start-patchwarden-tunnel.ps1 +503 -0
- package/scripts/tunnel-supervisor-smoke.js +77 -0
- package/scripts/watcher-supervisor-smoke.js +195 -0
- package/src/config.ts +165 -0
- package/src/doctor.ts +438 -0
- package/src/errors.ts +26 -0
- package/src/httpServer.ts +277 -0
- package/src/index.ts +34 -0
- package/src/runner/changeCapture.ts +304 -0
- package/src/runner/cli.ts +34 -0
- package/src/runner/runTask.ts +935 -0
- package/src/runner/watch.ts +152 -0
- package/src/security/commandGuard.ts +97 -0
- package/src/security/contentRedaction.ts +85 -0
- package/src/security/pathGuard.ts +175 -0
- package/src/security/planGuard.ts +93 -0
- package/src/security/sensitiveGuard.ts +72 -0
- package/src/smoke-test.ts +1078 -0
- package/src/taskProgress.ts +41 -0
- package/src/taskRuntime.ts +37 -0
- package/src/tools/auditTask.ts +340 -0
- package/src/tools/cancelTask.ts +70 -0
- package/src/tools/createTask.ts +337 -0
- package/src/tools/getPlan.ts +48 -0
- package/src/tools/getTaskFile.ts +111 -0
- package/src/tools/getTaskProgress.ts +5 -0
- package/src/tools/getTaskStatus.ts +85 -0
- package/src/tools/getTaskStdoutTail.ts +61 -0
- package/src/tools/getTaskSummary.ts +307 -0
- package/src/tools/healthCheck.ts +234 -0
- package/src/tools/killTask.ts +5 -0
- package/src/tools/listAgents.ts +54 -0
- package/src/tools/listTasks.ts +139 -0
- package/src/tools/listWorkspace.ts +71 -0
- package/src/tools/readWorkspaceFile.ts +41 -0
- package/src/tools/registry.ts +666 -0
- package/src/tools/retryTask.ts +53 -0
- package/src/tools/savePlan.ts +46 -0
- package/src/tools/taskOutputs.ts +155 -0
- package/src/tools/taskTemplates.ts +162 -0
- package/src/tools/toolCatalog.ts +92 -0
- package/src/tools/waitForTask.ts +90 -0
- package/src/version.ts +2 -0
- package/src/watcherStatus.ts +102 -0
- package/tsconfig.json +17 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PatchWarden contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
# PatchWarden
|
|
2
|
+
|
|
3
|
+
Development version: **v0.4.0** (not yet published). See the
|
|
4
|
+
[v0.4.0 release notes](docs/release-v0.4.0.md).
|
|
5
|
+
|
|
6
|
+
> **Renamed in v0.4.0:** PatchWarden replaces the former Safe-Bifrost package.
|
|
7
|
+
> This is an intentional pre-1.0 breaking rename with new CLI, environment,
|
|
8
|
+
> configuration, and runtime paths. See the
|
|
9
|
+
> [migration guide](docs/migration-from-safe-bifrost.md).
|
|
10
|
+
|
|
11
|
+
PatchWarden is a local Model Context Protocol (MCP) bridge for safe
|
|
12
|
+
plan-and-execute coding workflows.
|
|
13
|
+
|
|
14
|
+
It lets ChatGPT, Codex, Claude, or another MCP client save a plan, create a
|
|
15
|
+
workspace-scoped task, let a local agent execute it, and then read back the
|
|
16
|
+
result, git diff, test log, and task status.
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
## Why
|
|
21
|
+
|
|
22
|
+
Many local coding bridges give the upstream model broad shell access.
|
|
23
|
+
PatchWarden takes a narrower route:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
ChatGPT Web or another MCP client
|
|
27
|
+
-> PatchWarden MCP tools
|
|
28
|
+
-> save_plan / create_task
|
|
29
|
+
-> watcher finds pending tasks
|
|
30
|
+
-> local agent executes
|
|
31
|
+
-> result.md / result.json / diff.patch / verify.json / status.json
|
|
32
|
+
-> client reviews the result
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The MCP client can plan and review, but it does not receive a general shell
|
|
36
|
+
tool.
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- MCP stdio server with workspace-scoped tools.
|
|
41
|
+
- Optional HTTP MCP server bound to `127.0.0.1`.
|
|
42
|
+
- ChatGPT Connector / OpenAI Secure MCP Tunnel workflow.
|
|
43
|
+
- Automatic watcher for pending tasks.
|
|
44
|
+
- Local runner that captures `result.md`, `git.diff`, `test.log`, and
|
|
45
|
+
`status.json`.
|
|
46
|
+
- Task phases, heartbeat timestamps, progress reports, cancellation, forced
|
|
47
|
+
termination, and bounded task timeouts.
|
|
48
|
+
- Server-side `wait_for_task` long polling so ChatGPT can remain in one tool
|
|
49
|
+
loop until the agent reaches a terminal state.
|
|
50
|
+
- `create_task` accepts a saved `plan_id`, an auditable `inline_plan`, or one
|
|
51
|
+
of five guarded task templates.
|
|
52
|
+
- A supervised Windows tunnel launcher retries recoverable disconnects and
|
|
53
|
+
writes local, redacted runtime health state.
|
|
54
|
+
- Structured `result.json`, `verify.json`, `diff.patch`, and
|
|
55
|
+
`get_task_summary` acceptance evidence.
|
|
56
|
+
- Workspace-wide before/after fingerprints that fail a task when changes are
|
|
57
|
+
detected outside its explicit `repo_path`.
|
|
58
|
+
- Before/after file fingerprints for stronger change evidence.
|
|
59
|
+
- File reads contained to one configured `workspaceRoot`.
|
|
60
|
+
- Sensitive file blocking for `.env`, tokens, SSH keys, credentials, cookies,
|
|
61
|
+
and similar paths.
|
|
62
|
+
- Low-risk plan storage: ordinary build/test/release language is accepted;
|
|
63
|
+
explicit credential theft, destructive disk deletion, and backdoor plans are blocked.
|
|
64
|
+
- Task artifacts are returned with secret-like values redacted instead of
|
|
65
|
+
failing the entire read.
|
|
66
|
+
- Pending task artifacts return structured `available: false` evidence with
|
|
67
|
+
task phase, watcher health, pending reason, and the next safe tool call.
|
|
68
|
+
- Structured `result.json`, `verify.json`, and `get_task_summary` values are
|
|
69
|
+
recursively redacted and report `redacted` plus `redaction_categories`.
|
|
70
|
+
- Agent command allowlist through `patchwarden.config.json`.
|
|
71
|
+
- Test command exact-match allowlist.
|
|
72
|
+
- Windows-friendly helper scripts.
|
|
73
|
+
- Read-only `doctor` command for local setup diagnostics.
|
|
74
|
+
|
|
75
|
+
## MCP Tools and Profiles
|
|
76
|
+
|
|
77
|
+
PatchWarden has two deterministic tool profiles. `full` is the default for
|
|
78
|
+
ordinary local development and exposes all tools listed below. The Windows
|
|
79
|
+
tunnel stdio wrapper explicitly uses `chatgpt_core`, a stable 16-tool profile
|
|
80
|
+
ordered for the create/wait/review loop:
|
|
81
|
+
|
|
82
|
+
`health_check`, `list_agents`, `list_workspace`, `read_workspace_file`,
|
|
83
|
+
`save_plan`, `create_task`, `wait_for_task`, `get_task_summary`, `get_diff`,
|
|
84
|
+
`get_result`, `get_result_json`, `get_test_log`, `get_task_status`, `list_tasks`,
|
|
85
|
+
`cancel_task`, `audit_task`.
|
|
86
|
+
|
|
87
|
+
The full profile exposes:
|
|
88
|
+
|
|
89
|
+
- `list_workspace`
|
|
90
|
+
- `read_workspace_file`
|
|
91
|
+
- `save_plan`
|
|
92
|
+
- `get_plan`
|
|
93
|
+
- `health_check`
|
|
94
|
+
- `list_agents`
|
|
95
|
+
- `create_task`
|
|
96
|
+
- `get_task_status`
|
|
97
|
+
- `get_result`
|
|
98
|
+
- `get_result_json`
|
|
99
|
+
- `get_diff`
|
|
100
|
+
- `get_test_log`
|
|
101
|
+
- `list_tasks`
|
|
102
|
+
- `cancel_task`
|
|
103
|
+
- `kill_task`
|
|
104
|
+
- `retry_task`
|
|
105
|
+
- `get_task_progress`
|
|
106
|
+
- `wait_for_task`
|
|
107
|
+
- `get_task_summary`
|
|
108
|
+
- `get_task_stdout_tail`
|
|
109
|
+
- `get_task_log_tail`
|
|
110
|
+
- `audit_task`
|
|
111
|
+
|
|
112
|
+
## Install
|
|
113
|
+
|
|
114
|
+
Requirements:
|
|
115
|
+
|
|
116
|
+
- Node.js 18 or newer
|
|
117
|
+
- npm
|
|
118
|
+
- Git, if you want `git.diff`
|
|
119
|
+
- A configured local coding agent such as `opencode` or `codex`
|
|
120
|
+
|
|
121
|
+
Windows PowerShell:
|
|
122
|
+
|
|
123
|
+
```powershell
|
|
124
|
+
cd path\to\patchwarden
|
|
125
|
+
npm.cmd ci
|
|
126
|
+
npm.cmd run build
|
|
127
|
+
npm.cmd test
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Linux, macOS, or WSL:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
cd patchwarden
|
|
134
|
+
npm ci
|
|
135
|
+
npm run build
|
|
136
|
+
npm test
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Configure
|
|
140
|
+
|
|
141
|
+
Create `patchwarden.config.json` in the project root. Do not commit this
|
|
142
|
+
file.
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"workspaceRoot": "D:/path/to/test-or-project-workspace",
|
|
147
|
+
"plansDir": ".patchwarden/plans",
|
|
148
|
+
"tasksDir": ".patchwarden/tasks",
|
|
149
|
+
"toolProfile": "full",
|
|
150
|
+
"agents": {
|
|
151
|
+
"opencode": {
|
|
152
|
+
"command": "opencode",
|
|
153
|
+
"args": ["run", "{prompt}"]
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"allowedTestCommands": [
|
|
157
|
+
"npm test",
|
|
158
|
+
"npm run build",
|
|
159
|
+
"npm run doctor",
|
|
160
|
+
"npm run check:tool-manifest"
|
|
161
|
+
],
|
|
162
|
+
"maxReadFileBytes": 200000,
|
|
163
|
+
"defaultTaskTimeoutSeconds": 900,
|
|
164
|
+
"maxTaskTimeoutSeconds": 3600,
|
|
165
|
+
"watcherStaleSeconds": 30,
|
|
166
|
+
"httpPort": 7331
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Important rules:
|
|
171
|
+
|
|
172
|
+
- Use a small project directory for `workspaceRoot`.
|
|
173
|
+
- Do not set `workspaceRoot` to a drive root, home directory, Desktop,
|
|
174
|
+
Downloads, or Documents.
|
|
175
|
+
- Do not place secrets inside the workspace.
|
|
176
|
+
- Keep agent commands and test commands narrow.
|
|
177
|
+
|
|
178
|
+
## Run Locally
|
|
179
|
+
|
|
180
|
+
Build first:
|
|
181
|
+
|
|
182
|
+
```powershell
|
|
183
|
+
npm.cmd run build
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Run the stdio MCP server:
|
|
187
|
+
|
|
188
|
+
```powershell
|
|
189
|
+
$env:PATCHWARDEN_CONFIG = "path\to\patchwarden.config.json"
|
|
190
|
+
node dist\index.js
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Run the watcher in another terminal:
|
|
194
|
+
|
|
195
|
+
```powershell
|
|
196
|
+
$env:PATCHWARDEN_CONFIG = "path\to\patchwarden.config.json"
|
|
197
|
+
npm.cmd run watch
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Run the HTTP MCP server for local tunnel mode:
|
|
201
|
+
|
|
202
|
+
```powershell
|
|
203
|
+
$env:PATCHWARDEN_CONFIG = "path\to\patchwarden.config.json"
|
|
204
|
+
npm.cmd run start:http
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The HTTP server binds only to `127.0.0.1`.
|
|
208
|
+
|
|
209
|
+
## ChatGPT Connector
|
|
210
|
+
|
|
211
|
+
The intended ChatGPT flow is:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
ChatGPT Web
|
|
215
|
+
-> ChatGPT Connector
|
|
216
|
+
-> OpenAI Secure MCP Tunnel
|
|
217
|
+
-> PatchWarden MCP server
|
|
218
|
+
-> watcher
|
|
219
|
+
-> local agent
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
For stdio tunnel mode on Windows, use the launcher:
|
|
223
|
+
|
|
224
|
+
```text
|
|
225
|
+
scripts/patchwarden-mcp-stdio.cmd
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
This wrapper sets `PATCHWARDEN_CONFIG`, changes into the PatchWarden project
|
|
229
|
+
root, and starts `node dist/index.js`. It prevents tunnel-client from using
|
|
230
|
+
the tunnel-client directory as the MCP workspace.
|
|
231
|
+
|
|
232
|
+
### One-Click Windows Launcher
|
|
233
|
+
|
|
234
|
+
For local development, run:
|
|
235
|
+
|
|
236
|
+
```text
|
|
237
|
+
Start-PatchWarden-Tunnel.cmd
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The launcher:
|
|
241
|
+
|
|
242
|
+
- asks for your tunnel runtime API key on first use, then stores it encrypted
|
|
243
|
+
with Windows DPAPI under `%APPDATA%\patchwarden`
|
|
244
|
+
- asks for a tunnel ID if `PATCHWARDEN_TUNNEL_ID` is not already set
|
|
245
|
+
- starts a hidden watcher owned by the launcher when no healthy external watcher exists
|
|
246
|
+
- supervises only its owned watcher and retries stale/exited instances with a
|
|
247
|
+
capped 2/5/10/20/30-second backoff
|
|
248
|
+
- runs machine-readable `tunnel-client doctor` checks
|
|
249
|
+
- performs a real stdio MCP `initialize` plus `tools/list` preflight and stops
|
|
250
|
+
before tunnel startup if the core tools or v0.4.0 schemas are missing
|
|
251
|
+
- supervises `tunnel-client run`, probes readiness, and retries recoverable
|
|
252
|
+
exits with a capped 5/10/20/30-second backoff
|
|
253
|
+
- stops on non-retryable authentication, configuration, region, or control
|
|
254
|
+
plane errors instead of looping blindly
|
|
255
|
+
|
|
256
|
+
Optional environment variables:
|
|
257
|
+
|
|
258
|
+
```powershell
|
|
259
|
+
$env:PATCHWARDEN_TUNNEL_ID = "tunnel_xxx"
|
|
260
|
+
$env:TUNNEL_CLIENT_EXE = "C:\path\to\tunnel-client.exe"
|
|
261
|
+
$env:OPENCODE_BIN_DIR = "C:\path\to\opencode-ai\bin"
|
|
262
|
+
$env:HTTPS_PROXY = "http://127.0.0.1:7892"
|
|
263
|
+
$env:PATCHWARDEN_CREDENTIAL_PATH = "C:\private\patchwarden-key.dpapi"
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The saved key is bound to the current Windows user and computer. It is never
|
|
267
|
+
written to the repository or printed to logs. To remove it, run
|
|
268
|
+
`Reset-PatchWarden-Tunnel-Key.cmd`.
|
|
269
|
+
|
|
270
|
+
Never commit API keys, runtime keys, tunnel IDs, local account names, or
|
|
271
|
+
private workspace IDs.
|
|
272
|
+
|
|
273
|
+
If ChatGPT reports a tunnel 404 or cannot call any MCP tool, run:
|
|
274
|
+
|
|
275
|
+
```text
|
|
276
|
+
Check-PatchWarden-Health.cmd
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
This local-only diagnostic reports source/dist version, the actual MCP process
|
|
280
|
+
source, tool profile/count/names/schema hash, workspace/tasks access, watcher
|
|
281
|
+
freshness, configured agents, tunnel readiness, and other detected
|
|
282
|
+
PatchWarden processes. It only warns about mixed versions and never ends a
|
|
283
|
+
process. Runtime status is stored under `%LOCALAPPDATA%\patchwarden\runtime`
|
|
284
|
+
and does not contain the API key or Tunnel ID.
|
|
285
|
+
|
|
286
|
+
For an expanded read-only diagnosis, call
|
|
287
|
+
`health_check({"detail":"self_diagnostic"})`. It adds allowlist counts,
|
|
288
|
+
configured agents, recent task failures, and catalog consistency evidence
|
|
289
|
+
without creating a task that depends on the watcher.
|
|
290
|
+
|
|
291
|
+
If you need to fully restart everything (after a config change, version
|
|
292
|
+
upgrade, or hung process), double-click:
|
|
293
|
+
|
|
294
|
+
```text
|
|
295
|
+
Restart-PatchWarden.cmd
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
This stops only the process tree recorded as owned by the current launcher,
|
|
299
|
+
rebuilds the project, clears stale runtime state, and opens a fresh tunnel
|
|
300
|
+
launcher window. It does not stop unrelated or legacy PatchWarden instances.
|
|
301
|
+
|
|
302
|
+
## Demo
|
|
303
|
+
|
|
304
|
+
See [docs/demo.md](docs/demo.md) for a privacy-safe ChatGPT connector demo and
|
|
305
|
+
expected outputs.
|
|
306
|
+
|
|
307
|
+
## Troubleshooting
|
|
308
|
+
|
|
309
|
+
### ChatGPT lists the tunnel-client directory
|
|
310
|
+
|
|
311
|
+
If `list_workspace` returns only `tunnel-client.exe`, the MCP child process did
|
|
312
|
+
not receive `PATCHWARDEN_CONFIG` or started from the wrong working directory.
|
|
313
|
+
|
|
314
|
+
Fix: use `scripts/patchwarden-mcp-stdio.cmd` as the tunnel MCP command, then
|
|
315
|
+
restart tunnel-client.
|
|
316
|
+
|
|
317
|
+
### ChatGPT tool call times out
|
|
318
|
+
|
|
319
|
+
Check the tunnel-client UI at:
|
|
320
|
+
|
|
321
|
+
```text
|
|
322
|
+
http://127.0.0.1:8080/ui
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
If logs show:
|
|
326
|
+
|
|
327
|
+
```text
|
|
328
|
+
unsupported_country_region_territory
|
|
329
|
+
403 Forbidden
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
then the current proxy exit region is not supported by the OpenAI API control
|
|
333
|
+
plane. Change to a supported region and restart tunnel-client.
|
|
334
|
+
|
|
335
|
+
### ChatGPT stops after `create_task`
|
|
336
|
+
|
|
337
|
+
An MCP server cannot send a new message into ChatGPT after the assistant turn
|
|
338
|
+
has ended. Do not rely on a prompt that says only "wait and check later".
|
|
339
|
+
Immediately call `wait_for_task` after `create_task`. If its response contains
|
|
340
|
+
`continuation_required: true`, call it again in the same assistant turn. When
|
|
341
|
+
`terminal: true`, use the included summary and then call `audit_task` for the
|
|
342
|
+
independent review. Each wait is capped at 30 seconds to stay below common
|
|
343
|
+
connector and tunnel request timeouts.
|
|
344
|
+
|
|
345
|
+
### ChatGPT still shows an older tool list
|
|
346
|
+
|
|
347
|
+
Tool catalogs can remain attached to a connector session that was opened
|
|
348
|
+
before the tunnel was refreshed. First run `Check-PatchWarden-Health.cmd` and
|
|
349
|
+
confirm `configured_tunnel_manifest.tool_profile` is `chatgpt_core`, its
|
|
350
|
+
`tool_count` is 16, and the next tunnel status reports `core_tools_ready` as
|
|
351
|
+
true. Then refresh or reconnect the Connector and open a
|
|
352
|
+
new ChatGPT conversation. Do not use the old conversation as proof that the
|
|
353
|
+
new schema was loaded. `health_check` exposes `server_version`, `schema_epoch`,
|
|
354
|
+
and `tool_manifest_sha256` so the same tool names with stale schemas can still
|
|
355
|
+
be distinguished.
|
|
356
|
+
|
|
357
|
+
If an old conversation calls a tool that is no longer in the active profile,
|
|
358
|
+
PatchWarden returns `tool_catalog_mismatch` with the current tool manifest and
|
|
359
|
+
refresh instructions instead of a generic unavailable-tool error.
|
|
360
|
+
|
|
361
|
+
### Task remains queued and watcher is stale
|
|
362
|
+
|
|
363
|
+
`create_task`, `get_task_status`, `list_tasks`, and pending artifact reads all
|
|
364
|
+
return the same watcher evidence. A stale or missing watcher leaves the task
|
|
365
|
+
saved but sets `execution_blocked: true`, `continuation_required: false`, and
|
|
366
|
+
points to `health_check`. The Windows launcher automatically retries only the
|
|
367
|
+
watcher process it created; external and legacy instances are never stopped.
|
|
368
|
+
|
|
369
|
+
If logs show direct connection timeouts to `api.openai.com`, set a proxy:
|
|
370
|
+
|
|
371
|
+
```powershell
|
|
372
|
+
$env:HTTPS_PROXY = "http://127.0.0.1:7892"
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### ChatGPT Connector creation fails
|
|
376
|
+
|
|
377
|
+
Verify:
|
|
378
|
+
|
|
379
|
+
- tunnel-client is running
|
|
380
|
+
- the tunnel is associated with the correct ChatGPT workspace
|
|
381
|
+
- the connector uses `Channel`, not `Server URL`
|
|
382
|
+
- authentication is set to `None` unless you have implemented OAuth
|
|
383
|
+
- browser translation extensions are disabled on Platform pages
|
|
384
|
+
|
|
385
|
+
## Recommended Workflow
|
|
386
|
+
|
|
387
|
+
Start with `health_check` and `list_agents`. `create_task` requires an explicit
|
|
388
|
+
`repo_path`; it never silently falls back to the workspace root. Prefer
|
|
389
|
+
`verify_commands` from the exact schema allowlist. Immediately enter the
|
|
390
|
+
`wait_for_task(timeout_seconds: 25)` loop and keep calling it while
|
|
391
|
+
`continuation_required` is true. The legacy `wait_seconds` name remains
|
|
392
|
+
supported; if both aliases are sent, their values must match. Each wait
|
|
393
|
+
defaults to 25 seconds and is capped at 30 seconds.
|
|
394
|
+
Use `cancel_task` for graceful cancellation or `kill_task` for immediate
|
|
395
|
+
termination. Final acceptance starts with `get_task_summary`, followed by
|
|
396
|
+
`audit_task` and any detailed artifacts needed for review.
|
|
397
|
+
|
|
398
|
+
Do not use the entire `workspaceRoot` as the task repository unless that is
|
|
399
|
+
truly the intended repository. Prefer a relative subdirectory such as
|
|
400
|
+
`desktop-pet-wangzai`; absolute paths are also accepted when they resolve
|
|
401
|
+
inside `workspaceRoot`.
|
|
402
|
+
|
|
403
|
+
`create_task` requires exactly one plan source: `plan_id`, `inline_plan`, or
|
|
404
|
+
`template`. The existing `save_plan` flow remains compatible. A shorter inline
|
|
405
|
+
flow looks like:
|
|
406
|
+
|
|
407
|
+
```json
|
|
408
|
+
{
|
|
409
|
+
"agent": "opencode",
|
|
410
|
+
"repo_path": "desktop-pet-wangzai",
|
|
411
|
+
"inline_plan": "Implement the requested small feature without changing unrelated files.",
|
|
412
|
+
"verify_commands": [
|
|
413
|
+
"npm run build",
|
|
414
|
+
"npm test"
|
|
415
|
+
]
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Guarded templates are `inspect_only`, `feature_small`, `fix_tests`,
|
|
420
|
+
`release_check`, and `rollback_scope_violation`. Template tasks also require a
|
|
421
|
+
`goal`; the rollback review additionally requires `source_task_id` and never
|
|
422
|
+
performs an automatic rollback. `inspect_only` and rollback review tasks fail
|
|
423
|
+
with `failed_policy_violation` if they change repository files.
|
|
424
|
+
|
|
425
|
+
`list_tasks` accepts `status`, `repo_path`, `active_only`, and `limit`. Each
|
|
426
|
+
entry includes its computed `pending_reason` and watcher state.
|
|
427
|
+
|
|
428
|
+
1. `list_workspace` — explore the project
|
|
429
|
+
2. `save_plan` — ChatGPT writes the implementation plan
|
|
430
|
+
3. `create_task` with `repo_path` and `verify_commands`
|
|
431
|
+
4. `wait_for_task` — repeat in the same turn until `terminal: true`
|
|
432
|
+
5. `get_task_summary` — inspect scope, verification, files, and artifacts
|
|
433
|
+
6. `get_result_json` / `get_diff` / `get_test_log` — inspect detailed evidence
|
|
434
|
+
7. `audit_task` — independent verification (checks claims vs reality)
|
|
435
|
+
|
|
436
|
+
> **Important:**
|
|
437
|
+
> - `task done` means the agent finished executing — it does NOT mean the work is correct or complete.
|
|
438
|
+
> - `failed_scope_violation` takes precedence over acceptance. Review
|
|
439
|
+
> `rollback_scope_violation_plan.md`; PatchWarden never auto-rolls back concurrent/user edits.
|
|
440
|
+
> - `failed_verification` means at least one independent allow-listed command failed;
|
|
441
|
+
> inspect `verify.log` before retrying.
|
|
442
|
+
> - `failed_policy_violation` means a no-changes template unexpectedly changed
|
|
443
|
+
> repository files; inspect the diff and use the backup-first follow-up prompt.
|
|
444
|
+
> - `audit_task` provides an independent review, but still requires human judgment.
|
|
445
|
+
> - Local `result.md` claims about `npm publish`, `git push`, or `GitHub release` are **unverified**.
|
|
446
|
+
> - Publishing, tagging, pushing, and npm publish must be confirmed manually.
|
|
447
|
+
> - Before running `doctor`, create `patchwarden.config.json` from the example template.
|
|
448
|
+
|
|
449
|
+
### Task artifacts
|
|
450
|
+
|
|
451
|
+
- `result.md`: human-readable execution report and agent output.
|
|
452
|
+
- `result.json`: structured status, paths, changed files, scope evidence,
|
|
453
|
+
verification state, warnings, errors, and next steps for tools.
|
|
454
|
+
- `verify.json`: one structured record per independently executed allow-listed
|
|
455
|
+
verification command, including cwd, exit code, output tails, and timing.
|
|
456
|
+
- `verify.log`: readable form of the same independent verification evidence.
|
|
457
|
+
- `diff.patch`: complete task change evidence. `get_diff.patch_mode` is
|
|
458
|
+
`textual`, `no_changes`, or `hash_only`; hash-only responses include an
|
|
459
|
+
`unavailable_reason`. Large textual responses return a bounded patch head,
|
|
460
|
+
byte counts, truncation evidence, and the complete local `diff_patch_path`.
|
|
461
|
+
- `file-stats.json`: standalone per-file additions/deletions and aggregate counts.
|
|
462
|
+
- `rollback_scope_violation_plan.md`: review-only list of repo-external changes;
|
|
463
|
+
it never includes normal in-repo changes and never performs rollback itself.
|
|
464
|
+
|
|
465
|
+
## Security Model
|
|
466
|
+
|
|
467
|
+
PatchWarden intentionally avoids general shell execution through MCP tools.
|
|
468
|
+
|
|
469
|
+
- MCP clients cannot pass arbitrary shell commands.
|
|
470
|
+
- Agent commands must be configured ahead of time.
|
|
471
|
+
- Test commands must match `allowedTestCommands` exactly.
|
|
472
|
+
- File reads are contained to `workspaceRoot`.
|
|
473
|
+
- Sensitive file names are blocked even inside the workspace.
|
|
474
|
+
- The runner does not commit, push, delete files, or reset repositories.
|
|
475
|
+
- HTTP mode binds to `127.0.0.1` only.
|
|
476
|
+
|
|
477
|
+
This is still a local automation bridge. Treat connector access as powerful
|
|
478
|
+
and use a dedicated test workspace first.
|
|
479
|
+
|
|
480
|
+
## Development
|
|
481
|
+
|
|
482
|
+
Windows PowerShell:
|
|
483
|
+
|
|
484
|
+
```powershell
|
|
485
|
+
npm.cmd run build
|
|
486
|
+
npm.cmd test
|
|
487
|
+
npm.cmd run test:mcp
|
|
488
|
+
npm.cmd run test:http-mcp
|
|
489
|
+
npm.cmd run doctor
|
|
490
|
+
npm.cmd run check:tool-manifest
|
|
491
|
+
npm.cmd run test:tunnel-supervisor
|
|
492
|
+
npm.cmd run test:watcher-supervisor
|
|
493
|
+
npm.cmd run pack:clean
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Package checks:
|
|
497
|
+
|
|
498
|
+
```powershell
|
|
499
|
+
npm.cmd run verify:package
|
|
500
|
+
npm.cmd run pack:clean
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
The clean archive excludes:
|
|
504
|
+
|
|
505
|
+
- `node_modules/`
|
|
506
|
+
- `.patchwarden/`
|
|
507
|
+
- `*.log`
|
|
508
|
+
- `.env`
|
|
509
|
+
- `patchwarden.config.json`
|
|
510
|
+
- local release artifacts
|
|
511
|
+
|
|
512
|
+
## Roadmap
|
|
513
|
+
|
|
514
|
+
- [x] stdio MCP server
|
|
515
|
+
- [x] plan and task CRUD
|
|
516
|
+
- [x] runner and watcher
|
|
517
|
+
- [x] HTTP MCP server
|
|
518
|
+
- [x] ChatGPT Connector tunnel docs
|
|
519
|
+
- [x] doctor command
|
|
520
|
+
- [ ] worktree isolation
|
|
521
|
+
- [ ] multi-agent task queue
|
|
522
|
+
- [ ] dashboard
|
|
523
|
+
|
|
524
|
+
## License
|
|
525
|
+
|
|
526
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal
|
|
3
|
+
cd /d "%~dp0"
|
|
4
|
+
echo.
|
|
5
|
+
echo ========================================
|
|
6
|
+
echo PatchWarden One-Click Restart
|
|
7
|
+
echo ========================================
|
|
8
|
+
echo.
|
|
9
|
+
echo This will:
|
|
10
|
+
echo 1. Stop only processes owned by the current PatchWarden launcher
|
|
11
|
+
echo 2. Rebuild the project
|
|
12
|
+
echo 3. Start a fresh tunnel launcher window
|
|
13
|
+
echo.
|
|
14
|
+
echo Close this window to cancel, or
|
|
15
|
+
pause
|
|
16
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\restart-patchwarden.ps1"
|
|
17
|
+
echo.
|
|
18
|
+
echo Restart script finished.
|
|
19
|
+
pause
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface AgentConfig {
|
|
2
|
+
command: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
}
|
|
5
|
+
export interface PatchWardenConfig {
|
|
6
|
+
workspaceRoot: string;
|
|
7
|
+
plansDir: string;
|
|
8
|
+
tasksDir: string;
|
|
9
|
+
agents: Record<string, AgentConfig>;
|
|
10
|
+
allowedTestCommands: string[];
|
|
11
|
+
maxReadFileBytes: number;
|
|
12
|
+
defaultTaskTimeoutSeconds: number;
|
|
13
|
+
maxTaskTimeoutSeconds: number;
|
|
14
|
+
watcherStaleSeconds: number;
|
|
15
|
+
toolProfile?: "full" | "chatgpt_core";
|
|
16
|
+
repoAliases?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export declare function loadConfig(configPath?: string): PatchWardenConfig;
|
|
19
|
+
export declare function getConfig(): PatchWardenConfig;
|
|
20
|
+
/** Resolve workspaceRoot: expand relative paths */
|
|
21
|
+
export declare function resolveWorkspaceRoot(config: PatchWardenConfig): string;
|
|
22
|
+
/** Resolve plans/tasks dirs relative to workspaceRoot */
|
|
23
|
+
export declare function getPlansDir(config: PatchWardenConfig): string;
|
|
24
|
+
export declare function getTasksDir(config: PatchWardenConfig): string;
|