patchwarden 1.5.0 → 1.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 (597) hide show
  1. package/PatchWarden.cmd +32 -2
  2. package/README.en.md +194 -26
  3. package/README.md +160 -22
  4. package/dist/assessments/agentAssessor.d.ts +1 -1
  5. package/dist/assessments/agentAssessor.js +24 -15
  6. package/dist/assessments/assessmentStore.d.ts +1 -1
  7. package/dist/assessments/assessmentStore.js +44 -36
  8. package/dist/assessments/confirmCli.js +5 -4
  9. package/dist/config.d.ts +22 -0
  10. package/dist/config.js +98 -11
  11. package/dist/control/fileManager.d.ts +2 -0
  12. package/dist/control/fileManager.js +39 -0
  13. package/dist/control/middleware/auth.d.ts +16 -0
  14. package/dist/control/middleware/auth.js +17 -0
  15. package/dist/control/middleware/static.d.ts +3 -0
  16. package/dist/control/middleware/static.js +78 -0
  17. package/dist/control/routeTable.d.ts +24 -0
  18. package/dist/control/routeTable.js +263 -0
  19. package/dist/control/routes/audit.d.ts +15 -0
  20. package/dist/control/routes/audit.js +287 -0
  21. package/dist/control/routes/evidence.d.ts +4 -0
  22. package/dist/control/routes/evidence.js +96 -0
  23. package/dist/control/routes/lineage.d.ts +3 -0
  24. package/dist/control/routes/lineage.js +71 -0
  25. package/dist/control/routes/policy.d.ts +3 -0
  26. package/dist/control/routes/policy.js +81 -0
  27. package/dist/control/routes/process.d.ts +12 -0
  28. package/dist/control/routes/process.js +487 -0
  29. package/dist/control/routes/sessions.d.ts +30 -0
  30. package/dist/control/routes/sessions.js +287 -0
  31. package/dist/control/routes/status.d.ts +51 -0
  32. package/dist/control/routes/status.js +307 -0
  33. package/dist/control/routes/taskActions.d.ts +21 -0
  34. package/dist/control/routes/taskActions.js +197 -0
  35. package/dist/control/routes/tasks.d.ts +24 -0
  36. package/dist/control/routes/tasks.js +309 -0
  37. package/dist/control/routes/workspace.d.ts +15 -0
  38. package/dist/control/routes/workspace.js +220 -0
  39. package/dist/control/runtime.d.ts +92 -0
  40. package/dist/control/runtime.js +425 -0
  41. package/dist/control/server.d.ts +13 -0
  42. package/dist/control/server.js +150 -0
  43. package/dist/control/shared.d.ts +59 -0
  44. package/dist/control/shared.js +341 -0
  45. package/dist/controlCenter.d.ts +6 -0
  46. package/dist/controlCenter.js +7 -2197
  47. package/dist/direct/directAudit.js +234 -225
  48. package/dist/direct/directGuards.d.ts +2 -1
  49. package/dist/direct/directGuards.js +72 -37
  50. package/dist/direct/directPatch.d.ts +6 -1
  51. package/dist/direct/directPatch.js +55 -8
  52. package/dist/direct/directSessionStore.d.ts +16 -6
  53. package/dist/direct/directSessionStore.js +127 -35
  54. package/dist/direct/directVerification.js +8 -16
  55. package/dist/doctor.d.ts +18 -1
  56. package/dist/doctor.js +614 -373
  57. package/dist/goal/acceptanceEngine.d.ts +1 -1
  58. package/dist/goal/goalProgress.js +75 -69
  59. package/dist/goal/goalReport.d.ts +54 -0
  60. package/dist/goal/goalReport.js +197 -0
  61. package/dist/goal/goalStatus.d.ts +8 -0
  62. package/dist/goal/goalStatus.js +10 -3
  63. package/dist/goal/goalStore.d.ts +9 -2
  64. package/dist/goal/goalStore.js +152 -45
  65. package/dist/goal/handoffExport.js +6 -6
  66. package/dist/goal/specKitImport.d.ts +63 -0
  67. package/dist/goal/specKitImport.js +221 -0
  68. package/dist/goal/subgoalSync.js +13 -10
  69. package/dist/goal/worktreeManager.d.ts +2 -0
  70. package/dist/goal/worktreeManager.js +209 -136
  71. package/dist/httpServer.js +126 -44
  72. package/dist/index.js +7 -4
  73. package/dist/logging.d.ts +7 -1
  74. package/dist/logging.js +13 -3
  75. package/dist/policy/projectPolicy.js +5 -2
  76. package/dist/release/releaseGate.d.ts +1 -1
  77. package/dist/release/releaseGate.js +78 -25
  78. package/dist/runner/agentInvocation.d.ts +14 -0
  79. package/dist/runner/agentInvocation.js +96 -4
  80. package/dist/runner/changeCapture.d.ts +14 -6
  81. package/dist/runner/changeCapture.js +287 -81
  82. package/dist/runner/cli.js +7 -6
  83. package/dist/runner/postTaskCleanup.js +60 -7
  84. package/dist/runner/processSecurity.d.ts +56 -0
  85. package/dist/runner/processSecurity.js +373 -0
  86. package/dist/runner/runTask.d.ts +1 -1
  87. package/dist/runner/runTask.js +339 -287
  88. package/dist/runner/simpleProcess.d.ts +3 -0
  89. package/dist/runner/simpleProcess.js +52 -38
  90. package/dist/{taskProgress.d.ts → runner/taskProgress.d.ts} +1 -1
  91. package/dist/{taskProgress.js → runner/taskProgress.js} +2 -2
  92. package/dist/{taskRuntime.d.ts → runner/taskRuntime.d.ts} +1 -1
  93. package/dist/{taskRuntime.js → runner/taskRuntime.js} +3 -2
  94. package/dist/runner/taskStatusStore.d.ts +11 -0
  95. package/dist/runner/taskStatusStore.js +24 -0
  96. package/dist/runner/watch.d.ts +14 -1
  97. package/dist/runner/watch.js +265 -54
  98. package/dist/security/contentRedaction.d.ts +6 -0
  99. package/dist/security/contentRedaction.js +24 -2
  100. package/dist/security/discoveryTokenStore.d.ts +3 -2
  101. package/dist/security/discoveryTokenStore.js +17 -2
  102. package/dist/security/loopbackHost.d.ts +2 -0
  103. package/dist/security/loopbackHost.js +16 -0
  104. package/dist/security/pathGuard.js +32 -17
  105. package/dist/security/planGuard.js +2 -1
  106. package/dist/security/runtimeGuard.js +9 -6
  107. package/dist/security/secretComparison.d.ts +3 -0
  108. package/dist/security/secretComparison.js +11 -0
  109. package/dist/security/sensitiveGuard.d.ts +5 -0
  110. package/dist/security/sensitiveGuard.js +27 -8
  111. package/dist/security/toolInvocationGuard.d.ts +2 -2
  112. package/dist/security/toolInvocationGuard.js +1 -1
  113. package/dist/security/workspaceRootGuard.d.ts +8 -0
  114. package/dist/security/workspaceRootGuard.js +47 -0
  115. package/dist/smoke-test.js +280 -273
  116. package/dist/tools/catalog/index.d.ts +4 -0
  117. package/dist/tools/catalog/index.js +4 -0
  118. package/dist/tools/{toolCatalog.js → catalog/toolCatalog.js} +3 -12
  119. package/dist/tools/{toolRegistry.d.ts → catalog/toolRegistry.d.ts} +3 -3
  120. package/dist/tools/{toolRegistry.js → catalog/toolRegistry.js} +28 -15
  121. package/dist/tools/definitions/toolDefs.d.ts +18 -0
  122. package/dist/tools/definitions/toolDefs.js +1177 -0
  123. package/dist/tools/{auditSession.d.ts → diagnostics/auditSession.d.ts} +1 -1
  124. package/dist/tools/{auditSession.js → diagnostics/auditSession.js} +2 -2
  125. package/dist/tools/{auditTask.d.ts → diagnostics/auditTask.d.ts} +8 -63
  126. package/dist/tools/{auditTask.js → diagnostics/auditTask.js} +111 -37
  127. package/dist/tools/{healthCheck.d.ts → diagnostics/healthCheck.d.ts} +6 -6
  128. package/dist/tools/{healthCheck.js → diagnostics/healthCheck.js} +10 -10
  129. package/dist/tools/diagnostics/index.d.ts +6 -0
  130. package/dist/tools/diagnostics/index.js +6 -0
  131. package/dist/tools/{safeStatus.d.ts → diagnostics/safeStatus.d.ts} +3 -3
  132. package/dist/tools/{safeStatus.js → diagnostics/safeStatus.js} +6 -6
  133. package/dist/tools/{safeViews.d.ts → diagnostics/safeViews.d.ts} +14 -10
  134. package/dist/tools/{safeViews.js → diagnostics/safeViews.js} +25 -15
  135. package/dist/tools/{schemaDriftCheck.d.ts → diagnostics/schemaDriftCheck.d.ts} +1 -1
  136. package/dist/tools/{schemaDriftCheck.js → diagnostics/schemaDriftCheck.js} +2 -2
  137. package/dist/tools/{createDirectSession.d.ts → direct/createDirectSession.d.ts} +1 -1
  138. package/dist/tools/{createDirectSession.js → direct/createDirectSession.js} +8 -8
  139. package/dist/tools/{finalizeDirectSession.d.ts → direct/finalizeDirectSession.d.ts} +2 -2
  140. package/dist/tools/direct/finalizeDirectSession.js +86 -0
  141. package/dist/tools/direct/index.d.ts +3 -0
  142. package/dist/tools/direct/index.js +3 -0
  143. package/dist/tools/{runDirectVerificationBundle.js → direct/runDirectVerificationBundle.js} +2 -2
  144. package/dist/tools/{discoverTools.d.ts → discovery/discoverTools.d.ts} +2 -2
  145. package/dist/tools/{discoverTools.js → discovery/discoverTools.js} +5 -5
  146. package/dist/tools/{explainTool.d.ts → discovery/explainTool.d.ts} +2 -2
  147. package/dist/tools/{explainTool.js → discovery/explainTool.js} +2 -2
  148. package/dist/tools/discovery/index.d.ts +3 -0
  149. package/dist/tools/discovery/index.js +3 -0
  150. package/dist/tools/{invokeDiscoveredTool.d.ts → discovery/invokeDiscoveredTool.d.ts} +2 -2
  151. package/dist/tools/{invokeDiscoveredTool.js → discovery/invokeDiscoveredTool.js} +5 -5
  152. package/dist/tools/dispatch/coreDispatch.d.ts +9 -0
  153. package/dist/tools/dispatch/coreDispatch.js +283 -0
  154. package/dist/tools/dispatch/diagnosticDispatch.d.ts +12 -0
  155. package/dist/tools/dispatch/diagnosticDispatch.js +80 -0
  156. package/dist/tools/dispatch/directDispatch.d.ts +8 -0
  157. package/dist/tools/dispatch/directDispatch.js +116 -0
  158. package/dist/tools/dispatch/goalDispatch.d.ts +8 -0
  159. package/dist/tools/dispatch/goalDispatch.js +92 -0
  160. package/dist/tools/dispatch/releaseDispatch.d.ts +8 -0
  161. package/dist/tools/dispatch/releaseDispatch.js +46 -0
  162. package/dist/tools/dispatch/types.d.ts +23 -0
  163. package/dist/tools/dispatch/types.js +15 -0
  164. package/dist/tools/dispatch/validation.d.ts +7 -0
  165. package/dist/tools/dispatch/validation.js +71 -0
  166. package/dist/tools/{getPlan.js → goals/getPlan.js} +4 -4
  167. package/dist/tools/{goalSubgoalTask.d.ts → goals/goalSubgoalTask.d.ts} +2 -2
  168. package/dist/tools/goals/goalSubgoalTask.js +118 -0
  169. package/dist/tools/goals/index.d.ts +3 -0
  170. package/dist/tools/goals/index.js +3 -0
  171. package/dist/tools/{savePlan.js → goals/savePlan.js} +28 -8
  172. package/dist/tools/registry.d.ts +10 -14
  173. package/dist/tools/registry.js +47 -1651
  174. package/dist/tools/{checkReleaseGate.d.ts → release/checkReleaseGate.d.ts} +1 -1
  175. package/dist/tools/{checkReleaseGate.js → release/checkReleaseGate.js} +3 -3
  176. package/dist/tools/release/index.d.ts +2 -0
  177. package/dist/tools/release/index.js +2 -0
  178. package/dist/tools/{releaseMode.d.ts → release/releaseMode.d.ts} +2 -2
  179. package/dist/tools/{releaseMode.js → release/releaseMode.js} +46 -26
  180. package/dist/tools/tasks/cancelTask.d.ts +11 -0
  181. package/dist/tools/tasks/cancelTask.js +85 -0
  182. package/dist/tools/{createTask.d.ts → tasks/createTask.d.ts} +12 -4
  183. package/dist/tools/{createTask.js → tasks/createTask.js} +46 -31
  184. package/dist/tools/{diagnoseTask.d.ts → tasks/diagnoseTask.d.ts} +1 -1
  185. package/dist/tools/{diagnoseTask.js → tasks/diagnoseTask.js} +8 -8
  186. package/dist/tools/{evidencePack.d.ts → tasks/evidencePack.d.ts} +6 -0
  187. package/dist/tools/tasks/evidencePack.js +387 -0
  188. package/dist/tools/{getTaskFile.js → tasks/getTaskFile.js} +4 -4
  189. package/dist/tools/{getTaskStatus.d.ts → tasks/getTaskStatus.d.ts} +6 -1
  190. package/dist/tools/{getTaskStatus.js → tasks/getTaskStatus.js} +5 -5
  191. package/dist/tools/{getTaskStdoutTail.js → tasks/getTaskStdoutTail.js} +13 -11
  192. package/dist/tools/{getTaskSummary.js → tasks/getTaskSummary.js} +33 -26
  193. package/dist/tools/tasks/index.d.ts +18 -0
  194. package/dist/tools/tasks/index.js +18 -0
  195. package/dist/tools/tasks/killTask.d.ts +1 -0
  196. package/dist/tools/{listTasks.d.ts → tasks/listTasks.d.ts} +1 -1
  197. package/dist/tools/{listTasks.js → tasks/listTasks.js} +3 -3
  198. package/dist/tools/{reconcileTasks.d.ts → tasks/reconcileTasks.d.ts} +1 -1
  199. package/dist/tools/{reconcileTasks.js → tasks/reconcileTasks.js} +64 -66
  200. package/dist/tools/{retryTask.d.ts → tasks/retryTask.d.ts} +2 -2
  201. package/dist/tools/tasks/retryTask.js +60 -0
  202. package/dist/tools/{runTaskLoop.d.ts → tasks/runTaskLoop.d.ts} +6 -6
  203. package/dist/tools/{runTaskLoop.js → tasks/runTaskLoop.js} +59 -31
  204. package/dist/tools/tasks/runVerification.js +38 -0
  205. package/dist/tools/{taskLineage.js → tasks/taskLineage.js} +8 -7
  206. package/dist/tools/{taskOutputs.js → tasks/taskOutputs.js} +17 -16
  207. package/dist/tools/{androidDoctor.js → workspace/androidDoctor.js} +16 -10
  208. package/dist/tools/{applyPatch.d.ts → workspace/applyPatch.d.ts} +1 -1
  209. package/dist/tools/workspace/applyPatch.js +53 -0
  210. package/dist/tools/{discardWorktree.js → workspace/discardWorktree.js} +3 -3
  211. package/dist/tools/workspace/index.d.ts +10 -0
  212. package/dist/tools/workspace/index.js +10 -0
  213. package/dist/tools/{listAgents.d.ts → workspace/listAgents.d.ts} +5 -0
  214. package/dist/tools/{listAgents.js → workspace/listAgents.js} +8 -4
  215. package/dist/tools/{listWorkspace.js → workspace/listWorkspace.js} +3 -3
  216. package/dist/tools/{mergeWorktree.js → workspace/mergeWorktree.js} +3 -3
  217. package/dist/tools/{readWorkspaceFile.js → workspace/readWorkspaceFile.js} +8 -8
  218. package/dist/tools/{recommendAgentForTask.js → workspace/recommendAgentForTask.js} +3 -3
  219. package/dist/tools/{searchWorkspace.js → workspace/searchWorkspace.js} +5 -5
  220. package/dist/tools/{syncFile.d.ts → workspace/syncFile.d.ts} +1 -1
  221. package/dist/tools/workspace/syncFile.js +134 -0
  222. package/dist/utils/atomicFile.d.ts +7 -0
  223. package/dist/utils/atomicFile.js +48 -0
  224. package/dist/utils/boundedFile.d.ts +8 -0
  225. package/dist/utils/boundedFile.js +93 -0
  226. package/dist/utils/lockedJsonFile.d.ts +15 -0
  227. package/dist/utils/lockedJsonFile.js +224 -0
  228. package/dist/utils/platform.d.ts +11 -0
  229. package/dist/utils/platform.js +26 -0
  230. package/dist/utils/stableJson.d.ts +2 -0
  231. package/dist/utils/stableJson.js +12 -0
  232. package/dist/version.d.ts +3 -2
  233. package/dist/version.js +3 -2
  234. package/dist/watcherStatus.d.ts +2 -2
  235. package/dist/watcherStatus.js +18 -0
  236. package/docs/CODE_WIKI.md +1648 -0
  237. package/docs/agentseal-integration.md +150 -0
  238. package/docs/architecture.md +23 -0
  239. package/docs/assets/patchwarden-desktop-onboarding.png +0 -0
  240. package/docs/assets/patchwarden-oss-demo.gif +0 -0
  241. package/docs/control-center/README.md +4 -4
  242. package/docs/dashboard-overview.md +86 -0
  243. package/docs/demo.md +8 -0
  244. package/docs/desktop-app.md +175 -0
  245. package/docs/direct-session-workflow.md +98 -0
  246. package/docs/evidence-pack-schema.md +215 -0
  247. package/docs/lineage-evidence-pack-workflow.md +127 -0
  248. package/docs/mcp-inspector-testing.md +200 -0
  249. package/docs/open-source-application.md +168 -0
  250. package/docs/opencode-worker.md +151 -0
  251. package/docs/openhands-worker.md +181 -0
  252. package/docs/release-checklist.md +1 -1
  253. package/docs/release-evidence.md +82 -0
  254. package/docs/spec-kit-integration.md +131 -0
  255. package/docs/task-safe-review-workflow.md +98 -0
  256. package/docs/threat-model.md +97 -0
  257. package/docs/user-feedback.md +40 -0
  258. package/docs/why-patchwarden.md +110 -0
  259. package/examples/config.example.json +4 -2
  260. package/package.json +28 -11
  261. package/scripts/README.md +15 -6
  262. package/scripts/build.js +11 -0
  263. package/scripts/checks/brand-check.js +3 -0
  264. package/scripts/checks/build-output-check.js +37 -0
  265. package/scripts/checks/control-center-smoke.js +447 -6
  266. package/scripts/checks/control-smoke.js +19 -8
  267. package/scripts/checks/http-mcp-smoke.js +82 -4
  268. package/scripts/checks/lifecycle-smoke.js +39 -33
  269. package/scripts/checks/mcp-manifest-check.js +1 -1
  270. package/scripts/checks/mcp-smoke.js +30 -4
  271. package/scripts/checks/package-manifest-check.js +20 -7
  272. package/scripts/checks/unit-tests.js +3 -5
  273. package/scripts/checks/watcher-supervisor-smoke.js +9 -0
  274. package/scripts/control/get-patchwarden-health.ps1 +1 -1
  275. package/scripts/control/manage-patchwarden.ps1 +69 -4
  276. package/scripts/control/provision-patchwarden-tunnel.ps1 +127 -0
  277. package/scripts/control/run-background-supervisor.ps1 +41 -0
  278. package/scripts/control/start-patchwarden-tunnel.ps1 +126 -32
  279. package/scripts/generate-demo-gif.py +320 -0
  280. package/{PatchWarden-Control-Tray.cmd → scripts/launchers/PatchWarden-Control-Tray.cmd} +3 -3
  281. package/scripts/launchers/PatchWarden-Control.cmd +6 -0
  282. package/{PatchWarden-Desktop.cmd → scripts/launchers/PatchWarden-Desktop.cmd} +2 -2
  283. package/scripts/launchers/Restart-PatchWarden-Control.cmd +6 -0
  284. package/{Stop-PatchWarden.cmd → scripts/launchers/Stop-PatchWarden.cmd} +2 -2
  285. package/scripts/lib/clean-generated-output.js +11 -0
  286. package/scripts/lib/file-discovery.js +12 -0
  287. package/scripts/release/desktop-preflight.js +211 -0
  288. package/scripts/release/pack-clean.js +59 -14
  289. package/src/assessments/agentAssessor.ts +29 -15
  290. package/src/assessments/assessmentStore.ts +55 -43
  291. package/src/assessments/confirmCli.ts +5 -4
  292. package/src/config.ts +105 -11
  293. package/src/control/fileManager.ts +40 -0
  294. package/src/control/middleware/auth.ts +35 -0
  295. package/src/control/middleware/static.ts +84 -0
  296. package/src/control/routeTable.ts +301 -0
  297. package/src/control/routes/audit.ts +329 -0
  298. package/src/control/routes/evidence.ts +107 -0
  299. package/src/control/routes/lineage.ts +92 -0
  300. package/src/control/routes/policy.ts +81 -0
  301. package/src/control/routes/process.ts +505 -0
  302. package/src/control/routes/sessions.ts +314 -0
  303. package/src/control/routes/status.ts +405 -0
  304. package/src/control/routes/taskActions.ts +214 -0
  305. package/src/control/routes/tasks.ts +331 -0
  306. package/src/control/routes/workspace.ts +234 -0
  307. package/src/control/runtime.ts +508 -0
  308. package/src/control/server.ts +165 -0
  309. package/src/control/shared.ts +360 -0
  310. package/src/controlCenter.ts +7 -2347
  311. package/src/direct/directAudit.ts +17 -9
  312. package/src/direct/directGuards.ts +100 -51
  313. package/src/direct/directPatch.ts +95 -8
  314. package/src/direct/directSessionStore.ts +211 -55
  315. package/src/direct/directVerification.ts +9 -23
  316. package/src/doctor.ts +766 -492
  317. package/src/goal/acceptanceEngine.ts +1 -1
  318. package/src/goal/goalProgress.ts +17 -13
  319. package/src/goal/goalReport.ts +263 -0
  320. package/src/goal/goalStatus.ts +25 -3
  321. package/src/goal/goalStore.ts +241 -54
  322. package/src/goal/handoffExport.ts +6 -6
  323. package/src/goal/specKitImport.ts +355 -0
  324. package/src/goal/subgoalSync.ts +15 -10
  325. package/src/goal/worktreeManager.ts +139 -22
  326. package/src/httpServer.ts +130 -44
  327. package/src/index.ts +7 -4
  328. package/src/logging.ts +20 -4
  329. package/src/policy/projectPolicy.ts +5 -2
  330. package/src/release/releaseGate.ts +74 -27
  331. package/src/runner/agentInvocation.ts +126 -4
  332. package/src/runner/changeCapture.ts +342 -80
  333. package/src/runner/cli.ts +7 -6
  334. package/src/runner/postTaskCleanup.ts +55 -7
  335. package/src/runner/processSecurity.ts +433 -0
  336. package/src/runner/runTask.ts +441 -292
  337. package/src/runner/simpleProcess.ts +68 -33
  338. package/src/{taskProgress.ts → runner/taskProgress.ts} +3 -3
  339. package/src/{taskRuntime.ts → runner/taskRuntime.ts} +4 -3
  340. package/src/runner/taskStatusStore.ts +54 -0
  341. package/src/runner/watch.ts +290 -57
  342. package/src/security/contentRedaction.ts +31 -2
  343. package/src/security/discoveryTokenStore.ts +18 -4
  344. package/src/security/loopbackHost.ts +19 -0
  345. package/src/security/pathGuard.ts +35 -16
  346. package/src/security/planGuard.ts +2 -1
  347. package/src/security/runtimeGuard.ts +9 -6
  348. package/src/security/secretComparison.ts +13 -0
  349. package/src/security/sensitiveGuard.ts +27 -8
  350. package/src/security/toolInvocationGuard.ts +2 -2
  351. package/src/security/workspaceRootGuard.ts +53 -0
  352. package/src/smoke-test.ts +276 -273
  353. package/src/tools/catalog/index.ts +4 -0
  354. package/src/tools/{toolCatalog.ts → catalog/toolCatalog.ts} +3 -12
  355. package/src/tools/{toolRegistry.ts → catalog/toolRegistry.ts} +29 -16
  356. package/src/tools/definitions/toolDefs.ts +1264 -0
  357. package/src/tools/{auditSession.ts → diagnostics/auditSession.ts} +2 -2
  358. package/src/tools/{auditTask.ts → diagnostics/auditTask.ts} +196 -89
  359. package/src/tools/{healthCheck.ts → diagnostics/healthCheck.ts} +11 -11
  360. package/src/tools/diagnostics/index.ts +6 -0
  361. package/src/tools/{safeStatus.ts → diagnostics/safeStatus.ts} +7 -7
  362. package/src/tools/{safeViews.ts → diagnostics/safeViews.ts} +29 -19
  363. package/src/tools/{schemaDriftCheck.ts → diagnostics/schemaDriftCheck.ts} +3 -3
  364. package/src/tools/{createDirectSession.ts → direct/createDirectSession.ts} +9 -9
  365. package/src/tools/{finalizeDirectSession.ts → direct/finalizeDirectSession.ts} +11 -9
  366. package/src/tools/direct/index.ts +3 -0
  367. package/src/tools/{runDirectVerificationBundle.ts → direct/runDirectVerificationBundle.ts} +2 -2
  368. package/src/tools/{discoverTools.ts → discovery/discoverTools.ts} +6 -6
  369. package/src/tools/{explainTool.ts → discovery/explainTool.ts} +3 -3
  370. package/src/tools/discovery/index.ts +3 -0
  371. package/src/tools/{invokeDiscoveredTool.ts → discovery/invokeDiscoveredTool.ts} +7 -7
  372. package/src/tools/dispatch/coreDispatch.ts +379 -0
  373. package/src/tools/dispatch/diagnosticDispatch.ts +106 -0
  374. package/src/tools/dispatch/directDispatch.ts +168 -0
  375. package/src/tools/dispatch/goalDispatch.ts +128 -0
  376. package/src/tools/dispatch/releaseDispatch.ts +66 -0
  377. package/src/tools/dispatch/types.ts +24 -0
  378. package/src/tools/dispatch/validation.ts +78 -0
  379. package/src/tools/{getPlan.ts → goals/getPlan.ts} +4 -4
  380. package/src/tools/{goalSubgoalTask.ts → goals/goalSubgoalTask.ts} +43 -28
  381. package/src/tools/goals/index.ts +3 -0
  382. package/src/tools/{savePlan.ts → goals/savePlan.ts} +38 -8
  383. package/src/tools/registry.ts +54 -1858
  384. package/src/tools/{checkReleaseGate.ts → release/checkReleaseGate.ts} +3 -3
  385. package/src/tools/release/index.ts +2 -0
  386. package/src/tools/{releaseMode.ts → release/releaseMode.ts} +42 -24
  387. package/src/tools/tasks/cancelTask.ts +109 -0
  388. package/src/tools/{createTask.ts → tasks/createTask.ts} +56 -33
  389. package/src/tools/{diagnoseTask.ts → tasks/diagnoseTask.ts} +8 -8
  390. package/src/tools/tasks/evidencePack.ts +504 -0
  391. package/src/tools/{getTaskFile.ts → tasks/getTaskFile.ts} +4 -4
  392. package/src/tools/{getTaskStatus.ts → tasks/getTaskStatus.ts} +7 -5
  393. package/src/tools/{getTaskStdoutTail.ts → tasks/getTaskStdoutTail.ts} +13 -11
  394. package/src/tools/{getTaskSummary.ts → tasks/getTaskSummary.ts} +44 -33
  395. package/src/tools/tasks/index.ts +18 -0
  396. package/src/tools/{listTasks.ts → tasks/listTasks.ts} +4 -4
  397. package/src/tools/{reconcileTasks.ts → tasks/reconcileTasks.ts} +68 -66
  398. package/src/tools/tasks/retryTask.ts +69 -0
  399. package/src/tools/{runTaskLoop.ts → tasks/runTaskLoop.ts} +70 -35
  400. package/src/tools/{runVerification.ts → tasks/runVerification.ts} +6 -3
  401. package/src/tools/{taskLineage.ts → tasks/taskLineage.ts} +8 -7
  402. package/src/tools/{taskOutputs.ts → tasks/taskOutputs.ts} +27 -20
  403. package/src/tools/{androidDoctor.ts → workspace/androidDoctor.ts} +15 -10
  404. package/src/tools/{applyPatch.ts → workspace/applyPatch.ts} +38 -16
  405. package/src/tools/{discardWorktree.ts → workspace/discardWorktree.ts} +3 -3
  406. package/src/tools/workspace/index.ts +10 -0
  407. package/src/tools/{listAgents.ts → workspace/listAgents.ts} +11 -4
  408. package/src/tools/{listWorkspace.ts → workspace/listWorkspace.ts} +3 -3
  409. package/src/tools/{mergeWorktree.ts → workspace/mergeWorktree.ts} +3 -3
  410. package/src/tools/{readWorkspaceFile.ts → workspace/readWorkspaceFile.ts} +8 -8
  411. package/src/tools/{recommendAgentForTask.ts → workspace/recommendAgentForTask.ts} +3 -3
  412. package/src/tools/{searchWorkspace.ts → workspace/searchWorkspace.ts} +5 -5
  413. package/src/tools/workspace/syncFile.ts +292 -0
  414. package/src/utils/atomicFile.ts +58 -0
  415. package/src/utils/boundedFile.ts +116 -0
  416. package/src/utils/lockedJsonFile.ts +251 -0
  417. package/src/utils/platform.ts +31 -0
  418. package/src/utils/stableJson.ts +12 -0
  419. package/src/version.ts +3 -2
  420. package/src/watcherStatus.ts +19 -1
  421. package/ui/desktop-bootstrap.js +11 -0
  422. package/ui/desktop-bridge.js +36 -0
  423. package/ui/desktop.css +160 -0
  424. package/ui/getting-started.js +93 -0
  425. package/ui/i18n.js +484 -0
  426. package/ui/log-parser.js +30 -0
  427. package/ui/pages/audit.html +204 -3
  428. package/ui/pages/dashboard.html +937 -79
  429. package/ui/pages/direct-sessions.html +609 -60
  430. package/ui/pages/getting-started.html +43 -0
  431. package/ui/pages/logs.html +105 -22
  432. package/ui/pages/settings.html +101 -0
  433. package/ui/pages/task-detail.html +468 -438
  434. package/ui/pages/tasks.html +648 -65
  435. package/ui/pages/workspace.html +38 -1
  436. package/ui/settings.js +245 -0
  437. package/PatchWarden-Control.cmd +0 -6
  438. package/Restart-PatchWarden-Control.cmd +0 -6
  439. package/dist/test/unit/acceptance-engine.test.d.ts +0 -1
  440. package/dist/test/unit/acceptance-engine.test.js +0 -228
  441. package/dist/test/unit/agent-router.test.d.ts +0 -1
  442. package/dist/test/unit/agent-router.test.js +0 -287
  443. package/dist/test/unit/android-doctor.test.d.ts +0 -1
  444. package/dist/test/unit/android-doctor.test.js +0 -118
  445. package/dist/test/unit/audit-checks.test.d.ts +0 -1
  446. package/dist/test/unit/audit-checks.test.js +0 -350
  447. package/dist/test/unit/chinese-path.test.d.ts +0 -1
  448. package/dist/test/unit/chinese-path.test.js +0 -91
  449. package/dist/test/unit/command-guard.test.d.ts +0 -1
  450. package/dist/test/unit/command-guard.test.js +0 -160
  451. package/dist/test/unit/diagnose-task.test.d.ts +0 -1
  452. package/dist/test/unit/diagnose-task.test.js +0 -457
  453. package/dist/test/unit/direct-guards.test.d.ts +0 -1
  454. package/dist/test/unit/direct-guards.test.js +0 -213
  455. package/dist/test/unit/discovery-token-store.test.d.ts +0 -1
  456. package/dist/test/unit/discovery-token-store.test.js +0 -139
  457. package/dist/test/unit/evidence-pack.test.d.ts +0 -1
  458. package/dist/test/unit/evidence-pack.test.js +0 -130
  459. package/dist/test/unit/goal-graph.test.d.ts +0 -1
  460. package/dist/test/unit/goal-graph.test.js +0 -298
  461. package/dist/test/unit/goal-progress.test.d.ts +0 -1
  462. package/dist/test/unit/goal-progress.test.js +0 -381
  463. package/dist/test/unit/goal-status.test.d.ts +0 -1
  464. package/dist/test/unit/goal-status.test.js +0 -215
  465. package/dist/test/unit/goal-store.test.d.ts +0 -1
  466. package/dist/test/unit/goal-store.test.js +0 -253
  467. package/dist/test/unit/goal-subgoal-task.test.d.ts +0 -1
  468. package/dist/test/unit/goal-subgoal-task.test.js +0 -55
  469. package/dist/test/unit/goal-tools-registry.test.d.ts +0 -1
  470. package/dist/test/unit/goal-tools-registry.test.js +0 -190
  471. package/dist/test/unit/handoff-export.test.d.ts +0 -1
  472. package/dist/test/unit/handoff-export.test.js +0 -263
  473. package/dist/test/unit/invoke-discovered-tool.test.d.ts +0 -1
  474. package/dist/test/unit/invoke-discovered-tool.test.js +0 -167
  475. package/dist/test/unit/logging.test.d.ts +0 -1
  476. package/dist/test/unit/logging.test.js +0 -397
  477. package/dist/test/unit/path-guard.test.d.ts +0 -1
  478. package/dist/test/unit/path-guard.test.js +0 -109
  479. package/dist/test/unit/post-task-cleanup.test.d.ts +0 -1
  480. package/dist/test/unit/post-task-cleanup.test.js +0 -48
  481. package/dist/test/unit/project-policy-release-mode.test.d.ts +0 -1
  482. package/dist/test/unit/project-policy-release-mode.test.js +0 -125
  483. package/dist/test/unit/reconcile-tasks.test.d.ts +0 -1
  484. package/dist/test/unit/reconcile-tasks.test.js +0 -456
  485. package/dist/test/unit/release-gate.test.d.ts +0 -1
  486. package/dist/test/unit/release-gate.test.js +0 -242
  487. package/dist/test/unit/run-task-loop.test.d.ts +0 -1
  488. package/dist/test/unit/run-task-loop.test.js +0 -380
  489. package/dist/test/unit/safe-status.test.d.ts +0 -1
  490. package/dist/test/unit/safe-status.test.js +0 -165
  491. package/dist/test/unit/safe-views.test.d.ts +0 -1
  492. package/dist/test/unit/safe-views.test.js +0 -171
  493. package/dist/test/unit/schema-drift-check.test.d.ts +0 -1
  494. package/dist/test/unit/schema-drift-check.test.js +0 -176
  495. package/dist/test/unit/sensitive-guard.test.d.ts +0 -1
  496. package/dist/test/unit/sensitive-guard.test.js +0 -104
  497. package/dist/test/unit/subgoal-sync.test.d.ts +0 -1
  498. package/dist/test/unit/subgoal-sync.test.js +0 -183
  499. package/dist/test/unit/sync-file.test.d.ts +0 -1
  500. package/dist/test/unit/sync-file.test.js +0 -154
  501. package/dist/test/unit/tool-invocation-guard.test.d.ts +0 -1
  502. package/dist/test/unit/tool-invocation-guard.test.js +0 -432
  503. package/dist/test/unit/tool-usage-stats.test.d.ts +0 -1
  504. package/dist/test/unit/tool-usage-stats.test.js +0 -300
  505. package/dist/test/unit/toolSearch.test.d.ts +0 -1
  506. package/dist/test/unit/toolSearch.test.js +0 -571
  507. package/dist/test/unit/watcher-status.test.d.ts +0 -1
  508. package/dist/test/unit/watcher-status.test.js +0 -169
  509. package/dist/test/unit/worktree-manager.test.d.ts +0 -1
  510. package/dist/test/unit/worktree-manager.test.js +0 -176
  511. package/dist/tools/applyPatch.js +0 -41
  512. package/dist/tools/cancelTask.d.ts +0 -30
  513. package/dist/tools/cancelTask.js +0 -64
  514. package/dist/tools/evidencePack.js +0 -168
  515. package/dist/tools/finalizeDirectSession.js +0 -84
  516. package/dist/tools/goalSubgoalTask.js +0 -110
  517. package/dist/tools/killTask.d.ts +0 -15
  518. package/dist/tools/retryTask.js +0 -45
  519. package/dist/tools/runVerification.js +0 -36
  520. package/dist/tools/syncFile.js +0 -65
  521. package/docs/control-center/control-center-daily-driver.md +0 -211
  522. package/docs/control-center/control-center-mvp.md +0 -205
  523. package/docs/control-center/control-center-phase2.md +0 -159
  524. package/docs/release-v0.6.0.md +0 -71
  525. package/docs/release-v0.6.1.md +0 -75
  526. package/docs/release-v0.6.4.md +0 -45
  527. package/src/test/unit/acceptance-engine.test.ts +0 -261
  528. package/src/test/unit/agent-router.test.ts +0 -342
  529. package/src/test/unit/android-doctor.test.ts +0 -158
  530. package/src/test/unit/audit-checks.test.ts +0 -567
  531. package/src/test/unit/chinese-path.test.ts +0 -106
  532. package/src/test/unit/command-guard.test.ts +0 -221
  533. package/src/test/unit/diagnose-task.test.ts +0 -544
  534. package/src/test/unit/direct-guards.test.ts +0 -297
  535. package/src/test/unit/discovery-token-store.test.ts +0 -181
  536. package/src/test/unit/evidence-pack.test.ts +0 -142
  537. package/src/test/unit/goal-graph.test.ts +0 -347
  538. package/src/test/unit/goal-progress.test.ts +0 -538
  539. package/src/test/unit/goal-status.test.ts +0 -270
  540. package/src/test/unit/goal-store.test.ts +0 -318
  541. package/src/test/unit/goal-subgoal-task.test.ts +0 -72
  542. package/src/test/unit/goal-tools-registry.test.ts +0 -243
  543. package/src/test/unit/handoff-export.test.ts +0 -295
  544. package/src/test/unit/invoke-discovered-tool.test.ts +0 -216
  545. package/src/test/unit/logging.test.ts +0 -497
  546. package/src/test/unit/path-guard.test.ts +0 -150
  547. package/src/test/unit/post-task-cleanup.test.ts +0 -53
  548. package/src/test/unit/project-policy-release-mode.test.ts +0 -156
  549. package/src/test/unit/reconcile-tasks.test.ts +0 -551
  550. package/src/test/unit/release-gate.test.ts +0 -314
  551. package/src/test/unit/run-task-loop.test.ts +0 -425
  552. package/src/test/unit/safe-status.test.ts +0 -187
  553. package/src/test/unit/safe-views.test.ts +0 -184
  554. package/src/test/unit/schema-drift-check.test.ts +0 -260
  555. package/src/test/unit/sensitive-guard.test.ts +0 -124
  556. package/src/test/unit/subgoal-sync.test.ts +0 -236
  557. package/src/test/unit/sync-file.test.ts +0 -231
  558. package/src/test/unit/tool-invocation-guard.test.ts +0 -542
  559. package/src/test/unit/tool-usage-stats.test.ts +0 -384
  560. package/src/test/unit/toolSearch.test.ts +0 -756
  561. package/src/test/unit/watcher-status.test.ts +0 -190
  562. package/src/test/unit/worktree-manager.test.ts +0 -247
  563. package/src/tools/cancelTask.ts +0 -70
  564. package/src/tools/evidencePack.ts +0 -205
  565. package/src/tools/retryTask.ts +0 -53
  566. package/src/tools/syncFile.ts +0 -122
  567. /package/dist/tools/{toolCatalog.d.ts → catalog/toolCatalog.d.ts} +0 -0
  568. /package/dist/tools/{toolSearch.d.ts → catalog/toolSearch.d.ts} +0 -0
  569. /package/dist/tools/{toolSearch.js → catalog/toolSearch.js} +0 -0
  570. /package/dist/tools/{toolUsageStats.d.ts → catalog/toolUsageStats.d.ts} +0 -0
  571. /package/dist/tools/{toolUsageStats.js → catalog/toolUsageStats.js} +0 -0
  572. /package/dist/tools/{runDirectVerificationBundle.d.ts → direct/runDirectVerificationBundle.d.ts} +0 -0
  573. /package/dist/tools/{getPlan.d.ts → goals/getPlan.d.ts} +0 -0
  574. /package/dist/tools/{savePlan.d.ts → goals/savePlan.d.ts} +0 -0
  575. /package/dist/tools/{getTaskFile.d.ts → tasks/getTaskFile.d.ts} +0 -0
  576. /package/dist/tools/{getTaskProgress.d.ts → tasks/getTaskProgress.d.ts} +0 -0
  577. /package/dist/tools/{getTaskProgress.js → tasks/getTaskProgress.js} +0 -0
  578. /package/dist/tools/{getTaskStdoutTail.d.ts → tasks/getTaskStdoutTail.d.ts} +0 -0
  579. /package/dist/tools/{getTaskSummary.d.ts → tasks/getTaskSummary.d.ts} +0 -0
  580. /package/dist/tools/{killTask.js → tasks/killTask.js} +0 -0
  581. /package/dist/tools/{runVerification.d.ts → tasks/runVerification.d.ts} +0 -0
  582. /package/dist/tools/{taskLineage.d.ts → tasks/taskLineage.d.ts} +0 -0
  583. /package/dist/tools/{taskOutputs.d.ts → tasks/taskOutputs.d.ts} +0 -0
  584. /package/dist/tools/{waitForTask.d.ts → tasks/waitForTask.d.ts} +0 -0
  585. /package/dist/tools/{waitForTask.js → tasks/waitForTask.js} +0 -0
  586. /package/dist/tools/{androidDoctor.d.ts → workspace/androidDoctor.d.ts} +0 -0
  587. /package/dist/tools/{discardWorktree.d.ts → workspace/discardWorktree.d.ts} +0 -0
  588. /package/dist/tools/{listWorkspace.d.ts → workspace/listWorkspace.d.ts} +0 -0
  589. /package/dist/tools/{mergeWorktree.d.ts → workspace/mergeWorktree.d.ts} +0 -0
  590. /package/dist/tools/{readWorkspaceFile.d.ts → workspace/readWorkspaceFile.d.ts} +0 -0
  591. /package/dist/tools/{recommendAgentForTask.d.ts → workspace/recommendAgentForTask.d.ts} +0 -0
  592. /package/dist/tools/{searchWorkspace.d.ts → workspace/searchWorkspace.d.ts} +0 -0
  593. /package/src/tools/{toolSearch.ts → catalog/toolSearch.ts} +0 -0
  594. /package/src/tools/{toolUsageStats.ts → catalog/toolUsageStats.ts} +0 -0
  595. /package/src/tools/{getTaskProgress.ts → tasks/getTaskProgress.ts} +0 -0
  596. /package/src/tools/{killTask.ts → tasks/killTask.ts} +0 -0
  597. /package/src/tools/{waitForTask.ts → tasks/waitForTask.ts} +0 -0
