patchwarden 0.6.4 → 1.5.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 (254) hide show
  1. package/README.en.md +54 -20
  2. package/README.md +48 -21
  3. package/dist/agents/agentRouter.d.ts +40 -0
  4. package/dist/agents/agentRouter.js +95 -0
  5. package/dist/config.d.ts +1 -1
  6. package/dist/config.js +6 -2
  7. package/dist/controlCenter.js +212 -3
  8. package/dist/direct/directSessionStore.d.ts +2 -0
  9. package/dist/direct/directVerification.js +7 -0
  10. package/dist/doctor.js +32 -1
  11. package/dist/goal/acceptanceEngine.d.ts +62 -0
  12. package/dist/goal/acceptanceEngine.js +103 -0
  13. package/dist/goal/acceptanceTemplate.d.ts +10 -0
  14. package/dist/goal/acceptanceTemplate.js +104 -0
  15. package/dist/goal/goalGraph.d.ts +58 -0
  16. package/dist/goal/goalGraph.js +189 -0
  17. package/dist/goal/goalProgress.d.ts +81 -0
  18. package/dist/goal/goalProgress.js +216 -0
  19. package/dist/goal/goalStatus.d.ts +60 -0
  20. package/dist/goal/goalStatus.js +137 -0
  21. package/dist/goal/goalStore.d.ts +79 -0
  22. package/dist/goal/goalStore.js +211 -0
  23. package/dist/goal/handoffExport.d.ts +34 -0
  24. package/dist/goal/handoffExport.js +183 -0
  25. package/dist/goal/subgoalSync.d.ts +40 -0
  26. package/dist/goal/subgoalSync.js +72 -0
  27. package/dist/goal/worktreeManager.d.ts +96 -0
  28. package/dist/goal/worktreeManager.js +292 -0
  29. package/dist/logging.d.ts +44 -0
  30. package/dist/logging.js +68 -0
  31. package/dist/policy/projectPolicy.d.ts +55 -0
  32. package/dist/policy/projectPolicy.js +286 -0
  33. package/dist/release/releaseGate.d.ts +99 -0
  34. package/dist/release/releaseGate.js +475 -0
  35. package/dist/runner/postTaskCleanup.d.ts +13 -0
  36. package/dist/runner/postTaskCleanup.js +147 -0
  37. package/dist/runner/runTask.js +50 -10
  38. package/dist/security/discoveryTokenStore.d.ts +62 -0
  39. package/dist/security/discoveryTokenStore.js +100 -0
  40. package/dist/security/toolInvocationGuard.d.ts +35 -0
  41. package/dist/security/toolInvocationGuard.js +153 -0
  42. package/dist/smoke-test.js +18 -10
  43. package/dist/taskRuntime.d.ts +17 -0
  44. package/dist/test/unit/acceptance-engine.test.d.ts +1 -0
  45. package/dist/test/unit/acceptance-engine.test.js +228 -0
  46. package/dist/test/unit/agent-router.test.d.ts +1 -0
  47. package/dist/test/unit/agent-router.test.js +287 -0
  48. package/dist/test/unit/audit-checks.test.d.ts +1 -0
  49. package/dist/test/unit/audit-checks.test.js +350 -0
  50. package/dist/test/unit/diagnose-task.test.d.ts +1 -0
  51. package/dist/test/unit/diagnose-task.test.js +457 -0
  52. package/dist/test/unit/discovery-token-store.test.d.ts +1 -0
  53. package/dist/test/unit/discovery-token-store.test.js +139 -0
  54. package/dist/test/unit/evidence-pack.test.d.ts +1 -0
  55. package/dist/test/unit/evidence-pack.test.js +130 -0
  56. package/dist/test/unit/goal-graph.test.d.ts +1 -0
  57. package/dist/test/unit/goal-graph.test.js +298 -0
  58. package/dist/test/unit/goal-progress.test.d.ts +1 -0
  59. package/dist/test/unit/goal-progress.test.js +381 -0
  60. package/dist/test/unit/goal-status.test.d.ts +1 -0
  61. package/dist/test/unit/goal-status.test.js +215 -0
  62. package/dist/test/unit/goal-store.test.d.ts +1 -0
  63. package/dist/test/unit/goal-store.test.js +253 -0
  64. package/dist/test/unit/goal-subgoal-task.test.d.ts +1 -0
  65. package/dist/test/unit/goal-subgoal-task.test.js +55 -0
  66. package/dist/test/unit/goal-tools-registry.test.d.ts +1 -0
  67. package/dist/test/unit/goal-tools-registry.test.js +190 -0
  68. package/dist/test/unit/handoff-export.test.d.ts +1 -0
  69. package/dist/test/unit/handoff-export.test.js +263 -0
  70. package/dist/test/unit/invoke-discovered-tool.test.d.ts +1 -0
  71. package/dist/test/unit/invoke-discovered-tool.test.js +167 -0
  72. package/dist/test/unit/logging.test.js +127 -5
  73. package/dist/test/unit/post-task-cleanup.test.d.ts +1 -0
  74. package/dist/test/unit/post-task-cleanup.test.js +48 -0
  75. package/dist/test/unit/project-policy-release-mode.test.d.ts +1 -0
  76. package/dist/test/unit/project-policy-release-mode.test.js +125 -0
  77. package/dist/test/unit/reconcile-tasks.test.d.ts +1 -0
  78. package/dist/test/unit/reconcile-tasks.test.js +456 -0
  79. package/dist/test/unit/release-gate.test.d.ts +1 -0
  80. package/dist/test/unit/release-gate.test.js +242 -0
  81. package/dist/test/unit/run-task-loop.test.d.ts +1 -0
  82. package/dist/test/unit/run-task-loop.test.js +380 -0
  83. package/dist/test/unit/safe-views.test.d.ts +1 -0
  84. package/dist/test/unit/safe-views.test.js +171 -0
  85. package/dist/test/unit/schema-drift-check.test.d.ts +1 -0
  86. package/dist/test/unit/schema-drift-check.test.js +176 -0
  87. package/dist/test/unit/subgoal-sync.test.d.ts +1 -0
  88. package/dist/test/unit/subgoal-sync.test.js +183 -0
  89. package/dist/test/unit/tool-invocation-guard.test.d.ts +1 -0
  90. package/dist/test/unit/tool-invocation-guard.test.js +432 -0
  91. package/dist/test/unit/tool-usage-stats.test.d.ts +1 -0
  92. package/dist/test/unit/tool-usage-stats.test.js +300 -0
  93. package/dist/test/unit/toolSearch.test.d.ts +1 -0
  94. package/dist/test/unit/toolSearch.test.js +571 -0
  95. package/dist/test/unit/worktree-manager.test.d.ts +1 -0
  96. package/dist/test/unit/worktree-manager.test.js +176 -0
  97. package/dist/tools/auditTask.d.ts +103 -1
  98. package/dist/tools/auditTask.js +461 -8
  99. package/dist/tools/cancelTask.js +1 -1
  100. package/dist/tools/checkReleaseGate.d.ts +21 -0
  101. package/dist/tools/checkReleaseGate.js +22 -0
  102. package/dist/tools/createTask.d.ts +18 -2
  103. package/dist/tools/createTask.js +29 -1
  104. package/dist/tools/diagnoseTask.d.ts +45 -0
  105. package/dist/tools/diagnoseTask.js +347 -0
  106. package/dist/tools/discardWorktree.d.ts +24 -0
  107. package/dist/tools/discardWorktree.js +27 -0
  108. package/dist/tools/discoverTools.d.ts +11 -0
  109. package/dist/tools/discoverTools.js +39 -0
  110. package/dist/tools/evidencePack.d.ts +39 -0
  111. package/dist/tools/evidencePack.js +168 -0
  112. package/dist/tools/explainTool.d.ts +11 -0
  113. package/dist/tools/explainTool.js +21 -0
  114. package/dist/tools/getTaskSummary.js +2 -1
  115. package/dist/tools/goalSubgoalTask.d.ts +51 -0
  116. package/dist/tools/goalSubgoalTask.js +110 -0
  117. package/dist/tools/healthCheck.d.ts +1 -0
  118. package/dist/tools/healthCheck.js +5 -1
  119. package/dist/tools/invokeDiscoveredTool.d.ts +37 -0
  120. package/dist/tools/invokeDiscoveredTool.js +112 -0
  121. package/dist/tools/listTasks.d.ts +3 -1
  122. package/dist/tools/listTasks.js +14 -1
  123. package/dist/tools/mergeWorktree.d.ts +24 -0
  124. package/dist/tools/mergeWorktree.js +27 -0
  125. package/dist/tools/recommendAgentForTask.d.ts +19 -0
  126. package/dist/tools/recommendAgentForTask.js +56 -0
  127. package/dist/tools/reconcileTasks.d.ts +41 -0
  128. package/dist/tools/reconcileTasks.js +352 -0
  129. package/dist/tools/registry.js +926 -2
  130. package/dist/tools/releaseMode.d.ts +50 -0
  131. package/dist/tools/releaseMode.js +370 -0
  132. package/dist/tools/runDirectVerificationBundle.d.ts +26 -0
  133. package/dist/tools/runDirectVerificationBundle.js +64 -0
  134. package/dist/tools/runTaskLoop.d.ts +57 -0
  135. package/dist/tools/runTaskLoop.js +417 -0
  136. package/dist/tools/runVerification.d.ts +4 -0
  137. package/dist/tools/runVerification.js +4 -0
  138. package/dist/tools/safeStatus.d.ts +31 -1
  139. package/dist/tools/safeStatus.js +43 -1
  140. package/dist/tools/safeViews.d.ts +262 -0
  141. package/dist/tools/safeViews.js +252 -0
  142. package/dist/tools/schemaDriftCheck.d.ts +46 -0
  143. package/dist/tools/schemaDriftCheck.js +80 -0
  144. package/dist/tools/taskLineage.d.ts +91 -0
  145. package/dist/tools/taskLineage.js +175 -0
  146. package/dist/tools/toolCatalog.d.ts +4 -3
  147. package/dist/tools/toolCatalog.js +39 -11
  148. package/dist/tools/toolRegistry.d.ts +61 -0
  149. package/dist/tools/toolRegistry.js +834 -0
  150. package/dist/tools/toolSearch.d.ts +110 -0
  151. package/dist/tools/toolSearch.js +331 -0
  152. package/dist/tools/toolUsageStats.d.ts +41 -0
  153. package/dist/tools/toolUsageStats.js +116 -0
  154. package/dist/tools/waitForTask.js +1 -0
  155. package/dist/version.d.ts +2 -2
  156. package/dist/version.js +2 -2
  157. package/dist/watcherStatus.d.ts +29 -0
  158. package/dist/watcherStatus.js +92 -1
  159. package/docs/chatgpt-usage.md +31 -0
  160. package/docs/control-center/README.md +9 -0
  161. package/package.json +3 -2
  162. package/scripts/checks/control-center-smoke.js +87 -0
  163. package/scripts/checks/control-smoke.js +2 -2
  164. package/scripts/checks/doctor-smoke.js +1 -0
  165. package/scripts/checks/lifecycle-smoke.js +13 -9
  166. package/scripts/checks/mcp-manifest-check.js +65 -6
  167. package/scripts/checks/mcp-smoke.js +60 -9
  168. package/scripts/checks/watcher-supervisor-smoke.js +2 -2
  169. package/src/agents/agentRouter.ts +149 -0
  170. package/src/config.ts +9 -3
  171. package/src/controlCenter.ts +215 -4
  172. package/src/direct/directSessionStore.ts +2 -0
  173. package/src/direct/directVerification.ts +7 -0
  174. package/src/doctor.ts +36 -1
  175. package/src/goal/acceptanceEngine.ts +160 -0
  176. package/src/goal/acceptanceTemplate.ts +121 -0
  177. package/src/goal/goalGraph.ts +225 -0
  178. package/src/goal/goalProgress.ts +301 -0
  179. package/src/goal/goalStatus.ts +234 -0
  180. package/src/goal/goalStore.ts +306 -0
  181. package/src/goal/handoffExport.ts +211 -0
  182. package/src/goal/subgoalSync.ts +82 -0
  183. package/src/goal/worktreeManager.ts +404 -0
  184. package/src/logging.ts +91 -0
  185. package/src/policy/projectPolicy.ts +344 -0
  186. package/src/release/releaseGate.ts +567 -0
  187. package/src/runner/postTaskCleanup.ts +154 -0
  188. package/src/runner/runTask.ts +49 -10
  189. package/src/security/discoveryTokenStore.ts +157 -0
  190. package/src/security/toolInvocationGuard.ts +251 -0
  191. package/src/smoke-test.ts +15 -7
  192. package/src/taskRuntime.ts +17 -0
  193. package/src/test/unit/acceptance-engine.test.ts +261 -0
  194. package/src/test/unit/agent-router.test.ts +342 -0
  195. package/src/test/unit/audit-checks.test.ts +567 -0
  196. package/src/test/unit/diagnose-task.test.ts +544 -0
  197. package/src/test/unit/discovery-token-store.test.ts +181 -0
  198. package/src/test/unit/evidence-pack.test.ts +142 -0
  199. package/src/test/unit/goal-graph.test.ts +347 -0
  200. package/src/test/unit/goal-progress.test.ts +538 -0
  201. package/src/test/unit/goal-status.test.ts +270 -0
  202. package/src/test/unit/goal-store.test.ts +318 -0
  203. package/src/test/unit/goal-subgoal-task.test.ts +72 -0
  204. package/src/test/unit/goal-tools-registry.test.ts +243 -0
  205. package/src/test/unit/handoff-export.test.ts +295 -0
  206. package/src/test/unit/invoke-discovered-tool.test.ts +216 -0
  207. package/src/test/unit/logging.test.ts +177 -5
  208. package/src/test/unit/post-task-cleanup.test.ts +53 -0
  209. package/src/test/unit/project-policy-release-mode.test.ts +156 -0
  210. package/src/test/unit/reconcile-tasks.test.ts +551 -0
  211. package/src/test/unit/release-gate.test.ts +314 -0
  212. package/src/test/unit/run-task-loop.test.ts +425 -0
  213. package/src/test/unit/safe-views.test.ts +184 -0
  214. package/src/test/unit/schema-drift-check.test.ts +260 -0
  215. package/src/test/unit/subgoal-sync.test.ts +236 -0
  216. package/src/test/unit/tool-invocation-guard.test.ts +542 -0
  217. package/src/test/unit/tool-usage-stats.test.ts +384 -0
  218. package/src/test/unit/toolSearch.test.ts +756 -0
  219. package/src/test/unit/worktree-manager.test.ts +247 -0
  220. package/src/tools/auditTask.ts +831 -402
  221. package/src/tools/cancelTask.ts +1 -1
  222. package/src/tools/checkReleaseGate.ts +45 -0
  223. package/src/tools/createTask.ts +64 -6
  224. package/src/tools/diagnoseTask.ts +460 -0
  225. package/src/tools/discardWorktree.ts +42 -0
  226. package/src/tools/discoverTools.ts +51 -0
  227. package/src/tools/evidencePack.ts +205 -0
  228. package/src/tools/explainTool.ts +26 -0
  229. package/src/tools/getTaskSummary.ts +2 -1
  230. package/src/tools/goalSubgoalTask.ts +170 -0
  231. package/src/tools/healthCheck.ts +4 -1
  232. package/src/tools/invokeDiscoveredTool.ts +163 -0
  233. package/src/tools/listTasks.ts +16 -2
  234. package/src/tools/listWorkspace.ts +71 -71
  235. package/src/tools/mergeWorktree.ts +42 -0
  236. package/src/tools/recommendAgentForTask.ts +79 -0
  237. package/src/tools/reconcileTasks.ts +464 -0
  238. package/src/tools/registry.ts +1093 -73
  239. package/src/tools/releaseMode.ts +450 -0
  240. package/src/tools/runDirectVerificationBundle.ts +98 -0
  241. package/src/tools/runTaskLoop.ts +526 -0
  242. package/src/tools/runVerification.ts +8 -0
  243. package/src/tools/safeStatus.ts +73 -2
  244. package/src/tools/safeViews.ts +273 -0
  245. package/src/tools/schemaDriftCheck.ts +120 -0
  246. package/src/tools/taskLineage.ts +300 -0
  247. package/src/tools/toolCatalog.ts +40 -11
  248. package/src/tools/toolRegistry.ts +896 -0
  249. package/src/tools/toolSearch.ts +464 -0
  250. package/src/tools/toolUsageStats.ts +151 -0
  251. package/src/tools/waitForTask.ts +1 -0
  252. package/src/version.ts +2 -2
  253. package/src/watcherStatus.ts +97 -1
  254. package/ui/pages/dashboard.html +143 -2
