patchwarden 0.4.0 → 0.6.1

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/PatchWarden.cmd +51 -0
  2. package/README.en.md +1022 -0
  3. package/README.md +897 -358
  4. package/dist/assessments/agentAssessor.d.ts +15 -0
  5. package/dist/assessments/agentAssessor.js +293 -0
  6. package/dist/assessments/assessmentStore.d.ts +133 -0
  7. package/dist/assessments/assessmentStore.js +238 -0
  8. package/dist/assessments/confirmCli.d.ts +9 -0
  9. package/dist/assessments/confirmCli.js +26 -0
  10. package/dist/config.d.ts +22 -1
  11. package/dist/config.js +156 -3
  12. package/dist/direct/directAudit.d.ts +23 -0
  13. package/dist/direct/directAudit.js +309 -0
  14. package/dist/direct/directGuards.d.ts +20 -0
  15. package/dist/direct/directGuards.js +137 -0
  16. package/dist/direct/directPatch.d.ts +17 -0
  17. package/dist/direct/directPatch.js +113 -0
  18. package/dist/direct/directSessionStore.d.ts +63 -0
  19. package/dist/direct/directSessionStore.js +192 -0
  20. package/dist/direct/directVerification.d.ts +12 -0
  21. package/dist/direct/directVerification.js +96 -0
  22. package/dist/doctor.js +73 -5
  23. package/dist/logging.d.ts +52 -0
  24. package/dist/logging.js +123 -0
  25. package/dist/runner/agentInvocation.d.ts +23 -0
  26. package/dist/runner/agentInvocation.js +106 -0
  27. package/dist/runner/changeCapture.d.ts +70 -0
  28. package/dist/runner/changeCapture.js +278 -6
  29. package/dist/runner/runTask.js +271 -65
  30. package/dist/runner/simpleProcess.d.ts +21 -0
  31. package/dist/runner/simpleProcess.js +206 -0
  32. package/dist/runner/watch.js +17 -2
  33. package/dist/security/commandGuard.d.ts +2 -1
  34. package/dist/security/commandGuard.js +25 -3
  35. package/dist/security/riskEngine.d.ts +27 -0
  36. package/dist/security/riskEngine.js +118 -0
  37. package/dist/security/runtimeGuard.d.ts +6 -0
  38. package/dist/security/runtimeGuard.js +28 -0
  39. package/dist/smoke-test.js +1353 -7
  40. package/dist/test/unit/android-doctor.test.d.ts +1 -0
  41. package/dist/test/unit/android-doctor.test.js +118 -0
  42. package/dist/test/unit/chinese-path.test.d.ts +1 -0
  43. package/dist/test/unit/chinese-path.test.js +91 -0
  44. package/dist/test/unit/command-guard.test.d.ts +1 -0
  45. package/dist/test/unit/command-guard.test.js +160 -0
  46. package/dist/test/unit/direct-guards.test.d.ts +1 -0
  47. package/dist/test/unit/direct-guards.test.js +213 -0
  48. package/dist/test/unit/logging.test.d.ts +1 -0
  49. package/dist/test/unit/logging.test.js +275 -0
  50. package/dist/test/unit/path-guard.test.d.ts +1 -0
  51. package/dist/test/unit/path-guard.test.js +109 -0
  52. package/dist/test/unit/safe-status.test.d.ts +1 -0
  53. package/dist/test/unit/safe-status.test.js +165 -0
  54. package/dist/test/unit/sensitive-guard.test.d.ts +1 -0
  55. package/dist/test/unit/sensitive-guard.test.js +104 -0
  56. package/dist/test/unit/sync-file.test.d.ts +1 -0
  57. package/dist/test/unit/sync-file.test.js +154 -0
  58. package/dist/test/unit/watcher-status.test.d.ts +1 -0
  59. package/dist/test/unit/watcher-status.test.js +169 -0
  60. package/dist/tools/androidDoctor.d.ts +38 -0
  61. package/dist/tools/androidDoctor.js +391 -0
  62. package/dist/tools/applyPatch.d.ts +16 -0
  63. package/dist/tools/applyPatch.js +41 -0
  64. package/dist/tools/auditSession.d.ts +5 -0
  65. package/dist/tools/auditSession.js +12 -0
  66. package/dist/tools/auditTask.d.ts +7 -0
  67. package/dist/tools/auditTask.js +105 -7
  68. package/dist/tools/createDirectSession.d.ts +14 -0
  69. package/dist/tools/createDirectSession.js +54 -0
  70. package/dist/tools/createTask.d.ts +48 -1
  71. package/dist/tools/createTask.js +298 -47
  72. package/dist/tools/finalizeDirectSession.d.ts +19 -0
  73. package/dist/tools/finalizeDirectSession.js +84 -0
  74. package/dist/tools/getTaskSummary.d.ts +50 -0
  75. package/dist/tools/getTaskSummary.js +79 -2
  76. package/dist/tools/healthCheck.d.ts +27 -12
  77. package/dist/tools/healthCheck.js +44 -6
  78. package/dist/tools/readWorkspaceFile.d.ts +7 -1
  79. package/dist/tools/readWorkspaceFile.js +48 -2
  80. package/dist/tools/registry.js +270 -19
  81. package/dist/tools/runVerification.d.ts +16 -0
  82. package/dist/tools/runVerification.js +32 -0
  83. package/dist/tools/safeStatus.d.ts +19 -0
  84. package/dist/tools/safeStatus.js +72 -0
  85. package/dist/tools/savePlan.d.ts +1 -0
  86. package/dist/tools/savePlan.js +38 -7
  87. package/dist/tools/searchWorkspace.d.ts +19 -0
  88. package/dist/tools/searchWorkspace.js +205 -0
  89. package/dist/tools/syncFile.d.ts +18 -0
  90. package/dist/tools/syncFile.js +65 -0
  91. package/dist/tools/taskOutputs.d.ts +2 -2
  92. package/dist/tools/taskTemplates.js +2 -1
  93. package/dist/tools/toolCatalog.d.ts +4 -3
  94. package/dist/tools/toolCatalog.js +34 -5
  95. package/dist/tools/waitForTask.d.ts +2 -2
  96. package/dist/tools/waitForTask.js +1 -1
  97. package/dist/version.d.ts +2 -2
  98. package/dist/version.js +2 -2
  99. package/dist/watcherStatus.d.ts +1 -0
  100. package/dist/watcherStatus.js +96 -4
  101. package/docs/chatgpt-usage.md +101 -0
  102. package/docs/performance-notes.md +55 -0
  103. package/docs/release-checklist.md +14 -0
  104. package/docs/release-v0.6.0.md +71 -0
  105. package/docs/release-v0.6.1.md +75 -0
  106. package/examples/config.example.json +5 -0
  107. package/examples/openai-tunnel/README.md +11 -4
  108. package/examples/openai-tunnel/chatgpt-test-prompt.md +18 -14
  109. package/examples/openai-tunnel/tunnel-client.example.yaml +8 -0
  110. package/package.json +13 -8
  111. package/scripts/brand-check.js +58 -12
  112. package/scripts/control-smoke.js +206 -0
  113. package/scripts/http-mcp-smoke.js +10 -2
  114. package/scripts/launchers/Check-PatchWarden-Health.cmd +6 -0
  115. package/scripts/launchers/Reset-PatchWarden-Tunnel-Key.cmd +6 -0
  116. package/scripts/launchers/Restart-PatchWarden.cmd +6 -0
  117. package/scripts/launchers/Start-PatchWarden-Direct-Tunnel.cmd +7 -0
  118. package/scripts/launchers/Start-PatchWarden-Tunnel.cmd +7 -0
  119. package/scripts/lifecycle-smoke.js +402 -8
  120. package/scripts/manage-patchwarden.ps1 +639 -0
  121. package/scripts/mcp-manifest-check.js +123 -58
  122. package/scripts/mcp-smoke.js +160 -2
  123. package/scripts/pack-clean.js +160 -5
  124. package/scripts/package-manifest-check.js +78 -0
  125. package/scripts/patchwarden-mcp-direct.cmd +7 -0
  126. package/scripts/patchwarden-mcp-stdio.cmd +1 -1
  127. package/scripts/restart-patchwarden.ps1 +5 -4
  128. package/scripts/start-patchwarden-tunnel.ps1 +261 -30
  129. package/scripts/tunnel-supervisor-smoke.js +36 -4
  130. package/scripts/unit-tests.js +36 -0
  131. package/scripts/watcher-supervisor-smoke.js +10 -6
  132. package/src/assessments/agentAssessor.ts +324 -0
  133. package/src/assessments/assessmentStore.ts +426 -0
  134. package/src/assessments/confirmCli.ts +29 -0
  135. package/src/config.ts +178 -4
  136. package/src/direct/directAudit.ts +400 -0
  137. package/src/direct/directGuards.ts +279 -0
  138. package/src/direct/directPatch.ts +258 -0
  139. package/src/direct/directSessionStore.ts +345 -0
  140. package/src/direct/directVerification.ts +138 -0
  141. package/src/doctor.ts +103 -7
  142. package/src/logging.ts +152 -0
  143. package/src/runner/agentInvocation.ts +125 -0
  144. package/src/runner/changeCapture.ts +352 -6
  145. package/src/runner/runTask.ts +279 -63
  146. package/src/runner/simpleProcess.ts +223 -0
  147. package/src/runner/watch.ts +18 -2
  148. package/src/security/commandGuard.ts +46 -4
  149. package/src/security/riskEngine.ts +160 -0
  150. package/src/security/runtimeGuard.ts +41 -0
  151. package/src/smoke-test.ts +1291 -4
  152. package/src/test/unit/android-doctor.test.ts +158 -0
  153. package/src/test/unit/chinese-path.test.ts +106 -0
  154. package/src/test/unit/command-guard.test.ts +221 -0
  155. package/src/test/unit/direct-guards.test.ts +297 -0
  156. package/src/test/unit/logging.test.ts +325 -0
  157. package/src/test/unit/path-guard.test.ts +150 -0
  158. package/src/test/unit/safe-status.test.ts +187 -0
  159. package/src/test/unit/sensitive-guard.test.ts +124 -0
  160. package/src/test/unit/sync-file.test.ts +231 -0
  161. package/src/test/unit/watcher-status.test.ts +190 -0
  162. package/src/tools/androidDoctor.ts +424 -0
  163. package/src/tools/applyPatch.ts +86 -0
  164. package/src/tools/auditSession.ts +28 -0
  165. package/src/tools/auditTask.ts +111 -7
  166. package/src/tools/createDirectSession.ts +113 -0
  167. package/src/tools/createTask.ts +405 -55
  168. package/src/tools/finalizeDirectSession.ts +144 -0
  169. package/src/tools/getTaskSummary.ts +133 -2
  170. package/src/tools/healthCheck.ts +45 -6
  171. package/src/tools/readWorkspaceFile.ts +85 -2
  172. package/src/tools/registry.ts +305 -19
  173. package/src/tools/runVerification.ts +58 -0
  174. package/src/tools/safeStatus.ts +96 -0
  175. package/src/tools/savePlan.ts +57 -7
  176. package/src/tools/searchWorkspace.ts +275 -0
  177. package/src/tools/syncFile.ts +122 -0
  178. package/src/tools/taskTemplates.ts +2 -1
  179. package/src/tools/toolCatalog.ts +37 -6
  180. package/src/tools/waitForTask.ts +3 -3
  181. package/src/version.ts +2 -2
  182. package/src/watcherStatus.ts +101 -4
  183. package/tsconfig.json +18 -17
  184. package/Check-PatchWarden-Health.cmd +0 -6
  185. package/Reset-PatchWarden-Tunnel-Key.cmd +0 -6
  186. package/Restart-PatchWarden.cmd +0 -19
  187. package/Start-PatchWarden-Tunnel.cmd +0 -7
  188. package/docs/release-v0.3.0.md +0 -43
  189. package/docs/release-v0.4.0.md +0 -74