@@ -1,84 +0,0 @@
1
- import { join, resolve, relative, isAbsolute } from "node:path";
2
- import { readDirectSession, finalizeDirectSessionRecord, getDirectSessionDir, } from "../direct/directSessionStore.js";
3
- import { guardDirectSessionActive } from "../direct/directGuards.js";
4
- import { captureRepoSnapshot, buildChangeArtifacts, } from "../runner/changeCapture.js";
5
- // ── Main function ──────────────────────────────────────────────────
6
- export function finalizeDirectSession(input) {
7
- const { session_id } = input;
8
- // 1. Read session and guard active (not expired, not finalized)
9
- const session = readDirectSession(session_id);
10
- guardDirectSessionActive(session);
11
- // 2. Capture after snapshot
12
- const afterSnapshot = captureRepoSnapshot(session.resolved_repo_path);
13
- // 3. Build change artifacts from before/after snapshots
14
- const changeArtifacts = buildChangeArtifacts(session.resolved_repo_path, session.workspace_snapshot_before, afterSnapshot);
15
- // 4. Finalize session record — writes changed-files.json, diff.patch,
16
- // summary.json, summary.md and marks the session as finalized.
17
- finalizeDirectSessionRecord(session_id, afterSnapshot, changeArtifacts);
18
- // 5. Build verification summary from session.verification_runs
19
- const verification_summary = {};
20
- for (const run of session.verification_runs) {
21
- verification_summary[run.command] = run.passed ? "passed" : "failed";
22
- }
23
- // 6. Identify out-of-scope changes (paths outside resolved_repo_path)
24
- const out_of_scope_changes = findOutOfScopeChanges(changeArtifacts, session.resolved_repo_path);
25
- // 7. Build compact summary with categorized changes
26
- const sessionDir = getDirectSessionDir(session_id);
27
- return {
28
- session_id,
29
- changed_files_total: changeArtifacts.changed_files.length,
30
- source_changes: changeArtifacts.artifact_hygiene.source_changes,
31
- tracked_build_artifacts: changeArtifacts.artifact_hygiene.tracked_build_artifacts,
32
- runtime_generated_files: changeArtifacts.artifact_hygiene.runtime_generated_files,
33
- suspicious_changes: changeArtifacts.artifact_hygiene.suspicious_changes,
34
- out_of_scope_changes,
35
- verification_summary,
36
- diff_path: join(sessionDir, "diff.patch"),
37
- summary_path: join(sessionDir, "summary.md"),
38
- finalized: true,
39
- next_action: "Call audit_session to independently review the changes.",
40
- };
41
- }
42
- // ── Helpers ────────────────────────────────────────────────────────
43
- /**
44
- * Filter changeArtifacts.changed_files for paths that resolve outside the
45
- * session's resolved_repo_path and map them to ClassifiedChange format.
46
- */
47
- function findOutOfScopeChanges(artifacts, resolvedRepoPath) {
48
- const normalizedRepo = resolve(resolvedRepoPath);
49
- return artifacts.changed_files
50
- .filter((file) => {
51
- const fullPath = resolve(normalizedRepo, file.path);
52
- const rel = relative(normalizedRepo, fullPath);
53
- return isAbsolute(rel) || rel.startsWith("..");
54
- })
55
- .map((file) => toClassifiedChange(file));
56
- }
57
- /**
58
- * Map a ChangedFile to the ClassifiedChange format by adding a reason string.
59
- */
60
- function toClassifiedChange(file) {
61
- return {
62
- path: file.path,
63
- change: file.change,
64
- tracked: file.tracked,
65
- ignored: file.ignored,
66
- kind: file.kind,
67
- reason: classificationReason(file),
68
- };
69
- }
70
- /**
71
- * Produce a human-readable reason for a changed file classification.
72
- * Mirrors the logic in changeCapture.ts classifyArtifactHygiene.
73
- */
74
- function classificationReason(change) {
75
- if (change.ignored)
76
- return "untracked path is ignored by repository Git rules";
77
- if (change.kind === "build_artifact" && change.tracked)
78
- return "artifact-like path is tracked by Git and requires review";
79
- if (change.kind === "build_artifact")
80
- return "artifact-like path is not ignored and requires review";
81
- if (change.kind === "runtime_generated")
82
- return "runtime-generated path is not ignored and requires review";
83
- return change.tracked ? "tracked source change" : "untracked source change";
84
- }
@@ -1,110 +0,0 @@
1
- /**
2
- * v0.8.0: createSubgoalTask — 原子地将一个新 subgoal 关联到一个新任务。
3
- *
4
- * 流程(原子语义):
5
- * 1. 读取 goal_status.json(不存在则抛 goal_not_found)
6
- * 2. addSubgoal(校验 depends_on 引用已有 subgoal)
7
- * 3. createTask 创建关联任务(写入 goal_id / subgoal_id 到 task status.json)
8
- * 4. linkTaskToSubgoal(将 task_id 关联到 subgoal)
9
- * 5. updateSubgoalStatus(running)(ready → running)
10
- * 6. 写回 goal_status.json
11
- *
12
- * 注意:
13
- * - createSubgoalTask 强制 execution_mode 为 "execute",因为 assess_only 不产生可关联的 task。
14
- * - createTask 内部使用 getConfig(),因此 workspaceRoot 由全局配置决定。
15
- */
16
- import { readGoalStatus, writeGoalStatus } from "../goal/goalStore.js";
17
- import { addSubgoal, linkTaskToSubgoal, updateSubgoalStatus } from "../goal/goalStatus.js";
18
- import { createTask } from "./createTask.js";
19
- import { createWorktree, discardWorktree } from "../goal/worktreeManager.js";
20
- import { getConfig } from "../config.js";
21
- import { PatchWardenError } from "../errors.js";
22
- // ── 函数实现 ──────────────────────────────────────────────────────
23
- /**
24
- * 原子地创建一个 subgoal 并关联到一个新任务。
25
- *
26
- * @throws PatchWardenError("goal_not_found") 当 goal_id 不存在
27
- * @throws PatchWardenError("invalid_dependency") 当 depends_on 引用不存在的 subgoal
28
- * @throws PatchWardenError("invalid_execution_mode") 当 execution_mode 为 "assess_only"
29
- */
30
- export function createSubgoalTask(input) {
31
- // assess_only 不产生 task,无法关联到 subgoal
32
- if (input.execution_mode === "assess_only") {
33
- throw new PatchWardenError("invalid_execution_mode", "createSubgoalTask does not support execution_mode \"assess_only\"", "Use execution_mode \"execute\" (default) so a task is created and linked to the subgoal.", true, { goal_id: input.goal_id, execution_mode: input.execution_mode });
34
- }
35
- // 1. 读取 goal_status.json,如果不存在抛 goal_not_found
36
- let goalStatus;
37
- try {
38
- goalStatus = readGoalStatus(input.goal_id);
39
- }
40
- catch {
41
- throw new PatchWardenError("goal_not_found", `Goal "${input.goal_id}" not found`, "Call list_goals to see available goals.", true, { goal_id: input.goal_id });
42
- }
43
- // 2. addSubgoal(校验 depends_on)
44
- const { goalStatus: withSubgoal, subgoalId } = addSubgoal(goalStatus, input.subgoal_title, input.depends_on ?? []);
45
- // 2.5 Worktree 隔离(默认开启):为该 subgoal task 创建独立 git worktree,
46
- // 用 worktree 路径作为 createTask 的 repo_path,避免并发 task 互相污染。
47
- // isolate_worktree === false 时退化为原行为(使用 input.repo_path)。
48
- const isolate = input.isolate_worktree !== false;
49
- let repoPathForTask = input.repo_path;
50
- let worktreeId = null;
51
- if (isolate) {
52
- const workspaceRoot = getConfig().workspaceRoot;
53
- const wt = createWorktree(input.goal_id, subgoalId, workspaceRoot);
54
- repoPathForTask = wt.worktreePath;
55
- worktreeId = wt.worktreeId;
56
- }
57
- // 3. 调用 createTask 创建关联任务(强制 execute 模式,确保返回 CreateTaskOutput)
58
- let taskId;
59
- try {
60
- const taskResult = createTask({
61
- plan_id: input.plan_id,
62
- inline_plan: input.inline_plan,
63
- plan_title: input.plan_title,
64
- template: input.template,
65
- goal: input.goal,
66
- agent: input.agent,
67
- repo_path: repoPathForTask,
68
- test_command: input.test_command,
69
- verify_commands: input.verify_commands,
70
- timeout_seconds: input.timeout_seconds,
71
- execution_mode: "execute",
72
- assessment_id: input.assessment_id,
73
- scope: input.scope,
74
- forbidden: input.forbidden,
75
- verification: input.verification,
76
- done_evidence: input.done_evidence,
77
- goal_id: input.goal_id,
78
- subgoal_id: subgoalId,
79
- });
80
- // execution_mode 为 "execute",createTask 返回 CreateTaskOutput(含 task_id)
81
- taskId = taskResult.task_id;
82
- }
83
- catch (createTaskErr) {
84
- // createTask 失败:清理已创建的隔离 worktree,避免遗留半成品(best effort)
85
- if (isolate && worktreeId) {
86
- try {
87
- discardWorktree(worktreeId, getConfig().workspaceRoot);
88
- }
89
- catch { /* ignore cleanup failure,向上抛出原始 createTask 错误 */ }
90
- }
91
- throw createTaskErr;
92
- }
93
- // 4. linkTaskToSubgoal + updateSubgoalStatus(running)
94
- const withTask = linkTaskToSubgoal(withSubgoal, subgoalId, taskId);
95
- let withRunning = updateSubgoalStatus(withTask, subgoalId, "running");
96
- // 4.5 隔离模式下,把 worktree_id 记录到 subgoal 对象(写入 goal_status.json)
97
- if (isolate && worktreeId) {
98
- const newSubgoals = withRunning.subgoals.map((s) => s.id === subgoalId
99
- ? { ...s, worktree_id: worktreeId }
100
- : s);
101
- withRunning = { ...withRunning, subgoals: newSubgoals };
102
- }
103
- // 5. 写回 goal_status.json
104
- writeGoalStatus(input.goal_id, withRunning);
105
- return {
106
- subgoal_id: subgoalId,
107
- task_id: taskId,
108
- subgoal_status: "running",
109
- };
110
- }
@@ -1,15 +0,0 @@
1
- export declare function killTask(taskId: string): {
2
- task_id: string;
3
- previous_status: string;
4
- new_status: string;
5
- message: string;
6
- cancel_requested?: undefined;
7
- force_kill_requested?: undefined;
8
- } | {
9
- task_id: string;
10
- previous_status: string;
11
- new_status: string;
12
- cancel_requested: boolean;
13
- force_kill_requested: boolean;
14
- message: string;
15
- };
@@ -1,45 +0,0 @@
1
- import { readFileSync, writeFileSync, existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { getTasksDir, getConfig } from "../config.js";
4
- import { guardReadPath } from "../security/pathGuard.js";
5
- import { createTask } from "./createTask.js";
6
- export function retryTask(taskId) {
7
- const config = getConfig();
8
- const tasksDir = getTasksDir(config);
9
- const taskDir = join(tasksDir, taskId);
10
- const statusFile = join(taskDir, "status.json");
11
- guardReadPath(statusFile, config.workspaceRoot, config.tasksDir);
12
- if (!existsSync(statusFile)) {
13
- throw new Error(`Task not found: "${taskId}"`);
14
- }
15
- const data = JSON.parse(readFileSync(statusFile, "utf-8"));
16
- if (!data.plan_id || !data.agent) {
17
- throw new Error(`Task "${taskId}" is missing plan_id or agent. Cannot retry.`);
18
- }
19
- // Create a new task with the same parameters
20
- const newTask = createTask({
21
- plan_id: data.plan_id,
22
- agent: data.agent,
23
- repo_path: data.repo_path,
24
- test_command: data.test_command,
25
- verify_commands: data.verify_commands,
26
- timeout_seconds: data.timeout_seconds,
27
- });
28
- // Record retry relationship in the new task
29
- const newStatusFile = join(newTask.path, "status.json");
30
- const newData = JSON.parse(readFileSync(newStatusFile, "utf-8"));
31
- newData.retry_of = taskId;
32
- newData.retry_count = (data.retry_count || 0) + 1;
33
- newData.plan_source = data.plan_source || "saved";
34
- newData.template = data.template || null;
35
- newData.change_policy = data.change_policy || "repo_scoped_changes";
36
- writeFileSync(newStatusFile, JSON.stringify(newData, null, 2), "utf-8");
37
- return {
38
- original_task_id: taskId,
39
- new_task_id: newTask.task_id,
40
- plan_id: newTask.plan_id,
41
- agent: newTask.agent,
42
- status: newTask.status,
43
- message: `New task created from retry of ${taskId}. Original task is unchanged.`,
44
- };
45
- }
@@ -1,36 +0,0 @@
1
- import { readDirectSession, appendDirectSessionVerificationRun, } from "../direct/directSessionStore.js";
2
- import { guardDirectSessionActive } from "../direct/directGuards.js";
3
- import { runDirectVerification } from "../direct/directVerification.js";
4
- export async function runVerification(input) {
5
- // 1. Read session and guard active
6
- const session = readDirectSession(input.session_id);
7
- guardDirectSessionActive(session);
8
- // 2. Call runDirectVerification with command, resolvedRepoPath,
9
- // sessionId, and timeoutSeconds
10
- const timeoutSeconds = input.timeout_seconds ?? 120;
11
- const result = await runDirectVerification({
12
- command: input.command,
13
- resolvedRepoPath: session.resolved_repo_path,
14
- sessionId: input.session_id,
15
- timeoutSeconds,
16
- });
17
- // 3. Append verification run to session
18
- appendDirectSessionVerificationRun(input.session_id, result.run);
19
- // 4. Return result
20
- return {
21
- command: result.run.command,
22
- exit_code: result.run.exit_code,
23
- passed: result.run.passed,
24
- timed_out: result.run.timed_out,
25
- redacted: Boolean(result.run.redacted),
26
- redaction_categories: result.run.redaction_categories || [],
27
- started_at: result.run.started_at,
28
- finished_at: result.run.finished_at,
29
- stdout_tail: result.run.stdout_tail,
30
- stderr_tail: result.run.stderr_tail,
31
- log_path: result.run.log_path,
32
- next_action: result.run.passed
33
- ? "Call finalize_direct_session to complete the session."
34
- : "Review the verification output and apply_patch to fix issues.",
35
- };
36
- }
@@ -1,65 +0,0 @@
1
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
2
- import { dirname, resolve } from "node:path";
3
- import { PatchWardenError } from "../errors.js";
4
- import { getConfig } from "../config.js";
5
- import { guardDirectPath, guardDirectWritePath } from "../direct/directGuards.js";
6
- import { guardSensitivePath } from "../security/sensitiveGuard.js";
7
- import { computeFileSha256 } from "../direct/directPatch.js";
8
- /**
9
- * Copy a file from source to target within the same session repo.
10
- * Both source and target must be inside the session's repo_path.
11
- */
12
- export function syncFile(sessionId, sourcePath, targetPath, options, config) {
13
- const cfg = config || getConfig();
14
- const sessionsDir = resolve(cfg.workspaceRoot, cfg.directSessionsDir);
15
- // Load session to get repo_path
16
- const sessionFile = resolve(sessionsDir, sessionId, "session.json");
17
- if (!existsSync(sessionFile)) {
18
- throw new PatchWardenError("direct_session_not_found", `Direct session "${sessionId}" not found.`, "Create a direct session first using direct_start_session.", true, { session_id: sessionId });
19
- }
20
- const session = JSON.parse(readFileSync(sessionFile, "utf-8"));
21
- const repoPath = resolve(session.repo_path);
22
- const workspaceRoot = cfg.workspaceRoot;
23
- // Guard source path — must be inside repo
24
- const resolvedSource = guardDirectPath(sourcePath, repoPath, workspaceRoot);
25
- guardSensitivePath(resolvedSource);
26
- if (!existsSync(resolvedSource)) {
27
- throw new PatchWardenError("source_file_not_found", `Source file does not exist: "${sourcePath}".`, "Ensure the source path is correct.", true, { source_path: sourcePath });
28
- }
29
- // Guard target path — must be inside repo, not in blocked dirs
30
- const resolvedTarget = guardDirectWritePath(targetPath, repoPath, workspaceRoot);
31
- guardSensitivePath(resolvedTarget);
32
- // Verify source sha256 if provided
33
- const sourceSha256 = computeFileSha256(resolvedSource);
34
- if (options?.expected_source_sha256 && options.expected_source_sha256 !== sourceSha256) {
35
- throw new PatchWardenError("source_hash_mismatch", `Source file hash mismatch. Expected "${options.expected_source_sha256}" but got "${sourceSha256}".`, "Re-read the source file to get the current sha256.", true, { expected_sha256: options.expected_source_sha256, actual_sha256: sourceSha256 });
36
- }
37
- // Get target sha256 before copy
38
- let beforeTargetSha256 = null;
39
- if (existsSync(resolvedTarget)) {
40
- beforeTargetSha256 = computeFileSha256(resolvedTarget);
41
- // Verify target sha256 if provided
42
- if (options?.expected_target_sha256 && options.expected_target_sha256 !== beforeTargetSha256) {
43
- throw new PatchWardenError("target_hash_mismatch", `Target file hash mismatch. Expected "${options.expected_target_sha256}" but got "${beforeTargetSha256}".`, "Re-read the target file to get the current sha256.", true, { expected_sha256: options.expected_target_sha256, actual_sha256: beforeTargetSha256 });
44
- }
45
- }
46
- // Read source content
47
- const sourceContent = readFileSync(resolvedSource);
48
- const copiedBytes = sourceContent.length;
49
- // Create target directory if needed
50
- mkdirSync(dirname(resolvedTarget), { recursive: true });
51
- // Write to target
52
- writeFileSync(resolvedTarget, sourceContent, "utf-8");
53
- // Compute after hash
54
- const afterTargetSha256 = computeFileSha256(resolvedTarget);
55
- const changed = beforeTargetSha256 !== afterTargetSha256;
56
- return {
57
- source_path: sourcePath,
58
- target_path: targetPath,
59
- before_target_sha256: beforeTargetSha256,
60
- after_target_sha256: afterTargetSha256,
61
- source_sha256: sourceSha256,
62
- copied_bytes: copiedBytes,
63
- changed,
64
- };
65
- }
@@ -1,211 +0,0 @@
1
- # PatchWarden Control Center Daily Driver
2
-
3
- > v0.6.4 在 v0.6.2 MVP 与 v0.6.3 Phase 2 基础上,把 Control Center 从「启动页面脚本」
4
- > 升级为日常入口:单实例启动、后台运行、托盘入口、健康修复建议、页面通知和活动时间线。
5
- > 不重构架构,不合并 Core/Direct MCP,不改现有 MCP 工具注册逻辑。
6
- > 不发布 npm,不打 git tag。
7
-
8
- ## 概述
9
-
10
- Daily Driver 完全在 Control Center HTTP 层与启动脚本层增强,未触动 MCP 工具注册、
11
- watcher 核心循环或 Direct session 写入逻辑。新增的 API 沿用既有 token 校验、路径围栏
12
- 和脱敏机制;托盘与后台模式仅调用现有 Control Center API,不引入新的进程管理路径。
13
-
14
- - **单实例启动**:status 文件 + 端口探测,重复运行只开浏览器,不启第二个服务
15
- - **后台运行**:`-Background`(默认)/ `-Foreground` / `-NoBrowser`,日志写入
16
- `%LOCALAPPDATA%\patchwarden\control-center\control-center.{stdout,stderr}.log`
17
- - **托盘入口**:基于 .NET NotifyIcon 的轻量 PowerShell 托盘,无需 Electron
18
- - **健康修复建议**:`/api/status` 新增 `suggestions` 字段,dashboard 显示建议卡片
19
- - **页面通知**:dashboard 轮询状态变化时弹出 toast,同一事件只提示一次
20
- - **Activity Timeline**:`runtime/control-center-events.jsonl` 记录关键事件,
21
- `GET /api/events` 返回最近事件,dashboard 显示时间线区块
22
-
23
- ## 启动方式
24
-
25
- ### 1. 日常入口(推荐)
26
-
27
- ```powershell
28
- .\PatchWarden-Control.cmd
29
- ```
30
-
31
- 默认后台启动 Control Center 并打开浏览器。再次运行时:
32
-
33
- - 如果 127.0.0.1:8090 已经是当前 Control Center —— 直接打开浏览器页面,不重复启动
34
- - 如果端口被其他程序占用 —— 给出明确错误提示并退出
35
- - 如果 status 文件指向已死的 PID —— 清理孤儿进程后启动新实例
36
-
37
- ### 2. 启动参数
38
-
39
- ```powershell
40
- .\PatchWarden-Control.cmd -NoBrowser # 启动但不打开浏览器
41
- .\PatchWarden-Control.cmd -Foreground # 前台运行,日志直接输出到控制台
42
- .\PatchWarden-Control.cmd -Background # 后台运行(默认),脚本启动后即退出
43
- ```
44
-
45
- `-Foreground` 与 `-Background` 互斥;都不传时默认 `-Background`。
46
-
47
- ### 3. 托盘入口
48
-
49
- ```powershell
50
- .\PatchWarden-Control-Tray.cmd
51
- ```
52
-
53
- 启动 Windows 系统托盘图标(基于 .NET NotifyIcon,无需额外依赖)。如果 Control Center
54
- 未运行,托盘脚本会先在后台启动它。托盘菜单:
55
-
56
- | 菜单项 | 行为 |
57
- | --- | --- |
58
- | Open Control Center | 在默认浏览器打开 dashboard |
59
- | Start All | `POST /api/start-all`(带 token) |
60
- | Stop All | `POST /api/stop-all`(带 token) |
61
- | Restart All | `POST /api/restart-all`(带 token) |
62
- | Open Workspace | 通过 `GET /api/workspace` 获取 workspaceRoot 后用 explorer 打开 |
63
- | Open Logs Folder | `POST /api/open-logs-folder`(带 token) |
64
- | Exit | 关闭托盘(不停止 Control Center 后台进程) |
65
-
66
- 双击托盘图标打开 dashboard。所有 API 调用通过 `/control-token.json` 获取 token 后
67
- 带 `X-PatchWarden-Control-Token` 头发起请求。
68
-
69
- ## 改动文件
70
-
71
- | 文件 | 改动 |
72
- | --- | --- |
73
- | `src/version.ts` | `PATCHWARDEN_VERSION` 0.6.3 → 0.6.4 |
74
- | `package.json` | `version` 0.6.3 → 0.6.4 |
75
- | `src/controlCenter.ts` | 新增 status 文件、events JSONL、suggestions 引擎、`/api/events`、`/api/control-center-status`;`getControlCenterLogDir` 支持 `PATCHWARDEN_CONTROL_LOG_DIR` 覆盖 |
76
- | `scripts/control/start-control-center.ps1` | 重写:单实例检测、`-NoBrowser`/`-Foreground`/`-Background`、孤儿清理、端口冲突检测 |
77
- | `scripts/control/control-center-tray.ps1` | 新文件:.NET NotifyIcon 托盘,菜单驱动 Control Center API |
78
- | `PatchWarden-Control-Tray.cmd` | 新文件:托盘启动入口 |
79
- | `ui/pages/dashboard.html` | 新增 Health Suggestions 卡片、toast 通知、Activity Timeline 区块 |
80
- | `scripts/checks/control-center-smoke.js` | 新增 Test 16–20 覆盖 Daily Driver API;`PATCHWARDEN_CONTROL_LOG_DIR` 重定向到项目内临时目录 |
81
- | `scripts/release/pack-clean.js` | forbidden 列表新增 `.tmp/` |
82
- | `.gitignore` | 新增 `.tmp/` |
83
- | `docs/control-center/control-center-daily-driver.md` | 本文档 |
84
-
85
- ## 新增 API
86
-
87
- ### GET 接口(免 token)
88
-
89
- | 路径 | 说明 |
90
- | --- | --- |
91
- | `GET /api/events?limit=<N>` | 返回最近 N 条活动事件(最大 1000),结构 `{events, total, limit}` |
92
- | `GET /api/control-center-status` | 读取 status 文件,返回 `{running, pid, port, started_at, url, version}` 或 `{running: false}` |
93
-
94
- ### /api/status 增强字段
95
-
96
- `GET /api/status` 响应新增 `suggestions` 数组,每条建议包含:
97
-
98
- ```json
99
- {
100
- "code": "core_stopped",
101
- "severity": "warning",
102
- "message": "Core 未运行,建议启动 Core profile",
103
- "action": "/api/core/start",
104
- "link": null
105
- }
106
- ```
107
-
108
- | code | severity | 触发条件 | action |
109
- | --- | --- | --- | --- |
110
- | `core_stopped` | warning | Core 探测不可用 | `/api/core/start` |
111
- | `direct_stopped` | warning | Direct 探测不可用 | `/api/direct/start` |
112
- | `watcher_stale` | error | watcher 状态为 stale/unreadable | `/api/restart-all` |
113
- | `stale_task` | warning | 存在 stale 任务 | 无 action,`link` 指向 tasks 页面 |
114
- | `tunnel_not_ready` | warning | Core 或 Direct tunnel 未就绪 | `/api/restart-all` |
115
- | `agent_missing` | info | 配置的 agent 不可用 | 无 action,提示检查路径 |
116
-
117
- ## 活动事件
118
-
119
- 事件写入 `%LOCALAPPDATA%\patchwarden\control-center\control-center-events.jsonl`,
120
- 每行一个 JSON 对象 `{timestamp, type, payload?}`。文件超过 512KB 时惰性裁剪到
121
- 2000 行。
122
-
123
- ### 事件类型
124
-
125
- | type | 触发时机 |
126
- | --- | --- |
127
- | `control_center.started` | 服务 listen 成功 |
128
- | `control_center.stopped` | 服务收到 SIGTERM/SIGINT 关闭 |
129
- | `manage.start.all` / `manage.stop.all` / `manage.restart.all` | 用户请求 start/stop/restart all |
130
- | `manage.<mode>.<action>.failed` | manage-patchwarden.ps1 执行失败 |
131
- | `core.status_changed` | Core 可用性发生变化(diff 自上次 /api/status 轮询) |
132
- | `direct.status_changed` | Direct 可用性发生变化 |
133
- | `watcher.status_changed` | watcher 状态发生变化 |
134
- | `task.status_changed` | 任务状态从 running → done/failed 等 |
135
- | `task.reconciled` | 用户对 stale 任务执行 reconcile |
136
- | `task.audited` | 用户对任务执行 audit |
137
-
138
- > Control Center 是无状态、拉取驱动的服务。`core/direct/watcher/task.status_changed`
139
- > 事件在 `/api/status` 轮询时通过 digest diff 检测,因此事件时间戳反映的是「被观察到」
140
- > 的时间,不保证是状态变化的精确时刻。
141
-
142
- ## 页面通知(toast)
143
-
144
- dashboard.html 轮询 `/api/status`(30s)和 `/api/audit`(90s)时检测以下状态变化并
145
- 弹出 toast 通知:
146
-
147
- - core/direct: available → unavailable(error)/ unavailable → available(success)
148
- - watcher: healthy → stale/unreadable(error)/ stale → healthy(success)
149
- - task: running → done(success)/ running → failed*(error)
150
- - audit: 新出现的 pass(success)/ warn(warning)/ fail(error)
151
-
152
- 同一事件通过 dedup key 只提示一次;toast 8 秒后自动消失,也可手动关闭。首次加载时
153
- audit 列表会 seed 到 `seenAuditKeys`,不会对已有审计记录弹通知。
154
-
155
- ## 运行时文件
156
-
157
- | 文件 | 路径 | 说明 |
158
- | --- | --- | --- |
159
- | status 文件 | `%LOCALAPPDATA%\patchwarden\control-center\control-center-status.json` | pid/port/started_at/url/version,服务启动时写入,关闭时删除 |
160
- | events 文件 | `%LOCALAPPDATA%\patchwarden\control-center\control-center-events.jsonl` | 活动事件 JSONL |
161
- | stdout 日志 | `%LOCALAPPDATA%\patchwarden\control-center\control-center.stdout.log` | 后台模式 stdout |
162
- | stderr 日志 | `%LOCALAPPDATA%\patchwarden\control-center\control-center.stderr.log` | 后台模式 stderr |
163
-
164
- > `PATCHWARDEN_CONTROL_LOG_DIR` 环境变量可覆盖上述目录(必须为绝对路径),
165
- > 主要用于 smoke test 将其重定向到项目内临时目录。
166
-
167
- ## 测试
168
-
169
- ```powershell
170
- npm.cmd test
171
- ```
172
-
173
- ### control-center-smoke.js(21 项)
174
-
175
- | # | 测试 | 覆盖 |
176
- | --- | --- | --- |
177
- | 1–1b | 静态文件 + 页面路由 | 基础服务 |
178
- | 2 | `/api/status` JSON + 容错 | 结构校验 |
179
- | 3–4 | tasks JSON + control-token | token 机制 |
180
- | 5–7 | POST 无 token / 错 token → 403 | 安全门 |
181
- | 8–9 | token 不污染 git + 无 CDN | 发布卫生 |
182
- | 10 | 其他 GET API 可达 | workspace/audit/logs/tunnel |
183
- | 11–15 | Phase 2 API | stale/reconcile/workspace/direct-sessions/logs |
184
- | **16** | `/api/status` 包含 `suggestions` 数组 | Daily Driver |
185
- | **17** | `/api/events` 返回 JSON | Daily Driver |
186
- | **18** | `/api/logs/control-center` 返回 JSON | Daily Driver |
187
- | **19** | POST `/api/restart-all` 无 token → 403 | Daily Driver |
188
- | **20** | `/api/control-center-status` 报告 running 实例 | Daily Driver(单实例检测) |
189
-
190
- ### 全量测试结果
191
-
192
- ```
193
- security tests: 139 passed, 0 failed
194
- unit tests: 136 passed, 0 failed (1 skipped: Windows symlink)
195
- lifecycle tests: 22 passed, 0 failed
196
- control-center: 21 passed, 0 failed
197
- ```
198
-
199
- ## 已知限制
200
-
201
- 1. **托盘为 PowerShell 实现**:基于 .NET NotifyIcon,不提供跨平台支持;在非 Windows
202
- 环境下不可用。如需跨平台托盘,需引入 Electron 或类似框架(本阶段刻意避免)。
203
- 2. **事件时间为观测时间**:Control Center 无状态,`status_changed` 事件在轮询时通过
204
- diff 检测,时间戳是「被观察到」的时间,不保证是状态变化的精确时刻。
205
- 3. **status 文件依赖可写目录**:如果 `%LOCALAPPDATA%` 不可写(如沙箱环境),
206
- status 文件不会生成,单实例检测会退化为端口探测模式。可通过
207
- `PATCHWARDEN_CONTROL_LOG_DIR` 覆盖到可写目录。
208
- 4. **toast 为页面内通知**:不要求系统级通知;仅当 dashboard 页面打开时才会弹出。
209
- 5. **托盘 Exit 不停止后台进程**:Exit 仅关闭托盘,Control Center 后台 node 进程继续
210
- 运行。需通过 Stop All 或 `Stop-Process -Id <pid>` 停止。
211
- 6. **事件文件不轮转**:超过 512KB 时惰性裁剪到 2000 行,不按日期轮转。