package/README.en.md CHANGED
@@ -8,10 +8,9 @@
8
8
  [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-339933.svg)](https://nodejs.org/)
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
10
 
11
- Current stable release: **v0.6.4**. See the
12
- [release notes](docs/release-v0.6.4.md),
13
- [migration guide](docs/migration-from-safe-bifrost.md), and
14
- [GitHub Release](https://github.com/jiezeng2004-design/PatchWarden/releases/tag/v0.6.4).
11
+ Current source version: **v1.5.0**. See the
12
+ [CHANGELOG](CHANGELOG.md), [migration guide](docs/migration-from-safe-bifrost.md), and
13
+ [release checklist](docs/release-checklist.md). Verify GitHub Release / npm publication separately before release.
15
14
 
16
15
  PatchWarden is a local-first MCP safety and verification layer for AI coding
17
16
  agents, with workspace confinement, command allowlists, scope-violation
@@ -266,7 +265,7 @@ execution still requires a separate Watcher.
266
265
  New-Item -ItemType Directory .\patchwarden-runtime
267
266
  Set-Location .\patchwarden-runtime
268
267
  npm.cmd init -y
269
- npm.cmd install patchwarden@0.6.4
268
+ npm.cmd install patchwarden@<published-version>
270
269
  Copy-Item .\node_modules\patchwarden\examples\config.example.json .\patchwarden.config.json
271
270
  $env:PATCHWARDEN_CONFIG = (Resolve-Path .\patchwarden.config.json)
272
271
  node .\node_modules\patchwarden\dist\runner\watch.js
@@ -275,10 +274,10 @@ node .\node_modules\patchwarden\dist\runner\watch.js
275
274
  An MCP client can launch:
276
275
 
277
276
  ```text
278
- npx.cmd -y patchwarden@0.6.4
277
+ npx.cmd -y patchwarden@<published-version>
279
278
  ```
280
279
 
281
- Pin the version in important environments instead of using `latest`
280
+ Replace `<published-version>` with a version that exists on npm/GitHub, and pin that version in important environments instead of using `latest`
282
281
  unconditionally.
283
282
 
284
283
  ## Complete configuration guide
@@ -331,7 +330,7 @@ Configuration fields:
331
330
  | `workspaceRoot` | Yes | The only workspace root PatchWarden may access. |
332
331
  | `plansDir` | Yes | Plan directory, normally `.patchwarden/plans`. |
333
332
  | `tasksDir` | Yes | Task and result directory, normally `.patchwarden/tasks`. |
334
- | `toolProfile` | No | `full` or `chatgpt_core`; use `full` for local clients. |
333
+ | `toolProfile` | No | `full`, `chatgpt_core`, `chatgpt_direct`, or `chatgpt_search`; use `full` for local clients and `chatgpt_search` for compact discovery-driven clients. |
335
334
  | `agents` | Yes | Execution-agent allowlist; supports `{repo}` and `{prompt}` placeholders. |
336
335
  | `allowedTestCommands` | Yes | Exact allowlist for independent verification commands. |
337
336
  | `repoAllowedTestCommands` | No | Extra exact commands keyed by workspace-relative repository path; wildcards are unsupported. |
@@ -434,7 +433,7 @@ Pinned npm configuration:
434
433
  ```toml
435
434
  [mcp_servers.patchwarden]
436
435
  command = "npx.cmd"
437
- args = ["-y", "patchwarden@0.6.4"]
436
+ args = ["-y", "patchwarden@<published-version>"]
438
437
 
439
438
  [mcp_servers.patchwarden.env]
440
439
  PATCHWARDEN_CONFIG = "D:\\path\\to\\patchwarden.config.json"
@@ -494,7 +493,7 @@ PatchWarden.cmd start core
494
493
  The launcher:
495
494
 
496
495
  - Builds `dist/index.js` if it is missing.
497
- - Verifies v0.6.4, the fixed 17-tool `chatgpt_core` catalog, and its schema
496
+ - Verifies v1.5.0, the fixed 26-tool `chatgpt_core` catalog, and its schema
498
497
  manifest.
499
498
  - Reads or prompts for the Tunnel ID.
500
499
  - Reads or prompts for the runtime API key.
@@ -742,7 +741,7 @@ Optional token configuration:
742
741
  Set the token in the PowerShell process that starts the server:
743
742
 
744
743
  ```powershell
745
- $env:PATCHWARDEN_OWNER_TOKEN = "use-a-random-local-only-value"
744
+ $env:PATCHWARDEN_OWNER_TOKEN = "<token>"
746
745
  ```
747
746
 
748
747
  Clients can send `Authorization: Bearer ...` or `x-patchwarden-token`. Never
@@ -931,18 +930,52 @@ names.
931
930
 
932
931
  ## MCP tools and profiles
933
932
 
934
- `chatgpt_core` is the fixed 17-tool profile used by the ChatGPT tunnel:
933
+ `chatgpt_core` is the fixed 26-tool profile used by the ChatGPT tunnel:
935
934
 
936
935
  `health_check`, `list_agents`, `list_workspace`,
937
- `read_workspace_file`, `save_plan`, `create_task`,
936
+ `read_workspace_file`, `save_plan`, `create_task`, `run_task_loop`,
937
+ `recommend_agent_for_task`, `get_task_lineage`, `export_task_evidence_pack`,
938
+ `get_project_policy`,
938
939
  `wait_for_task`, `get_task_summary`, `get_diff`, `get_result`,
939
940
  `get_result_json`, `get_test_log`, `get_task_status`, `list_tasks`,
940
- `cancel_task`, `audit_task`, and `safe_status`.
941
+ `cancel_task`, `audit_task`, `safe_status`, `safe_result`, `safe_audit`, `safe_test_summary`, and `safe_diff_summary`.
941
942
 
942
943
  `get_task_summary` keeps the backward-compatible `standard` view by default.
943
944
  ChatGPT should request `view: "compact"` first; terminal `wait_for_task`
944
945
  responses also embed compact acceptance evidence only.
945
946
 
947
+ `run_task_loop` is the v1.2 safe orchestration entrypoint. It only composes
948
+ existing `create_task`, `wait_for_task`, safe summary, and `audit_task`
949
+ behavior; it does not bypass the Watcher, command allowlist, workspace
950
+ confinement, or local confirmation boundaries. `get_task_lineage` reads the
951
+ bounded `.patchwarden/lineages/<lineage_id>/` summary without returning full
952
+ logs or diffs.
953
+
954
+ `get_project_policy` is the v1.3 read-only policy entrypoint. It returns the
955
+ bounded effective `.patchwarden/project-policy.json` policy and release
956
+ readiness summary without expanding command permissions. The v1.3 release mode
957
+ tools, `release_check`, `release_prepare`, `release_verify`, and
958
+ `release_cleanup`, are full-profile only and never perform publish, push, tag,
959
+ or GitHub Release writes. The Control Center dashboard also shows bounded
960
+ lineage, policy, and release status summaries without full logs, diffs, or
961
+ secret-bearing content.
962
+
963
+ v1.4 adds Direct-assisted loop verification. `run_task_loop` can opt into
964
+ `direct_verify=true`; after the guarded task and audit succeed, PatchWarden
965
+ creates a Direct session, runs only allowlisted verification commands, safe
966
+ finalizes, safe audits, and records bounded Direct evidence in lineage. It does
967
+ not call Direct patching tools, publish, push, tag, create releases, restart
968
+ watchers, or return full stdout/stderr/diffs.
969
+
970
+ v1.5 adds worktree-assisted loop isolation, bounded agent routing, and evidence
971
+ pack export. `run_task_loop(isolation_mode="worktree")` creates an isolated git
972
+ worktree for the task and records the worktree id, path, branch, and next action
973
+ in lineage. It does not auto-merge or auto-delete the worktree. `agent="auto"`
974
+ uses `recommend_agent_for_task` to select a configured agent before task
975
+ creation. `export_task_evidence_pack` writes bounded `evidence.json` and
976
+ `EVIDENCE.md` files under `.patchwarden/evidence-packs/<lineage_id>/` without
977
+ stdout/stderr tails, full diffs, verification logs, or sensitive file content.
978
+
946
979
  `full` additionally provides:
947
980
 
948
981
  - `get_plan`
@@ -957,9 +990,9 @@ to `full`.
957
990
 
958
991
  ### ChatGPT Direct mode
959
992
 
960
- Direct mode exposes ten guarded tools so ChatGPT can create an editing
993
+ Direct mode exposes fourteen guarded tools so ChatGPT can create an editing
961
994
  session, read and search source files, apply hash-bound JSON patches, run
962
- exactly allowlisted verification commands, finalize the evidence, and audit
995
+ exactly allowlisted verification commands or a bounded verification bundle, finalize the evidence, and audit
963
996
  the result without a local execution agent.
964
997
 
965
998
  Enable it in the trusted local configuration while keeping the ordinary Core
@@ -981,7 +1014,7 @@ On first use, provide the `tunnel-client.exe` path and a Tunnel ID dedicated
981
1014
  to the Direct Connector. The launcher uses the `patchwarden-direct` profile,
982
1015
  stores runtime state under `%LOCALAPPDATA%\patchwarden\runtime-direct`, skips
983
1016
  the Watcher, and retains the existing DPAPI credential handling. In a fresh
984
- ChatGPT conversation, `health_check` should report `chatgpt_direct`, ten
1017
+ ChatGPT conversation, `health_check` should report `chatgpt_direct`, fourteen
985
1018
  tools, and `direct_profile_enabled=true`.
986
1019
 
987
1020
  ## Security boundaries and local data
@@ -1017,7 +1050,7 @@ Start with a dedicated test workspace and a repository you can recover.
1017
1050
  Upgrade a pinned npm installation:
1018
1051
 
1019
1052
  ```powershell
1020
- npm.cmd install patchwarden@0.6.4
1053
+ npm.cmd install patchwarden@<published-version>
1021
1054
  ```
1022
1055
 
1023
1056
  Upgrade a source checkout:
@@ -1101,8 +1134,9 @@ and release-asset checksums independently.
1101
1134
  - [x] ChatGPT Connector / tunnel
1102
1135
  - [x] Doctor and runtime health checks
1103
1136
  - [x] Tool manifest and schema-drift detection
1104
- - [ ] Worktree isolation
1105
- - [ ] Multi-agent task queue
1137
+ - [x] Release Gate (five-stage pre-release verification)
1138
+ - [x] Worktree isolation
1139
+ - [x] Multi-agent routing
1106
1140
  - [ ] Local dashboard
1107
1141
 
1108
1142
  ## License
package/README.md CHANGED
@@ -8,10 +8,9 @@
8
8
  [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-339933.svg)](https://nodejs.org/)
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
10
 
11
- 当前稳定版本:**v0.6.4**。查看
12
- [发布说明](docs/release-v0.6.4.md)
13
- [迁移指南](docs/migration-from-safe-bifrost.md)
14
- [GitHub Release](https://github.com/jiezeng2004-design/PatchWarden/releases/tag/v0.6.4)。
11
+ 当前源码版本:**v1.5.0**。查看
12
+ [CHANGELOG](CHANGELOG.md)、[迁移指南](docs/migration-from-safe-bifrost.md)
13
+ [发布检查清单](docs/release-checklist.md)。GitHub Release / npm 发布状态需要在发布前单独核对。
15
14
 
16
15
  PatchWarden 是一个面向本地编程 Agent 的安全 MCP 桥接器。上游的
17
16
  ChatGPT、Codex、OpenCode 或其他 MCP 客户端负责规划与验收,
@@ -180,7 +179,7 @@ npm 包适合让 MCP 客户端通过固定版本启动 PatchWarden。为了执
180
179
  New-Item -ItemType Directory .\patchwarden-runtime
181
180
  Set-Location .\patchwarden-runtime
182
181
  npm.cmd init -y
183
- npm.cmd install patchwarden@0.6.4
182
+ npm.cmd install patchwarden@<published-version>
184
183
  Copy-Item .\node_modules\patchwarden\examples\config.example.json .\patchwarden.config.json
185
184
  $env:PATCHWARDEN_CONFIG = (Resolve-Path .\patchwarden.config.json)
186
185
  node .\node_modules\patchwarden\dist\runner\watch.js
@@ -189,10 +188,10 @@ node .\node_modules\patchwarden\dist\runner\watch.js
189
188
  MCP 客户端可以使用:
190
189
 
191
190
  ```text
192
- npx.cmd -y patchwarden@0.6.4
191
+ npx.cmd -y patchwarden@<published-version>
193
192
  ```
194
193
 
195
- 建议固定版本号,不要在重要环境中无条件使用 `latest`。
194
+ `<published-version>` 替换为已经在 npm/GitHub 上确认存在的版本;不要在重要环境中无条件使用 `latest`。
196
195
 
197
196
  ## 完整配置说明
198
197
 
@@ -244,7 +243,7 @@ Copy-Item .\examples\config.example.json .\patchwarden.config.json
244
243
  | `workspaceRoot` | 是 | PatchWarden 唯一允许访问的工作区根目录。 |
245
244
  | `plansDir` | 是 | 计划目录,通常使用 `.patchwarden/plans`。 |
246
245
  | `tasksDir` | 是 | 任务和结果目录,通常使用 `.patchwarden/tasks`。 |
247
- | `toolProfile` | 否 | `full` 或 `chatgpt_core`;本地客户端推荐 `full`。 |
246
+ | `toolProfile` | 否 | `full`、`chatgpt_core`、`chatgpt_direct` 或 `chatgpt_search`;本地客户端推荐 `full`,动态工具发现场景使用 `chatgpt_search`。 |
248
247
  | `agents` | 是 | 可执行 Agent 白名单;支持 `{repo}` 和 `{prompt}` 占位符。 |
249
248
  | `allowedTestCommands` | 是 | 独立验证命令白名单,调用时必须精确匹配。 |
250
249
  | `repoAllowedTestCommands` | 否 | 按工作区相对仓库路径增加精确验证命令;不支持通配符。 |
@@ -342,7 +341,7 @@ npm.cmd run watch
342
341
  ```toml
343
342
  [mcp_servers.patchwarden]
344
343
  command = "npx.cmd"
345
- args = ["-y", "patchwarden@0.6.4"]
344
+ args = ["-y", "patchwarden@<published-version>"]
346
345
 
347
346
  [mcp_servers.patchwarden.env]
348
347
  PATCHWARDEN_CONFIG = "D:\\path\\to\\patchwarden.config.json"
@@ -400,7 +399,7 @@ PatchWarden.cmd start core
400
399
  启动器会:
401
400
 
402
401
  - 检查 `dist/index.js`,缺失时自动构建。
403
- - 校验 `chatgpt_core` 的版本、16 个核心工具和 Schema Manifest。
402
+ - 校验 `chatgpt_core` 的版本、26 个核心工具和 Schema Manifest。
404
403
  - 读取或提示输入 Tunnel ID。
405
404
  - 读取或提示输入运行时 API Key。
406
405
  - 使用 Windows DPAPI 保存凭据到 `%APPDATA%\patchwarden`。
@@ -837,18 +836,45 @@ PatchWarden v0.4.0 不自动读取旧 CLI、旧环境变量、旧 Header、旧
837
836
 
838
837
  ## MCP 工具与 Profile
839
838
 
840
- `chatgpt_core` 是固定的 17 工具 Profile,适合 ChatGPT Tunnel:
839
+ `chatgpt_core` 是固定的 26 工具 Profile,适合 ChatGPT Tunnel:
841
840
 
842
841
  `health_check`、`list_agents`、`list_workspace`、
843
- `read_workspace_file`、`save_plan`、`create_task`、
842
+ `read_workspace_file`、`save_plan`、`create_task`、`run_task_loop`、`recommend_agent_for_task`、
843
+ `get_task_lineage`、`export_task_evidence_pack`、`get_project_policy`、
844
844
  `wait_for_task`、`get_task_summary`、`get_diff`、`get_result`、
845
845
  `get_result_json`、`get_test_log`、`get_task_status`、`list_tasks`、
846
- `cancel_task`、`audit_task`、`safe_status`。
846
+ `cancel_task`、`audit_task`、`safe_status`、`safe_result`、`safe_audit`、`safe_test_summary`、`safe_diff_summary`。
847
847
 
848
848
  `get_task_summary` 默认保留兼容的 `standard` 视图;ChatGPT 应优先使用
849
849
  `view: "compact"`,终态 `wait_for_task` 也只内嵌 compact 验收证据。
850
850
 
851
- `full` 提供完整 30 工具本地开发目录,包含核心工具、管理工具和 Direct
851
+ `run_task_loop` v1.2 的安全编排入口:它只组合现有 `create_task`、`wait_for_task`、safe summary 和
852
+ `audit_task`,不会绕过 Watcher、命令白名单、workspace confinement 或确认边界。`get_task_lineage`
853
+ 读取 `.patchwarden/lineages/<lineage_id>/` 中的有界链路摘要,不返回完整日志或 diff。
854
+
855
+ v1.4 adds Direct-assisted loop verification. `run_task_loop(direct_verify=true)`
856
+ will create a Direct session only after the watcher-driven task and normal audit
857
+ succeed, run allowlisted Direct verification commands, safe-finalize, safe-audit,
858
+ and write bounded Direct evidence into lineage. It does not call Direct patching
859
+ tools, publish, push, tag, create releases, restart live services, or return full
860
+ stdout/stderr/diffs.
861
+
862
+ v1.5 adds worktree-assisted loop isolation, bounded agent routing, and evidence
863
+ pack export. `run_task_loop(isolation_mode="worktree")` creates an isolated git
864
+ worktree for the task and records the worktree id, path, branch, and next action
865
+ in lineage. It does not auto-merge or auto-delete the worktree. `agent="auto"`
866
+ uses `recommend_agent_for_task` to select a configured agent before task
867
+ creation. `export_task_evidence_pack` writes bounded `evidence.json` and
868
+ `EVIDENCE.md` files under `.patchwarden/evidence-packs/<lineage_id>/` without
869
+ stdout/stderr tails, full diffs, verification logs, or sensitive file content.
870
+
871
+ `get_project_policy` 是 v1.3 的只读策略入口,返回 `.patchwarden/project-policy.json`
872
+ 的有界 effective policy 与 release readiness,不会扩大命令白名单。v1.3 的
873
+ `release_check`、`release_prepare`、`release_verify`、`release_cleanup` 仅在 `full`
874
+ Profile 中可见,不执行 publish、push、tag 或 GitHub Release 写操作。Control Center
875
+ Dashboard 会展示 lineage、policy 和 release status 的有界摘要,不返回完整日志、diff 或密钥内容。
876
+
877
+ `full` 提供完整 64 工具本地开发目录,包含核心工具、管理工具和 Direct
852
878
  工具。除 `chatgpt_core` 外,常用额外管理工具包括:
853
879
 
854
880
  - `get_plan`
@@ -858,15 +884,15 @@ PatchWarden v0.4.0 不自动读取旧 CLI、旧环境变量、旧 Header、旧
858
884
  - `get_task_stdout_tail`
859
885
  - `get_task_log_tail`
860
886
 
861
- `chatgpt_direct` 是 v0.6.0 新增的 Direct 直接开发 Profile,v0.6.4 包含 10 个工具:
887
+ `chatgpt_direct` 是 v0.6.0 新增的 Direct 直接开发 Profile,v1.4 包含 14 个工具:
862
888
 
863
889
  `health_check`、`list_workspace`、`create_direct_session`、
864
890
  `search_workspace`、`read_workspace_file`、`apply_patch`、
865
- `run_verification`、`finalize_direct_session`、`audit_session`、`sync_file`。
891
+ `run_verification`、`run_direct_verification_bundle`、`finalize_direct_session`、`audit_session`、`safe_direct_summary`、`safe_finalize_direct_session`、`safe_audit_direct_session`、`sync_file`。
866
892
 
867
893
  `chatgpt_direct` 默认关闭,需要通过 `enableDirectProfile: true` 或
868
894
  `PATCHWARDEN_TOOL_PROFILE=chatgpt_direct` 显式启用。`chatgpt_core` 保持
869
- 17 工具不变。
895
+ 26 工具清单。
870
896
 
871
897
  Tunnel 包装脚本会强制使用 `chatgpt_core`;普通本地开发默认使用 `full`。
872
898
 
@@ -921,7 +947,7 @@ Tunnel ID。启动器使用 `patchwarden-direct` Profile、独立的
921
947
  Tunnel API Key 仍通过现有 Windows DPAPI 缓存处理,不会写入仓库。
922
948
 
923
949
  连接 ChatGPT 后新建对话并先调用 `health_check`。预期
924
- `tool_profile=chatgpt_direct`、`tool_count=10`、
950
+ `tool_profile=chatgpt_direct`、`tool_count=14`、
925
951
  `direct_profile_enabled=true`。已有对话可能缓存旧工具清单,需要重新连接
926
952
  Connector 后再新建对话。
927
953
 
@@ -984,7 +1010,7 @@ PatchWarden 能降低误操作风险,但不能替代人工审查。第一次
984
1010
  升级 npm 固定版本:
985
1011
 
986
1012
  ```powershell
987
- npm.cmd install patchwarden@0.6.4
1013
+ npm.cmd install patchwarden@<published-version>
988
1014
  ```
989
1015
 
990
1016
  源码升级:
@@ -1067,8 +1093,9 @@ Release 和发布资产校验值。
1067
1093
  - [x] ChatGPT Connector / Tunnel
1068
1094
  - [x] Doctor 与运行时健康检查
1069
1095
  - [x] Tool Manifest 与 Schema 漂移检测
1070
- - [ ] Worktree 隔离
1071
- - [ ] Agent 任务队列
1096
+ - [x] Release Gate(发布前五阶段校验)
1097
+ - [x] Worktree 隔离
1098
+ - [x] 多 Agent 路由
1072
1099
  - [ ] 本地 Dashboard
1073
1100
 
1074
1101
  ## License
@@ -0,0 +1,40 @@
1
+ export interface AgentRouteInput {
2
+ goal?: string;
3
+ scope?: string[];
4
+ inline_plan?: string;
5
+ template?: string;
6
+ configuredAgents: string[];
7
+ }
8
+ export interface AgentRouteResult {
9
+ recommended_agent: string;
10
+ reason: string;
11
+ fallback: boolean;
12
+ }
13
+ export declare const AGENT_ROUTING_RULES: {
14
+ /** 大规模代码修改 → opencode */
15
+ readonly largeScope: {
16
+ readonly agent: "opencode";
17
+ readonly threshold: 10;
18
+ };
19
+ /** 单文件修改 → patchwarden-direct */
20
+ readonly singleFile: {
21
+ readonly agent: "patchwarden-direct";
22
+ };
23
+ /** 验收审计 → patchwarden-audit */
24
+ readonly audit: {
25
+ readonly agent: "patchwarden-audit";
26
+ readonly keywords: readonly ["审计", "audit", "验收", "verify"];
27
+ };
28
+ /** 复杂推理和重构 → codex */
29
+ readonly refactor: {
30
+ readonly agent: "codex";
31
+ readonly keywords: readonly ["重构", "refactor", "跨模块", "redesign"];
32
+ };
33
+ /** 文档整理 → claude(fallback 到 opencode) */
34
+ readonly documentation: {
35
+ readonly agent: "claude";
36
+ readonly fallbackAgent: "opencode";
37
+ readonly keywords: readonly ["文档", "readme", "changelog", "doc"];
38
+ };
39
+ };
40
+ export declare function routeAgent(input: AgentRouteInput): AgentRouteResult;
@@ -0,0 +1,95 @@
1
+ import { PatchWardenError } from "../errors.js";
2
+ // ── Routing rules (roadmap 9.3) ───────────────────────────────────
3
+ export const AGENT_ROUTING_RULES = {
4
+ /** 大规模代码修改 → opencode */
5
+ largeScope: {
6
+ agent: "opencode",
7
+ threshold: 10, // scope.length > threshold
8
+ },
9
+ /** 单文件修改 → patchwarden-direct */
10
+ singleFile: {
11
+ agent: "patchwarden-direct",
12
+ },
13
+ /** 验收审计 → patchwarden-audit */
14
+ audit: {
15
+ agent: "patchwarden-audit",
16
+ keywords: ["审计", "audit", "验收", "verify"],
17
+ },
18
+ /** 复杂推理和重构 → codex */
19
+ refactor: {
20
+ agent: "codex",
21
+ keywords: ["重构", "refactor", "跨模块", "redesign"],
22
+ },
23
+ /** 文档整理 → claude(fallback 到 opencode) */
24
+ documentation: {
25
+ agent: "claude",
26
+ fallbackAgent: "opencode",
27
+ keywords: ["文档", "readme", "changelog", "doc"],
28
+ },
29
+ };
30
+ // ── Helpers ───────────────────────────────────────────────────────
31
+ function containsAny(text, keywords) {
32
+ return keywords.some((keyword) => text.includes(keyword));
33
+ }
34
+ function resolveRoute(preferred, reason, configuredAgents) {
35
+ if (configuredAgents.includes(preferred)) {
36
+ return { recommended_agent: preferred, reason, fallback: false };
37
+ }
38
+ const fallback = configuredAgents[0];
39
+ return {
40
+ recommended_agent: fallback,
41
+ reason: `fallback: ${preferred} not configured, using ${fallback}`,
42
+ fallback: true,
43
+ };
44
+ }
45
+ // ── Route agent ───────────────────────────────────────────────────
46
+ export function routeAgent(input) {
47
+ if (!input.configuredAgents || input.configuredAgents.length === 0) {
48
+ throw new PatchWardenError("no_agent_configured", "No agent is configured for routing.", "Configure at least one agent in patchwarden.config.json under the agents field.");
49
+ }
50
+ const scopeCount = input.scope?.length ?? 0;
51
+ const text = `${input.goal || ""} ${input.inline_plan || ""}`.toLowerCase();
52
+ // Rule 1: 大规模代码修改 → opencode (scope files > 10)
53
+ if (scopeCount > AGENT_ROUTING_RULES.largeScope.threshold) {
54
+ return resolveRoute(AGENT_ROUTING_RULES.largeScope.agent, `large scope (${scopeCount} files)`, input.configuredAgents);
55
+ }
56
+ // Rule 2: 单文件修改 → patchwarden-direct (scope files === 1)
57
+ if (scopeCount === 1) {
58
+ return resolveRoute(AGENT_ROUTING_RULES.singleFile.agent, "single file scope", input.configuredAgents);
59
+ }
60
+ // Rule 3: 验收审计 → patchwarden-audit
61
+ if (containsAny(text, AGENT_ROUTING_RULES.audit.keywords)) {
62
+ return resolveRoute(AGENT_ROUTING_RULES.audit.agent, "audit keywords", input.configuredAgents);
63
+ }
64
+ // Rule 4: 复杂推理和重构 → codex
65
+ if (containsAny(text, AGENT_ROUTING_RULES.refactor.keywords)) {
66
+ return resolveRoute(AGENT_ROUTING_RULES.refactor.agent, "refactor keywords", input.configuredAgents);
67
+ }
68
+ // Rule 5: 文档整理 → claude(fallback 到 opencode)
69
+ if (containsAny(text, AGENT_ROUTING_RULES.documentation.keywords)) {
70
+ const preferred = AGENT_ROUTING_RULES.documentation.agent;
71
+ const fallbackAgent = AGENT_ROUTING_RULES.documentation.fallbackAgent;
72
+ if (input.configuredAgents.includes(preferred)) {
73
+ return { recommended_agent: preferred, reason: "documentation keywords", fallback: false };
74
+ }
75
+ if (input.configuredAgents.includes(fallbackAgent)) {
76
+ return {
77
+ recommended_agent: fallbackAgent,
78
+ reason: `fallback: ${preferred} not configured, using ${fallbackAgent}`,
79
+ fallback: true,
80
+ };
81
+ }
82
+ const firstAgent = input.configuredAgents[0];
83
+ return {
84
+ recommended_agent: firstAgent,
85
+ reason: `fallback: ${preferred} not configured, using ${firstAgent}`,
86
+ fallback: true,
87
+ };
88
+ }
89
+ // Rule 6: 无匹配 → fallback 到 configuredAgents[0]
90
+ return {
91
+ recommended_agent: input.configuredAgents[0],
92
+ reason: `no specific routing rule matched, using default agent ${input.configuredAgents[0]}`,
93
+ fallback: true,
94
+ };
95
+ }
package/dist/config.d.ts CHANGED
@@ -15,7 +15,7 @@ export interface PatchWardenConfig {
15
15
  defaultTaskTimeoutSeconds: number;
16
16
  maxTaskTimeoutSeconds: number;
17
17
  watcherStaleSeconds: number;
18
- toolProfile?: "full" | "chatgpt_core" | "chatgpt_direct";
18
+ toolProfile?: "full" | "chatgpt_core" | "chatgpt_direct" | "chatgpt_search";
19
19
  repoAliases?: Record<string, string>;
20
20
  enableAgentAssessment?: boolean;
21
21
  agentAssessmentTimeoutSeconds?: number;
package/dist/config.js CHANGED
@@ -175,8 +175,12 @@ function normalizeConfig(config) {
175
175
  if (!Number.isInteger(config.watcherStaleSeconds) || config.watcherStaleSeconds < 5 || config.watcherStaleSeconds > 3600) {
176
176
  throw new Error("watcherStaleSeconds must be an integer from 5 to 3600");
177
177
  }
178
- if (config.toolProfile !== undefined && config.toolProfile !== "full" && config.toolProfile !== "chatgpt_core" && config.toolProfile !== "chatgpt_direct") {
179
- throw new Error('toolProfile must be "full", "chatgpt_core", or "chatgpt_direct"');
178
+ if (config.toolProfile !== undefined &&
179
+ config.toolProfile !== "full" &&
180
+ config.toolProfile !== "chatgpt_core" &&
181
+ config.toolProfile !== "chatgpt_direct" &&
182
+ config.toolProfile !== "chatgpt_search") {
183
+ throw new Error('toolProfile must be "full", "chatgpt_core", "chatgpt_direct", or "chatgpt_search"');
180
184
  }
181
185
  if (config.enableAgentAssessment !== undefined && typeof config.enableAgentAssessment !== "boolean") {
182
186
  throw new Error("enableAgentAssessment must be a boolean");