package/README.en.md ADDED
@@ -0,0 +1,1022 @@
1
+ # PatchWarden
2
+
3
+ <p align="right">
4
+ <a href="./README.md">简体中文</a> · <strong>English</strong>
5
+ </p>
6
+
7
+ [![npm version](https://img.shields.io/npm/v/patchwarden.svg)](https://www.npmjs.com/package/patchwarden)
8
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-339933.svg)](https://nodejs.org/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
+
11
+ Current stable release: **v0.6.0**. See the
12
+ [release notes](docs/release-v0.6.0.md),
13
+ [migration guide](docs/migration-from-safe-bifrost.md), and
14
+ [GitHub Release](https://github.com/jiezeng2004-design/PatchWarden/releases/tag/v0.6.0).
15
+
16
+ PatchWarden is a security-focused MCP bridge for local coding agents.
17
+ ChatGPT, Codex, OpenCode, or another MCP client can plan and review work;
18
+ PatchWarden stores that plan as a workspace-scoped task, lets a preconfigured
19
+ local agent execute it, and returns results, diffs, and independent
20
+ verification evidence.
21
+
22
+ ![PatchWarden ChatGPT connector demo](docs/assets/patchwarden-chatgpt-demo.svg)
23
+
24
+ > [!IMPORTANT]
25
+ > PatchWarden is not a general-purpose remote shell. MCP clients cannot run
26
+ > arbitrary commands: files must remain inside the configured workspace,
27
+ > agents must be registered in advance, verification commands must exactly
28
+ > match the allowlist, and sensitive paths are blocked.
29
+
30
+ ## Contents
31
+
32
+ - [What PatchWarden solves](#what-patchwarden-solves)
33
+ - [Runtime architecture](#runtime-architecture)
34
+ - [Requirements](#requirements)
35
+ - [Five-minute quick start](#five-minute-quick-start)
36
+ - [Complete configuration guide](#complete-configuration-guide)
37
+ - [Connect OpenCode](#connect-opencode)
38
+ - [Connect Codex](#connect-codex)
39
+ - [Connect ChatGPT](#connect-chatgpt)
40
+ - [Proxy configuration: read this first](#proxy-configuration-read-this-first)
41
+ - [Recommended task workflow](#recommended-task-workflow)
42
+ - [HTTP MCP mode](#http-mcp-mode)
43
+ - [Diagnostics and health checks](#diagnostics-and-health-checks)
44
+ - [Lessons learned and troubleshooting](#lessons-learned-and-troubleshooting)
45
+ - [Security boundaries and local data](#security-boundaries-and-local-data)
46
+ - [Upgrading and migration](#upgrading-and-migration)
47
+ - [Development and release verification](#development-and-release-verification)
48
+
49
+ ## What PatchWarden solves
50
+
51
+ Many local coding bridges expose a broad shell to the upstream model.
52
+ PatchWarden uses a narrower, auditable task channel:
53
+
54
+ - Upstream models call explicit MCP tools instead of assembling arbitrary
55
+ shell commands.
56
+ - Every task must specify a `repo_path` inside `workspaceRoot`.
57
+ - Agent launch commands come from local configuration, not model input.
58
+ - Verification commands must exactly match `allowedTestCommands`.
59
+ - Every completed task records structured results, a full diff, file
60
+ statistics, and independent verification output.
61
+ - Changes outside the requested repository cause a scope violation instead of
62
+ being silently accepted.
63
+ - Sensitive paths such as `.env` files, tokens, SSH keys, cookies, and
64
+ credential stores are blocked by default.
65
+
66
+ Good use cases:
67
+
68
+ - Let ChatGPT plan and review while OpenCode or Codex executes locally.
69
+ - Add an auditable plan → task → verify flow to a local MCP client.
70
+ - Review `result.json`, `diff.patch`, and `verify.json` after execution.
71
+ - Automate tasks that need workspace containment, command allowlists, and
72
+ sensitive-data protection.
73
+
74
+ PatchWarden is not designed for:
75
+
76
+ - Giving an MCP client unrestricted shell access.
77
+ - Managing an entire drive, home directory, or directory full of private data.
78
+ - Unattended commits, pushes, releases, or production changes.
79
+
80
+ ## Runtime architecture
81
+
82
+ ```text
83
+ ChatGPT / Codex / OpenCode / another MCP client
84
+ |
85
+ v
86
+ PatchWarden MCP Server
87
+ |
88
+ save_plan / create_task
89
+ |
90
+ v
91
+ .patchwarden/tasks/<task_id>/
92
+ |
93
+ Watcher finds task
94
+ |
95
+ v
96
+ Local agent (OpenCode / Codex)
97
+ |
98
+ v
99
+ result.json / diff.patch / verify.json / status.json
100
+ |
101
+ v
102
+ Client reviews and audits
103
+ ```
104
+
105
+ A complete setup normally has three distinct roles:
106
+
107
+ 1. **MCP Server** — started by Codex, OpenCode, or the tunnel.
108
+ 2. **Watcher** — monitors pending tasks and launches the local agent.
109
+ 3. **Local agent** — modifies the code and must be registered in advance.
110
+
111
+ > [!WARNING]
112
+ > “MCP connected” does not mean tasks can execute. If the Watcher is not
113
+ > running, `create_task` can still save a task, but the task remains queued and
114
+ > reports `execution_blocked: true`.
115
+
116
+ ## Requirements
117
+
118
+ - Node.js 18 or newer
119
+ - npm
120
+ - Git (optional, but reliable `git.diff` evidence requires it)
121
+ - At least one local coding agent, such as OpenCode or the Codex CLI
122
+ - Windows tunnel mode also requires `tunnel-client.exe`, a Tunnel ID, and a
123
+ runtime API key
124
+
125
+ Check the Windows environment in PowerShell:
126
+
127
+ ```powershell
128
+ node -v
129
+ npm.cmd -v
130
+ git --version
131
+ where.exe opencode
132
+ where.exe codex
133
+ ```
134
+
135
+ If `where.exe codex` only returns the Codex Desktop executable under
136
+ WindowsApps, it may not be a callable Codex CLI. Install or point to the real
137
+ CLI, or configure OpenCode as the execution agent.
138
+
139
+ ## Five-minute quick start
140
+
141
+ ### Option A: run from source (recommended)
142
+
143
+ Source mode is the easiest way to use the Watcher, Windows launchers, and
144
+ diagnostic scripts together.
145
+
146
+ Windows PowerShell:
147
+
148
+ ```powershell
149
+ git clone https://github.com/jiezeng2004-design/PatchWarden.git
150
+ cd .\PatchWarden
151
+ npm.cmd ci
152
+ npm.cmd run build
153
+ Copy-Item .\examples\config.example.json .\patchwarden.config.json
154
+ ```
155
+
156
+ Edit `patchwarden.config.json` and set at least:
157
+
158
+ - `workspaceRoot`
159
+ - `agents`
160
+ - `allowedTestCommands`
161
+
162
+ Run diagnostics:
163
+
164
+ ```powershell
165
+ npm.cmd run doctor
166
+ ```
167
+
168
+ Start the Watcher:
169
+
170
+ ```powershell
171
+ $env:PATCHWARDEN_CONFIG = (Resolve-Path .\patchwarden.config.json)
172
+ npm.cmd run watch
173
+ ```
174
+
175
+ Keep this window open, then configure OpenCode, Codex, or ChatGPT as described
176
+ below.
177
+
178
+ ### Option B: use the npm package
179
+
180
+ The npm package is convenient for launching a pinned MCP server. Task
181
+ execution still requires a separate Watcher.
182
+
183
+ ```powershell
184
+ New-Item -ItemType Directory .\patchwarden-runtime
185
+ Set-Location .\patchwarden-runtime
186
+ npm.cmd init -y
187
+ npm.cmd install patchwarden@0.6.0
188
+ Copy-Item .\node_modules\patchwarden\examples\config.example.json .\patchwarden.config.json
189
+ $env:PATCHWARDEN_CONFIG = (Resolve-Path .\patchwarden.config.json)
190
+ node .\node_modules\patchwarden\dist\runner\watch.js
191
+ ```
192
+
193
+ An MCP client can launch:
194
+
195
+ ```text
196
+ npx.cmd -y patchwarden@0.6.0
197
+ ```
198
+
199
+ Pin the version in important environments instead of using `latest`
200
+ unconditionally.
201
+
202
+ ## Complete configuration guide
203
+
204
+ Create a local configuration from the example:
205
+
206
+ ```powershell
207
+ Copy-Item .\examples\config.example.json .\patchwarden.config.json
208
+ ```
209
+
210
+ Recommended Windows example:
211
+
212
+ ```json
213
+ {
214
+ "workspaceRoot": "D:/ai_agent/codex_program",
215
+ "plansDir": ".patchwarden/plans",
216
+ "tasksDir": ".patchwarden/tasks",
217
+ "toolProfile": "full",
218
+ "agents": {
219
+ "opencode": {
220
+ "command": "opencode",
221
+ "args": ["run", "{prompt}"]
222
+ },
223
+ "codex": {
224
+ "command": "codex",
225
+ "args": ["exec", "--cd", "{repo}", "{prompt}"]
226
+ }
227
+ },
228
+ "allowedTestCommands": [
229
+ "npm test",
230
+ "npm run build",
231
+ "npm run lint",
232
+ "pytest"
233
+ ],
234
+ "repoAllowedTestCommands": {
235
+ "desktop-app": ["npm run release:check"]
236
+ },
237
+ "maxReadFileBytes": 200000,
238
+ "defaultTaskTimeoutSeconds": 900,
239
+ "maxTaskTimeoutSeconds": 3600,
240
+ "watcherStaleSeconds": 30,
241
+ "httpPort": 7331
242
+ }
243
+ ```
244
+
245
+ Configuration fields:
246
+
247
+ | Field | Required | Description |
248
+ | --- | --- | --- |
249
+ | `workspaceRoot` | Yes | The only workspace root PatchWarden may access. |
250
+ | `plansDir` | Yes | Plan directory, normally `.patchwarden/plans`. |
251
+ | `tasksDir` | Yes | Task and result directory, normally `.patchwarden/tasks`. |
252
+ | `toolProfile` | No | `full` or `chatgpt_core`; use `full` for local clients. |
253
+ | `agents` | Yes | Execution-agent allowlist; supports `{repo}` and `{prompt}` placeholders. |
254
+ | `allowedTestCommands` | Yes | Exact allowlist for independent verification commands. |
255
+ | `repoAllowedTestCommands` | No | Extra exact commands keyed by workspace-relative repository path; wildcards are unsupported. |
256
+ | `maxReadFileBytes` | Yes | Maximum bytes returned by one MCP file read. |
257
+ | `defaultTaskTimeoutSeconds` | Yes | Default task timeout. |
258
+ | `maxTaskTimeoutSeconds` | Yes | Maximum timeout a client may request. |
259
+ | `watcherStaleSeconds` | Yes | Watcher heartbeat expiry, from 5 to 3600 seconds. |
260
+ | `repoAliases` | No | Short aliases for repositories inside the workspace. |
261
+ | `httpPort` | No | Local HTTP MCP port; default is 7331. |
262
+ | `http.ownerTokenEnv` | No | Environment variable that contains the HTTP owner token. |
263
+
264
+ Important configuration rules:
265
+
266
+ - In Windows JSON, prefer paths such as `D:/path/to/project`.
267
+ - If you use backslashes, escape them as `D:\\path\\to\\project`.
268
+ - Do not set `workspaceRoot` to a drive root, home directory, Desktop,
269
+ Downloads, or Documents.
270
+ - `plansDir` and `tasksDir` are resolved relative to `workspaceRoot`.
271
+ - `repo_path` must stay inside `workspaceRoot` and cannot escape with `..`.
272
+ - `allowedTestCommands` uses exact matching; similar commands are not
273
+ automatically authorized.
274
+ - Repository-specific commands come only from trusted local configuration;
275
+ a target repository cannot authorize itself through `package.json`.
276
+ - Configuration may contain private paths and should not be committed.
277
+
278
+ Set the configuration path:
279
+
280
+ ```powershell
281
+ $env:PATCHWARDEN_CONFIG = "D:\path\to\patchwarden.config.json"
282
+ ```
283
+
284
+ This environment variable affects only the current PowerShell process and its
285
+ children. Set it again in every separately opened terminal that starts a
286
+ Watcher or MCP Server.
287
+
288
+ ## Connect OpenCode
289
+
290
+ Local source mode is recommended so the MCP Server, Watcher, and
291
+ configuration remain on the same version.
292
+
293
+ Edit:
294
+
295
+ ```text
296
+ %USERPROFILE%\.config\opencode\opencode.jsonc
297
+ ```
298
+
299
+ Example:
300
+
301
+ ```jsonc
302
+ {
303
+ "mcp": {
304
+ "patchwarden": {
305
+ "type": "local",
306
+ "command": [
307
+ "node",
308
+ "D:/path/to/PatchWarden/dist/index.js"
309
+ ],
310
+ "environment": {
311
+ "PATCHWARDEN_CONFIG": "D:/path/to/PatchWarden/patchwarden.config.json",
312
+ "PATCHWARDEN_TOOL_PROFILE": "full"
313
+ },
314
+ "enabled": true
315
+ }
316
+ }
317
+ }
318
+ ```
319
+
320
+ Verify the connection:
321
+
322
+ ```powershell
323
+ opencode mcp list
324
+ ```
325
+
326
+ Expected result:
327
+
328
+ ```text
329
+ patchwarden connected
330
+ ```
331
+
332
+ In a separate PowerShell window, start the Watcher:
333
+
334
+ ```powershell
335
+ $env:PATCHWARDEN_CONFIG = (Resolve-Path .\patchwarden.config.json)
336
+ npm.cmd run watch
337
+ ```
338
+
339
+ If OpenCode sees the MCP tools but tasks remain queued, check the Watcher
340
+ before repeatedly deleting and recreating the MCP entry.
341
+
342
+ ## Connect Codex
343
+
344
+ Edit:
345
+
346
+ ```text
347
+ %USERPROFILE%\.codex\config.toml
348
+ ```
349
+
350
+ Pinned npm configuration:
351
+
352
+ ```toml
353
+ [mcp_servers.patchwarden]
354
+ command = "npx.cmd"
355
+ args = ["-y", "patchwarden@0.6.0"]
356
+
357
+ [mcp_servers.patchwarden.env]
358
+ PATCHWARDEN_CONFIG = "D:\\path\\to\\patchwarden.config.json"
359
+ PATCHWARDEN_TOOL_PROFILE = "full"
360
+ ```
361
+
362
+ Local source configuration:
363
+
364
+ ```toml
365
+ [mcp_servers.patchwarden]
366
+ command = "node"
367
+ args = ["D:\\path\\to\\PatchWarden\\dist\\index.js"]
368
+
369
+ [mcp_servers.patchwarden.env]
370
+ PATCHWARDEN_CONFIG = "D:\\path\\to\\PatchWarden\\patchwarden.config.json"
371
+ PATCHWARDEN_TOOL_PROFILE = "full"
372
+ ```
373
+
374
+ Fully exit and reopen Codex Desktop after editing the configuration, then
375
+ start a new conversation. Existing conversations may retain the old MCP tool
376
+ catalog.
377
+
378
+ Codex as an **MCP client** and the Codex CLI as an **execution agent** are
379
+ different roles. A successful MCP connection does not prove that the CLI
380
+ configured under `agents` is available.
381
+
382
+ ## Connect ChatGPT
383
+
384
+ Recommended Windows path:
385
+
386
+ ```text
387
+ ChatGPT Web
388
+ → ChatGPT Connector
389
+ → OpenAI Secure MCP Tunnel
390
+ → PatchWarden stdio MCP
391
+ → Watcher
392
+ → local agent
393
+ ```
394
+
395
+ ### One-click launcher
396
+
397
+ Prepare:
398
+
399
+ - A built PatchWarden source checkout
400
+ - A valid `patchwarden.config.json`
401
+ - `tunnel-client.exe`
402
+ - A Tunnel ID
403
+ - A tunnel runtime API key
404
+ - A working HTTP proxy with a supported exit region
405
+
406
+ Configure the proxy first, then run:
407
+
408
+ ```text
409
+ PatchWarden.cmd start core
410
+ ```
411
+
412
+ The launcher:
413
+
414
+ - Builds `dist/index.js` if it is missing.
415
+ - Verifies v0.6.0, the fixed 16-tool `chatgpt_core` catalog, and its schema
416
+ manifest.
417
+ - Reads or prompts for the Tunnel ID.
418
+ - Reads or prompts for the runtime API key.
419
+ - Stores credentials with Windows DPAPI under `%APPDATA%\patchwarden`.
420
+ - Starts and supervises only the Watcher it owns.
421
+ - Runs `tunnel-client doctor` and readiness checks.
422
+ - Applies capped retries to recoverable disconnects.
423
+
424
+ Runtime status is stored under:
425
+
426
+ ```text
427
+ %LOCALAPPDATA%\patchwarden\runtime
428
+ ```
429
+
430
+ This directory contains PIDs, health state, and redacted diagnostics. It must
431
+ not contain the API key or Tunnel ID.
432
+
433
+ When creating the ChatGPT Connector:
434
+
435
+ - Select the tunnel **Channel**.
436
+ - Choose **None** for authentication unless you implemented OAuth.
437
+ - Do not use the local `127.0.0.1` address as a public Server URL.
438
+ - Reconnect the Connector and open a new ChatGPT conversation after changes.
439
+ - Disable browser translation extensions if the Platform page behaves
440
+ unexpectedly.
441
+
442
+ See [examples/openai-tunnel/README.md](examples/openai-tunnel/README.md) for
443
+ the expanded tunnel examples.
444
+
445
+ ## Proxy configuration: read this first
446
+
447
+ ### Launcher default
448
+
449
+ `scripts/start-patchwarden-tunnel.ps1` first reads `HTTPS_PROXY` from the
450
+ current process. If it is absent, the launcher defaults to:
451
+
452
+ ```text
453
+ http://127.0.0.1:7892
454
+ ```
455
+
456
+ **Port 7892 is not universal.** Clash, Mihomo, V2Ray, sing-box, and other proxy
457
+ applications may use 7890, 7897, 10809, or a custom port. Check the actual
458
+ HTTP/Mixed listening port in your proxy application instead of copying the
459
+ example.
460
+
461
+ Test the port:
462
+
463
+ ```powershell
464
+ Test-NetConnection 127.0.0.1 -Port 7892
465
+ ```
466
+
467
+ If `TcpTestSucceeded` is `False`, no proxy service is listening on that port.
468
+
469
+ ### Recommended environment
470
+
471
+ These variables affect only the current PowerShell process and its children.
472
+ They do not modify system-wide environment variables:
473
+
474
+ ```powershell
475
+ $env:HTTPS_PROXY = "http://127.0.0.1:YOUR_HTTP_OR_MIXED_PORT"
476
+ $env:HTTP_PROXY = $env:HTTPS_PROXY
477
+ $env:ALL_PROXY = $env:HTTPS_PROXY
478
+ $env:NO_PROXY = "localhost,127.0.0.1,::1"
479
+ .\PatchWarden.cmd start core
480
+ ```
481
+
482
+ Example for a Mixed port of 7890:
483
+
484
+ ```powershell
485
+ $env:HTTPS_PROXY = "http://127.0.0.1:7890"
486
+ $env:HTTP_PROXY = $env:HTTPS_PROXY
487
+ $env:ALL_PROXY = $env:HTTPS_PROXY
488
+ $env:NO_PROXY = "localhost,127.0.0.1,::1"
489
+ .\PatchWarden.cmd start core
490
+ ```
491
+
492
+ Using `HTTPS_PROXY=http://...` is expected: the variable identifies HTTPS
493
+ requests that should use a proxy, while the `http://` scheme describes the
494
+ local HTTP proxy endpoint. Do not enter a SOCKS-only port into the current
495
+ `--http-proxy` setting.
496
+
497
+ ### Three separate network paths
498
+
499
+ | Network path | Proxy? | Notes |
500
+ | --- | --- | --- |
501
+ | Tunnel → OpenAI control plane | Usually | The launcher passes `HTTPS_PROXY` to tunnel-client. |
502
+ | PatchWarden → `127.0.0.1` | No | Keep `NO_PROXY=localhost,127.0.0.1,::1`. |
503
+ | Local agent → model provider API | Agent-specific | The Watcher and child agent may inherit terminal proxy variables. |
504
+ | npm / GitHub | Network-specific | Their connectivity is separate from tunnel health. |
505
+
506
+ If you start the Watcher manually and want its child agent to use the same
507
+ proxy, set the proxy variables in the PowerShell window that launches the
508
+ Watcher.
509
+
510
+ ### Region errors are not code errors
511
+
512
+ If logs show:
513
+
514
+ ```text
515
+ unsupported_country_region_territory
516
+ 403 Forbidden
517
+ ```
518
+
519
+ the proxy exit region is not accepted by the current OpenAI control plane.
520
+ Reinstalling dependencies, rebuilding `dist`, or repeatedly logging in will
521
+ usually not address this condition. Switch to a supported exit region and
522
+ restart the tunnel. Support can change, so this project does not hard-code a
523
+ country list.
524
+
525
+ ### Proxy troubleshooting order
526
+
527
+ 1. Confirm the proxy application is running.
528
+ 2. Use its actual HTTP/Mixed port, not a copied example.
529
+ 3. Confirm `Test-NetConnection` succeeds.
530
+ 4. Set `HTTPS_PROXY` in the same terminal that starts the tunnel.
531
+ 5. Keep local addresses in `NO_PROXY`.
532
+ 6. Check whether the exit region is accepted.
533
+ 7. Then run `PatchWarden.cmd health` and tunnel-client doctor.
534
+
535
+ ## Recommended task workflow
536
+
537
+ Use this sequence:
538
+
539
+ 1. `health_check` — verify version, workspace, Watcher, and tool catalog.
540
+ 2. `list_agents` — confirm the local execution agent is available.
541
+ 3. `list_workspace` — identify the correct `repo_path`.
542
+ 4. `save_plan`, or provide an `inline_plan` when creating the task.
543
+ 5. `create_task` — specify the agent, repository, and verification commands.
544
+ 6. Use `wait_for_task(timeout_seconds: 25)` for short tasks; poll long tasks with `list_tasks` and `get_task_status`.
545
+ 7. `get_task_summary(view: "compact")` — inspect bounded structured evidence first.
546
+ 8. `get_result_json`, `get_diff`, and `get_test_log` — inspect detail as needed.
547
+ 9. `audit_task` — independently verify the result.
548
+ 10. Let a human decide whether to accept, commit, or publish.
549
+
550
+ Example `create_task` payload:
551
+
552
+ ```json
553
+ {
554
+ "agent": "opencode",
555
+ "repo_path": "my-project",
556
+ "inline_plan": "Fix form validation on the login page, avoid unrelated files, and add regression coverage.",
557
+ "verify_commands": [
558
+ "npm run build",
559
+ "npm test"
560
+ ],
561
+ "timeout_seconds": 900
562
+ }
563
+ ```
564
+
565
+ Rules:
566
+
567
+ - `repo_path` must stay inside `workspaceRoot`.
568
+ - Every `verify_commands` entry must exactly match the global or current
569
+ repository's trusted command allowlist.
570
+ - Select exactly one plan source: `plan_id`, `inline_plan`, or `template`.
571
+ - When `wait_for_task` returns `continuation_required: true`, call it again.
572
+ - `terminal: true` means the task reached a terminal state, not that the work
573
+ is correct.
574
+
575
+ Built-in templates:
576
+
577
+ - `inspect_only`
578
+ - `feature_small`
579
+ - `fix_tests`
580
+ - `release_check`
581
+ - `rollback_scope_violation`
582
+
583
+ ChatGPT tasks should prefer the first three guarded templates: use
584
+ `inspect_only` for read-only diagnosis, `feature_small` for a narrowly scoped
585
+ change, and `fix_tests` for a known verification failure. Use `inline_plan` or
586
+ a saved long plan only when these templates cannot express the goal. Prefer an
587
+ `execution_mode: "assess_only"` call followed by the returned `next_tool_call`;
588
+ do not resend the goal, plan, repository, agent, or verification arguments in
589
+ the execute call.
590
+
591
+ `inspect_only` and rollback-review tasks fail with
592
+ `failed_policy_violation` if they modify files. Rollback review only writes a
593
+ plan; it never automatically reverts user changes.
594
+
595
+ `audit_task` places evidence-backed failures in `confirmed_failures` and lists
596
+ heuristic warnings separately in `possible_false_positives` and
597
+ `manual_verification_items`. A `warn` verdict therefore does not automatically
598
+ mean the task is wrong.
599
+
600
+ ### Task artifacts
601
+
602
+ | File | Purpose |
603
+ | --- | --- |
604
+ | `status.json` | Current status, phase, heartbeat, and error details. |
605
+ | `progress.md` | Progress reported by the agent. |
606
+ | `result.md` | Human-readable execution report. |
607
+ | `result.json` | Structured result, paths, changes, warnings, and next steps. |
608
+ | `diff.patch` | Complete task change evidence. |
609
+ | `file-stats.json` | Per-file addition and deletion statistics. |
610
+ | `verify.json` | Structured record for every independent verification command. |
611
+ | `verify.log` | Human-readable independent verification output. |
612
+ | `test.log` | Test output captured during agent execution. |
613
+
614
+ An agent saying “published” or “pushed” is not reliable remote evidence.
615
+ Verify GitHub, npm, tags, and releases against the live platform state.
616
+
617
+ ## HTTP MCP mode
618
+
619
+ The HTTP server binds only to `127.0.0.1`. The default port is 7331 and it is
620
+ not directly exposed to the LAN.
621
+
622
+ Terminal 1 — start the Watcher:
623
+
624
+ ```powershell
625
+ $env:PATCHWARDEN_CONFIG = (Resolve-Path .\patchwarden.config.json)
626
+ npm.cmd run watch
627
+ ```
628
+
629
+ Terminal 2 — start HTTP MCP:
630
+
631
+ ```powershell
632
+ $env:PATCHWARDEN_CONFIG = (Resolve-Path .\patchwarden.config.json)
633
+ npm.cmd run start:http
634
+ ```
635
+
636
+ Health check:
637
+
638
+ ```powershell
639
+ Invoke-RestMethod http://127.0.0.1:7331/healthz
640
+ ```
641
+
642
+ MCP endpoint:
643
+
644
+ ```text
645
+ http://127.0.0.1:7331/mcp
646
+ ```
647
+
648
+ Optional token configuration:
649
+
650
+ ```json
651
+ {
652
+ "httpPort": 7331,
653
+ "http": {
654
+ "ownerTokenEnv": "PATCHWARDEN_OWNER_TOKEN"
655
+ }
656
+ }
657
+ ```
658
+
659
+ Set the token in the PowerShell process that starts the server:
660
+
661
+ ```powershell
662
+ $env:PATCHWARDEN_OWNER_TOKEN = "use-a-random-local-only-value"
663
+ ```
664
+
665
+ Clients can send `Authorization: Bearer ...` or `x-patchwarden-token`. Never
666
+ write the token into configuration, documentation, logs, or Git.
667
+
668
+ > [!CAUTION]
669
+ > Do not expose local port 7331 through router port forwarding, a
670
+ > `0.0.0.0` relay, or an ordinary reverse proxy. Use an authenticated secure
671
+ > tunnel for remote access.
672
+
673
+ ## Diagnostics and health checks
674
+
675
+ Project diagnostics:
676
+
677
+ ```powershell
678
+ npm.cmd run doctor
679
+ ```
680
+
681
+ Doctor checks Node, npm, Git, configuration, workspace containment, sensitive
682
+ path protection, agent commands, the tool manifest, HTTP port, task
683
+ directories, and build output.
684
+
685
+ ### Unified Windows control entry point
686
+
687
+ Double-click `PatchWarden.cmd` for one menu that starts, stops, restarts, and
688
+ checks Core Agent and Direct independently or together. The same operations are
689
+ available from PowerShell:
690
+
691
+ ```powershell
692
+ .\PatchWarden.cmd start core
693
+ .\PatchWarden.cmd start direct
694
+ .\PatchWarden.cmd stop all
695
+ .\PatchWarden.cmd restart all
696
+ .\PatchWarden.cmd status all
697
+ .\PatchWarden.cmd kill all
698
+ ```
699
+
700
+ The old single-purpose launchers remain under `scripts/launchers/` as a
701
+ compatibility layer. Personal launchers live under `.local/launchers/` and
702
+ remain excluded from Git and release packages. `stop` and `restart` correlate
703
+ runtime state with the exact Tunnel profile, project launcher, and process tree,
704
+ so they can clean up an orphaned `tunnel-client.exe` for that profile without
705
+ terminating unrelated processes. `kill` is an explicit force-clean command but
706
+ keeps the same profile and project-path restrictions. If an unrelated process
707
+ owns port 8080 or 8081, the operation stops and reports its PID.
708
+
709
+ `status` cross-checks runtime JSON, the health URL file, the fixed `/readyz` and
710
+ `/healthz` endpoints, and the real process list. A ready endpoint therefore wins
711
+ over a stale stopped status file. Supervisor output is written to:
712
+
713
+ ```text
714
+ %LOCALAPPDATA%\patchwarden\runtime\tunnel-client.stdout.log
715
+ %LOCALAPPDATA%\patchwarden\runtime\tunnel-client.stderr.log
716
+ %LOCALAPPDATA%\patchwarden\runtime-direct\tunnel-client.stdout.log
717
+ %LOCALAPPDATA%\patchwarden\runtime-direct\tunnel-client.stderr.log
718
+ ```
719
+
720
+ On a non-zero exit, the launcher displays the last 30 stderr lines and records
721
+ the exit code, redacted stdout/stderr tails, and log paths in
722
+ `tunnel-status.json`. It never prints the API key value.
723
+
724
+ Detailed Windows tunnel health:
725
+
726
+ ```text
727
+ PatchWarden.cmd health
728
+ ```
729
+
730
+ It reports:
731
+
732
+ - Source and `dist` versions
733
+ - The real MCP process source
734
+ - Tool profile, count, names, and schema hash
735
+ - Workspace and task-directory access
736
+ - Watcher heartbeat
737
+ - Tunnel readiness
738
+ - Mixed-version process warnings
739
+
740
+ The check is read-only and does not terminate processes.
741
+
742
+ For expanded MCP diagnostics, call `health_check` with:
743
+
744
+ ```json
745
+ {
746
+ "detail": "self_diagnostic"
747
+ }
748
+ ```
749
+
750
+ This includes configured agents, allowlist counts, recent failures, and tool
751
+ catalog consistency.
752
+
753
+ After a configuration or version change, use:
754
+
755
+ ```text
756
+ PatchWarden.cmd restart all
757
+ ```
758
+
759
+ It stops only this project's launchers and Watcher plus `tunnel-client.exe`
760
+ processes that exactly match the selected profile. It does not globally
761
+ terminate unrelated PatchWarden, OpenCode, or Codex instances.
762
+
763
+ ## Lessons learned and troubleshooting
764
+
765
+ ### Quick reference
766
+
767
+ | Symptom | Most likely cause | Fix |
768
+ | --- | --- | --- |
769
+ | Tunnel connection keeps timing out | No proxy is listening on default port 7892 | Find the real HTTP/Mixed port, set `HTTPS_PROXY`, and start from the same terminal. |
770
+ | Logs show 403 and `unsupported_country_region_territory` | Unsupported proxy exit region | Switch exit region and restart the tunnel. |
771
+ | `list_workspace` only shows `tunnel-client.exe` | MCP started in the wrong directory or did not receive the config path | Use `scripts/patchwarden-mcp-stdio.cmd`. |
772
+ | MCP is connected, but tasks do not run | Watcher is missing or stale | Start `npm.cmd run watch` and inspect `health_check`. |
773
+ | `Agent command not found` | Agent is not on PATH, or Codex Desktop was mistaken for the CLI | Run `where.exe` and use the real CLI path in `agents.command`. |
774
+ | Verification command is rejected | It does not exactly match the allowlist | Add the exact command to `allowedTestCommands`. |
775
+ | ChatGPT still shows old tools | Connector or conversation cached the old catalog | Reconnect and open a new ChatGPT conversation. |
776
+ | ChatGPT stops after `create_task` | The same turn did not continue with `wait_for_task` | Loop while `continuation_required` is true. |
777
+ | HTTP reports `EADDRINUSE` | Port 7331 is already in use | Check the existing instance or change `httpPort`. |
778
+ | DPAPI credential cannot be decrypted | Windows user/machine changed or the cache is damaged | Run `PatchWarden.cmd reset-key` and enter it again. |
779
+ | Code changed but runtime behavior did not | Old `dist` or process is still active | Build, compare the manifest, and restart owned processes. |
780
+ | The supervisor shows only exit code 1 | The real tunnel-client failure is in child-process stderr | Read the mode's `tunnel-client.stderr.log` or `tunnel-status.json.stderr_tail`. |
781
+ | Core looks for its profile under `opencode-config\tunnel-client` | An older launcher leaked the Watcher's `XDG_CONFIG_HOME` into tunnel-client | Upgrade to v0.6.0 and run `PatchWarden.cmd restart core`; v0.6.0 isolates Watcher-only environment variables. |
782
+ | npm MCP initializes, but tasks remain queued | npm launched only the MCP Server | Start `dist/runner/watch.js` in the local installation. |
783
+ | Config exists but is not found | Variable was set in another terminal or path escaping is wrong | Use an absolute path and set `PATCHWARDEN_CONFIG` in the launching terminal. |
784
+ | Legacy environment names are ignored | v0.4.0 intentionally broke old names | Use `PATCHWARDEN_*` everywhere. |
785
+
786
+ ### Lesson 1: connected is not end-to-end readiness
787
+
788
+ An MCP connection proves only that the client started PatchWarden. Also check:
789
+
790
+ 1. `health_check` sees the intended workspace.
791
+ 2. `list_agents` finds the execution agent.
792
+ 3. The Watcher heartbeat is fresh.
793
+ 4. A task moves from queued to running.
794
+
795
+ ### Lesson 2: do not copy proxy port 7892 blindly
796
+
797
+ Port 7892 is a launcher default, not a standard shared by all proxy clients.
798
+ Check the proxy application and run `Test-NetConnection` before reinstalling
799
+ Node or PatchWarden.
800
+
801
+ ### Lesson 3: do not proxy localhost
802
+
803
+ HTTP MCP, health endpoints, and the tunnel-client UI use loopback addresses.
804
+ Keep:
805
+
806
+ ```powershell
807
+ $env:NO_PROXY = "localhost,127.0.0.1,::1"
808
+ ```
809
+
810
+ ### Lesson 4: old sessions can keep old schemas
811
+
812
+ Connectors and MCP clients may cache tool catalogs when a session opens.
813
+ Compare `server_version`, `schema_epoch`, and
814
+ `tool_manifest_sha256`, then reconnect and create a new session.
815
+
816
+ ### Lesson 5: stale Watchers and unsafe process killing
817
+
818
+ PatchWarden uses heartbeat age to determine Watcher health. The launcher
819
+ supervises only the Watcher it created, and restart scripts touch only owned
820
+ processes. Do not use broad commands such as `taskkill /IM node.exe`; they can
821
+ terminate unrelated Node, Codex, or OpenCode work.
822
+
823
+ ### Lesson 6: oversized workspace roots
824
+
825
+ Using a drive, home directory, or mixed workspace as `workspaceRoot` expands
826
+ scan scope, privacy risk, and accidental unrelated changes. Use a dedicated
827
+ code directory and point each task at a specific relative `repo_path`.
828
+
829
+ ### Lesson 7: execution finished is not acceptance
830
+
831
+ `done` only means the agent process finished. Still verify:
832
+
833
+ - Whether `failed_scope_violation` occurred
834
+ - Whether every record in `verify.json` passed
835
+ - Whether `diff.patch` contains only intended changes
836
+ - Whether `audit_task` found inconsistent claims
837
+ - Whether claimed npm, GitHub, tag, or release state exists remotely
838
+
839
+ ### Lesson 8: rename migration does not read old state
840
+
841
+ PatchWarden v0.4.0 does not automatically read legacy CLI names, environment
842
+ variables, headers, task directories, or DPAPI credentials. Preserve old data
843
+ as a backup if needed, but configure all new runs with PatchWarden paths and
844
+ names.
845
+
846
+ ## MCP tools and profiles
847
+
848
+ `chatgpt_core` is the fixed 16-tool profile used by the ChatGPT tunnel:
849
+
850
+ `health_check`, `list_agents`, `list_workspace`,
851
+ `read_workspace_file`, `save_plan`, `create_task`,
852
+ `wait_for_task`, `get_task_summary`, `get_diff`, `get_result`,
853
+ `get_result_json`, `get_test_log`, `get_task_status`, `list_tasks`,
854
+ `cancel_task`, and `audit_task`.
855
+
856
+ `get_task_summary` keeps the backward-compatible `standard` view by default.
857
+ ChatGPT should request `view: "compact"` first; terminal `wait_for_task`
858
+ responses also embed compact acceptance evidence only.
859
+
860
+ `full` additionally provides:
861
+
862
+ - `get_plan`
863
+ - `kill_task`
864
+ - `retry_task`
865
+ - `get_task_progress`
866
+ - `get_task_stdout_tail`
867
+ - `get_task_log_tail`
868
+
869
+ The tunnel wrapper forces `chatgpt_core`. Ordinary local development defaults
870
+ to `full`.
871
+
872
+ ### ChatGPT Direct mode
873
+
874
+ Direct mode exposes nine guarded tools so ChatGPT can create an editing
875
+ session, read and search source files, apply hash-bound JSON patches, run
876
+ exactly allowlisted verification commands, finalize the evidence, and audit
877
+ the result without a local execution agent.
878
+
879
+ Enable it in the trusted local configuration while keeping the ordinary Core
880
+ profile unchanged:
881
+
882
+ ```json
883
+ {
884
+ "enableDirectProfile": true
885
+ }
886
+ ```
887
+
888
+ Start the separate Direct tunnel entrypoint:
889
+
890
+ ```text
891
+ PatchWarden.cmd start direct
892
+ ```
893
+
894
+ On first use, provide the `tunnel-client.exe` path and a Tunnel ID dedicated
895
+ to the Direct Connector. The launcher uses the `patchwarden-direct` profile,
896
+ stores runtime state under `%LOCALAPPDATA%\patchwarden\runtime-direct`, skips
897
+ the Watcher, and retains the existing DPAPI credential handling. In a fresh
898
+ ChatGPT conversation, `health_check` should report `chatgpt_direct`, nine
899
+ tools, and `direct_profile_enabled=true`.
900
+
901
+ ## Security boundaries and local data
902
+
903
+ Primary protections:
904
+
905
+ - MCP tools do not expose a general shell.
906
+ - Agent commands and argument templates must be configured in advance.
907
+ - Verification commands must exactly match the allowlist.
908
+ - File access is contained to `workspaceRoot`.
909
+ - Sensitive filenames and obvious credential-read plans are blocked.
910
+ - Secret-like values in task artifacts are redacted.
911
+ - HTTP mode binds only to `127.0.0.1`.
912
+ - The Runner does not automatically commit, push, publish, or reset.
913
+
914
+ Protect these local paths:
915
+
916
+ | Path | Content | Commit? |
917
+ | --- | --- | --- |
918
+ | `patchwarden.config.json` | Private paths, agents, command allowlist | No |
919
+ | `.patchwarden/` | Plans, tasks, diffs, and logs | No |
920
+ | `%APPDATA%\patchwarden` | DPAPI-encrypted tunnel credential | No |
921
+ | `%LOCALAPPDATA%\patchwarden` | Runtime status and isolated configuration | No |
922
+
923
+ Never commit API keys, tokens, Tunnel IDs, ChatGPT Workspace IDs, cookies,
924
+ `.env` files, private project paths, or real task logs.
925
+
926
+ PatchWarden reduces accidental exposure, but it does not replace human review.
927
+ Start with a dedicated test workspace and a repository you can recover.
928
+
929
+ ## Upgrading and migration
930
+
931
+ Upgrade a pinned npm installation:
932
+
933
+ ```powershell
934
+ npm.cmd install patchwarden@0.6.0
935
+ ```
936
+
937
+ Upgrade a source checkout:
938
+
939
+ ```powershell
940
+ git pull --ff-only
941
+ npm.cmd ci
942
+ npm.cmd run build
943
+ npm.cmd test
944
+ ```
945
+
946
+ After upgrading:
947
+
948
+ 1. Run `npm.cmd run doctor`.
949
+ 2. Run `PatchWarden.cmd health`.
950
+ 3. Compare version, schema epoch, and manifest hash.
951
+ 4. Restart owned processes with `PatchWarden.cmd restart all`.
952
+ 5. Reconnect the MCP client or Connector.
953
+ 6. Validate in a new session instead of relying on an old conversation.
954
+
955
+ When migrating from Safe-Bifrost, manually update:
956
+
957
+ - npm package and CLIs include `patchwarden`, `patchwarden-runner`, and the
958
+ local-only medium-risk ticket confirmation command `patchwarden-confirm`
959
+ - Configuration filename to `patchwarden.config.json`
960
+ - Environment variables to `PATCHWARDEN_*`
961
+ - Task directory to `.patchwarden/`
962
+ - HTTP header to `x-patchwarden-token`
963
+ - AppData directory to `patchwarden`
964
+
965
+ Old data is not deleted and is not read as an automatic fallback. See the
966
+ [migration guide](docs/migration-from-safe-bifrost.md).
967
+
968
+ ## Development and release verification
969
+
970
+ Windows PowerShell:
971
+
972
+ ```powershell
973
+ npm.cmd run build
974
+ npm.cmd test
975
+ npm.cmd run test:mcp
976
+ npm.cmd run test:http-mcp
977
+ npm.cmd run doctor
978
+ npm.cmd run check:tool-manifest
979
+ npm.cmd run check:brand
980
+ npm.cmd run test:tunnel-supervisor
981
+ npm.cmd run test:watcher-supervisor
982
+ npm.cmd run pack:clean
983
+ npm.cmd run verify:package
984
+ ```
985
+
986
+ Package checks exclude:
987
+
988
+ - `node_modules/`
989
+ - `.patchwarden/`
990
+ - `*.log`
991
+ - `.env`
992
+ - `patchwarden.config.json`
993
+ - Local credentials and runtime state
994
+
995
+ Before publishing, verify npm Registry state, remote tags, the GitHub Release,
996
+ and release-asset checksums independently.
997
+
998
+ ## Related documentation
999
+
1000
+ - [v0.6.0 release notes](docs/release-v0.6.0.md)
1001
+ - [ChatGPT usage guide](docs/chatgpt-usage.md)
1002
+ - [Migration guide](docs/migration-from-safe-bifrost.md)
1003
+ - [ChatGPT Connector demo](docs/demo.md)
1004
+ - [OpenAI tunnel examples](examples/openai-tunnel/README.md)
1005
+ - [ChatGPT test prompt](examples/openai-tunnel/chatgpt-test-prompt.md)
1006
+
1007
+ ## Roadmap
1008
+
1009
+ - [x] stdio MCP Server
1010
+ - [x] Plan and Task lifecycle
1011
+ - [x] Runner and Watcher
1012
+ - [x] HTTP MCP Server
1013
+ - [x] ChatGPT Connector / tunnel
1014
+ - [x] Doctor and runtime health checks
1015
+ - [x] Tool manifest and schema-drift detection
1016
+ - [ ] Worktree isolation
1017
+ - [ ] Multi-agent task queue
1018
+ - [ ] Local dashboard
1019
+
1020
+ ## License
1021
+
1022
+ [MIT](LICENSE)