patchwarden 1.5.1 → 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 (573) hide show
  1. package/PatchWarden.cmd +32 -2
  2. package/README.en.md +152 -25
  3. package/README.md +120 -23
  4. package/dist/assessments/agentAssessor.js +21 -12
  5. package/dist/assessments/assessmentStore.js +42 -34
  6. package/dist/config.d.ts +15 -0
  7. package/dist/config.js +66 -13
  8. package/dist/control/fileManager.d.ts +2 -0
  9. package/dist/control/fileManager.js +39 -0
  10. package/dist/control/middleware/auth.d.ts +6 -0
  11. package/dist/control/middleware/auth.js +14 -5
  12. package/dist/control/middleware/static.js +16 -3
  13. package/dist/control/routeTable.d.ts +24 -0
  14. package/dist/control/routeTable.js +263 -0
  15. package/dist/control/routes/audit.js +17 -7
  16. package/dist/control/routes/evidence.js +1 -1
  17. package/dist/control/routes/lineage.js +1 -1
  18. package/dist/control/routes/process.d.ts +7 -0
  19. package/dist/control/routes/process.js +329 -42
  20. package/dist/control/routes/sessions.d.ts +9 -1
  21. package/dist/control/routes/sessions.js +84 -21
  22. package/dist/control/routes/status.d.ts +46 -1
  23. package/dist/control/routes/status.js +72 -15
  24. package/dist/control/routes/taskActions.js +24 -60
  25. package/dist/control/routes/tasks.d.ts +4 -0
  26. package/dist/control/routes/tasks.js +61 -62
  27. package/dist/control/routes/workspace.js +50 -23
  28. package/dist/control/runtime.d.ts +3 -2
  29. package/dist/control/runtime.js +63 -30
  30. package/dist/control/server.js +36 -365
  31. package/dist/control/shared.d.ts +25 -1
  32. package/dist/control/shared.js +64 -11
  33. package/dist/direct/directAudit.js +234 -225
  34. package/dist/direct/directGuards.d.ts +2 -1
  35. package/dist/direct/directGuards.js +42 -29
  36. package/dist/direct/directPatch.d.ts +6 -1
  37. package/dist/direct/directPatch.js +55 -8
  38. package/dist/direct/directSessionStore.d.ts +16 -6
  39. package/dist/direct/directSessionStore.js +127 -35
  40. package/dist/direct/directVerification.js +8 -16
  41. package/dist/doctor.js +62 -52
  42. package/dist/goal/acceptanceEngine.d.ts +1 -1
  43. package/dist/goal/goalProgress.js +75 -69
  44. package/dist/goal/goalReport.js +5 -12
  45. package/dist/goal/goalStatus.d.ts +2 -0
  46. package/dist/goal/goalStatus.js +10 -3
  47. package/dist/goal/goalStore.d.ts +9 -2
  48. package/dist/goal/goalStore.js +152 -45
  49. package/dist/goal/handoffExport.js +6 -6
  50. package/dist/goal/specKitImport.js +97 -96
  51. package/dist/goal/subgoalSync.js +11 -9
  52. package/dist/goal/worktreeManager.d.ts +2 -0
  53. package/dist/goal/worktreeManager.js +209 -136
  54. package/dist/httpServer.js +111 -32
  55. package/dist/logging.js +5 -3
  56. package/dist/policy/projectPolicy.js +5 -2
  57. package/dist/release/releaseGate.d.ts +1 -1
  58. package/dist/release/releaseGate.js +78 -25
  59. package/dist/runner/agentInvocation.d.ts +14 -0
  60. package/dist/runner/agentInvocation.js +96 -4
  61. package/dist/runner/changeCapture.d.ts +13 -5
  62. package/dist/runner/changeCapture.js +243 -61
  63. package/dist/runner/postTaskCleanup.js +48 -19
  64. package/dist/runner/processSecurity.d.ts +56 -0
  65. package/dist/runner/processSecurity.js +373 -0
  66. package/dist/runner/runTask.d.ts +1 -1
  67. package/dist/runner/runTask.js +115 -87
  68. package/dist/runner/simpleProcess.d.ts +3 -0
  69. package/dist/runner/simpleProcess.js +50 -36
  70. package/dist/{taskProgress.d.ts → runner/taskProgress.d.ts} +1 -1
  71. package/dist/{taskProgress.js → runner/taskProgress.js} +2 -2
  72. package/dist/{taskRuntime.d.ts → runner/taskRuntime.d.ts} +1 -1
  73. package/dist/{taskRuntime.js → runner/taskRuntime.js} +3 -2
  74. package/dist/runner/taskStatusStore.d.ts +11 -0
  75. package/dist/runner/taskStatusStore.js +24 -0
  76. package/dist/runner/watch.d.ts +14 -1
  77. package/dist/runner/watch.js +256 -48
  78. package/dist/security/contentRedaction.js +2 -2
  79. package/dist/security/discoveryTokenStore.d.ts +3 -2
  80. package/dist/security/discoveryTokenStore.js +17 -2
  81. package/dist/security/loopbackHost.d.ts +2 -0
  82. package/dist/security/loopbackHost.js +16 -0
  83. package/dist/security/pathGuard.js +32 -17
  84. package/dist/security/planGuard.js +2 -1
  85. package/dist/security/runtimeGuard.js +9 -6
  86. package/dist/security/secretComparison.d.ts +3 -0
  87. package/dist/security/secretComparison.js +11 -0
  88. package/dist/security/sensitiveGuard.d.ts +5 -0
  89. package/dist/security/sensitiveGuard.js +27 -8
  90. package/dist/security/toolInvocationGuard.d.ts +2 -2
  91. package/dist/security/toolInvocationGuard.js +1 -1
  92. package/dist/security/workspaceRootGuard.d.ts +8 -0
  93. package/dist/security/workspaceRootGuard.js +47 -0
  94. package/dist/smoke-test.js +24 -23
  95. package/dist/tools/catalog/index.d.ts +4 -0
  96. package/dist/tools/catalog/index.js +4 -0
  97. package/dist/tools/{toolCatalog.js → catalog/toolCatalog.js} +3 -12
  98. package/dist/tools/{toolRegistry.d.ts → catalog/toolRegistry.d.ts} +3 -3
  99. package/dist/tools/{toolRegistry.js → catalog/toolRegistry.js} +6 -15
  100. package/dist/tools/definitions/toolDefs.d.ts +18 -0
  101. package/dist/tools/definitions/toolDefs.js +1177 -0
  102. package/dist/tools/{auditSession.d.ts → diagnostics/auditSession.d.ts} +1 -1
  103. package/dist/tools/{auditSession.js → diagnostics/auditSession.js} +2 -2
  104. package/dist/tools/{auditTask.d.ts → diagnostics/auditTask.d.ts} +1 -1
  105. package/dist/tools/{auditTask.js → diagnostics/auditTask.js} +99 -29
  106. package/dist/tools/{healthCheck.d.ts → diagnostics/healthCheck.d.ts} +6 -6
  107. package/dist/tools/{healthCheck.js → diagnostics/healthCheck.js} +7 -7
  108. package/dist/tools/diagnostics/index.d.ts +6 -0
  109. package/dist/tools/diagnostics/index.js +6 -0
  110. package/dist/tools/{safeStatus.d.ts → diagnostics/safeStatus.d.ts} +3 -3
  111. package/dist/tools/{safeStatus.js → diagnostics/safeStatus.js} +6 -6
  112. package/dist/tools/{safeViews.d.ts → diagnostics/safeViews.d.ts} +12 -8
  113. package/dist/tools/{safeViews.js → diagnostics/safeViews.js} +23 -13
  114. package/dist/tools/{schemaDriftCheck.d.ts → diagnostics/schemaDriftCheck.d.ts} +1 -1
  115. package/dist/tools/{schemaDriftCheck.js → diagnostics/schemaDriftCheck.js} +2 -2
  116. package/dist/tools/{createDirectSession.js → direct/createDirectSession.js} +6 -6
  117. package/dist/tools/{finalizeDirectSession.d.ts → direct/finalizeDirectSession.d.ts} +1 -1
  118. package/dist/tools/direct/finalizeDirectSession.js +86 -0
  119. package/dist/tools/direct/index.d.ts +3 -0
  120. package/dist/tools/direct/index.js +3 -0
  121. package/dist/tools/{runDirectVerificationBundle.js → direct/runDirectVerificationBundle.js} +2 -2
  122. package/dist/tools/{discoverTools.d.ts → discovery/discoverTools.d.ts} +2 -2
  123. package/dist/tools/{discoverTools.js → discovery/discoverTools.js} +5 -5
  124. package/dist/tools/{explainTool.d.ts → discovery/explainTool.d.ts} +2 -2
  125. package/dist/tools/{explainTool.js → discovery/explainTool.js} +2 -2
  126. package/dist/tools/discovery/index.d.ts +3 -0
  127. package/dist/tools/discovery/index.js +3 -0
  128. package/dist/tools/{invokeDiscoveredTool.d.ts → discovery/invokeDiscoveredTool.d.ts} +2 -2
  129. package/dist/tools/{invokeDiscoveredTool.js → discovery/invokeDiscoveredTool.js} +5 -5
  130. package/dist/tools/dispatch/coreDispatch.js +32 -31
  131. package/dist/tools/dispatch/diagnosticDispatch.d.ts +3 -5
  132. package/dist/tools/dispatch/diagnosticDispatch.js +70 -68
  133. package/dist/tools/dispatch/directDispatch.js +11 -10
  134. package/dist/tools/dispatch/goalDispatch.js +5 -4
  135. package/dist/tools/dispatch/releaseDispatch.js +3 -2
  136. package/dist/tools/dispatch/validation.d.ts +7 -0
  137. package/dist/tools/dispatch/validation.js +71 -0
  138. package/dist/tools/{getPlan.js → goals/getPlan.js} +4 -4
  139. package/dist/tools/{goalSubgoalTask.d.ts → goals/goalSubgoalTask.d.ts} +1 -1
  140. package/dist/tools/goals/goalSubgoalTask.js +118 -0
  141. package/dist/tools/goals/index.d.ts +3 -0
  142. package/dist/tools/goals/index.js +3 -0
  143. package/dist/tools/{savePlan.js → goals/savePlan.js} +28 -8
  144. package/dist/tools/registry.d.ts +7 -11
  145. package/dist/tools/registry.js +17 -1178
  146. package/dist/tools/{checkReleaseGate.d.ts → release/checkReleaseGate.d.ts} +1 -1
  147. package/dist/tools/{checkReleaseGate.js → release/checkReleaseGate.js} +3 -3
  148. package/dist/tools/release/index.d.ts +2 -0
  149. package/dist/tools/release/index.js +2 -0
  150. package/dist/tools/{releaseMode.d.ts → release/releaseMode.d.ts} +2 -2
  151. package/dist/tools/{releaseMode.js → release/releaseMode.js} +46 -26
  152. package/dist/tools/tasks/cancelTask.d.ts +11 -0
  153. package/dist/tools/tasks/cancelTask.js +85 -0
  154. package/dist/tools/{createTask.d.ts → tasks/createTask.d.ts} +10 -2
  155. package/dist/tools/{createTask.js → tasks/createTask.js} +42 -27
  156. package/dist/tools/{diagnoseTask.d.ts → tasks/diagnoseTask.d.ts} +1 -1
  157. package/dist/tools/{diagnoseTask.js → tasks/diagnoseTask.js} +8 -8
  158. package/dist/tools/{evidencePack.js → tasks/evidencePack.js} +34 -22
  159. package/dist/tools/{getTaskFile.js → tasks/getTaskFile.js} +4 -4
  160. package/dist/tools/{getTaskStatus.d.ts → tasks/getTaskStatus.d.ts} +6 -1
  161. package/dist/tools/{getTaskStatus.js → tasks/getTaskStatus.js} +5 -5
  162. package/dist/tools/{getTaskStdoutTail.js → tasks/getTaskStdoutTail.js} +13 -11
  163. package/dist/tools/{getTaskSummary.js → tasks/getTaskSummary.js} +33 -26
  164. package/dist/tools/tasks/index.d.ts +18 -0
  165. package/dist/tools/tasks/index.js +18 -0
  166. package/dist/tools/tasks/killTask.d.ts +1 -0
  167. package/dist/tools/{listTasks.d.ts → tasks/listTasks.d.ts} +1 -1
  168. package/dist/tools/{listTasks.js → tasks/listTasks.js} +3 -3
  169. package/dist/tools/{reconcileTasks.d.ts → tasks/reconcileTasks.d.ts} +1 -1
  170. package/dist/tools/{reconcileTasks.js → tasks/reconcileTasks.js} +64 -66
  171. package/dist/tools/tasks/retryTask.js +60 -0
  172. package/dist/tools/{runTaskLoop.d.ts → tasks/runTaskLoop.d.ts} +6 -6
  173. package/dist/tools/{runTaskLoop.js → tasks/runTaskLoop.js} +58 -30
  174. package/dist/tools/tasks/runVerification.js +38 -0
  175. package/dist/tools/{taskLineage.js → tasks/taskLineage.js} +8 -7
  176. package/dist/tools/{taskOutputs.js → tasks/taskOutputs.js} +17 -16
  177. package/dist/tools/{androidDoctor.js → workspace/androidDoctor.js} +16 -10
  178. package/dist/tools/{applyPatch.d.ts → workspace/applyPatch.d.ts} +1 -1
  179. package/dist/tools/workspace/applyPatch.js +53 -0
  180. package/dist/tools/{discardWorktree.js → workspace/discardWorktree.js} +3 -3
  181. package/dist/tools/workspace/index.d.ts +10 -0
  182. package/dist/tools/workspace/index.js +10 -0
  183. package/dist/tools/{listAgents.d.ts → workspace/listAgents.d.ts} +5 -0
  184. package/dist/tools/{listAgents.js → workspace/listAgents.js} +8 -4
  185. package/dist/tools/{listWorkspace.js → workspace/listWorkspace.js} +3 -3
  186. package/dist/tools/{mergeWorktree.js → workspace/mergeWorktree.js} +3 -3
  187. package/dist/tools/{readWorkspaceFile.js → workspace/readWorkspaceFile.js} +8 -8
  188. package/dist/tools/{recommendAgentForTask.js → workspace/recommendAgentForTask.js} +3 -3
  189. package/dist/tools/{searchWorkspace.js → workspace/searchWorkspace.js} +5 -5
  190. package/dist/tools/{syncFile.d.ts → workspace/syncFile.d.ts} +1 -1
  191. package/dist/tools/workspace/syncFile.js +134 -0
  192. package/dist/utils/atomicFile.d.ts +7 -0
  193. package/dist/utils/atomicFile.js +48 -0
  194. package/dist/utils/boundedFile.d.ts +8 -0
  195. package/dist/utils/boundedFile.js +93 -0
  196. package/dist/utils/lockedJsonFile.d.ts +15 -0
  197. package/dist/utils/lockedJsonFile.js +224 -0
  198. package/dist/utils/platform.d.ts +11 -0
  199. package/dist/utils/platform.js +26 -0
  200. package/dist/utils/stableJson.d.ts +2 -0
  201. package/dist/utils/stableJson.js +12 -0
  202. package/dist/version.d.ts +3 -2
  203. package/dist/version.js +3 -2
  204. package/dist/watcherStatus.d.ts +2 -2
  205. package/dist/watcherStatus.js +18 -0
  206. package/docs/CODE_WIKI.md +808 -143
  207. package/docs/architecture.md +15 -55
  208. package/docs/assets/patchwarden-desktop-onboarding.png +0 -0
  209. package/docs/control-center/README.md +4 -4
  210. package/docs/dashboard-overview.md +4 -4
  211. package/docs/desktop-app.md +175 -0
  212. package/docs/evidence-pack-schema.md +3 -3
  213. package/docs/open-source-application.md +17 -11
  214. package/docs/release-checklist.md +1 -1
  215. package/docs/release-evidence.md +39 -29
  216. package/docs/task-safe-review-workflow.md +5 -5
  217. package/docs/threat-model.md +19 -1
  218. package/examples/config.example.json +4 -2
  219. package/package.json +27 -10
  220. package/scripts/README.md +15 -6
  221. package/scripts/build.js +11 -0
  222. package/scripts/checks/brand-check.js +3 -0
  223. package/scripts/checks/build-output-check.js +37 -0
  224. package/scripts/checks/control-center-smoke.js +91 -6
  225. package/scripts/checks/control-smoke.js +19 -8
  226. package/scripts/checks/http-mcp-smoke.js +82 -4
  227. package/scripts/checks/lifecycle-smoke.js +10 -10
  228. package/scripts/checks/mcp-manifest-check.js +1 -1
  229. package/scripts/checks/mcp-smoke.js +27 -3
  230. package/scripts/checks/package-manifest-check.js +20 -7
  231. package/scripts/checks/unit-tests.js +3 -5
  232. package/scripts/checks/watcher-supervisor-smoke.js +9 -0
  233. package/scripts/control/get-patchwarden-health.ps1 +1 -1
  234. package/scripts/control/manage-patchwarden.ps1 +69 -4
  235. package/scripts/control/provision-patchwarden-tunnel.ps1 +127 -0
  236. package/scripts/control/run-background-supervisor.ps1 +41 -0
  237. package/scripts/control/start-patchwarden-tunnel.ps1 +126 -32
  238. package/{PatchWarden-Control-Tray.cmd → scripts/launchers/PatchWarden-Control-Tray.cmd} +3 -3
  239. package/scripts/launchers/PatchWarden-Control.cmd +6 -0
  240. package/{PatchWarden-Desktop.cmd → scripts/launchers/PatchWarden-Desktop.cmd} +2 -2
  241. package/scripts/launchers/Restart-PatchWarden-Control.cmd +6 -0
  242. package/{Stop-PatchWarden.cmd → scripts/launchers/Stop-PatchWarden.cmd} +2 -2
  243. package/scripts/lib/clean-generated-output.js +11 -0
  244. package/scripts/lib/file-discovery.js +12 -0
  245. package/scripts/release/desktop-preflight.js +211 -0
  246. package/scripts/release/pack-clean.js +59 -14
  247. package/src/assessments/agentAssessor.ts +26 -12
  248. package/src/assessments/assessmentStore.ts +52 -40
  249. package/src/config.ts +70 -13
  250. package/src/control/fileManager.ts +40 -0
  251. package/src/control/middleware/auth.ts +22 -4
  252. package/src/control/middleware/static.ts +16 -3
  253. package/src/control/routeTable.ts +301 -0
  254. package/src/control/routes/audit.ts +14 -6
  255. package/src/control/routes/evidence.ts +1 -1
  256. package/src/control/routes/lineage.ts +1 -1
  257. package/src/control/routes/process.ts +341 -40
  258. package/src/control/routes/sessions.ts +88 -25
  259. package/src/control/routes/status.ts +97 -17
  260. package/src/control/routes/taskActions.ts +24 -58
  261. package/src/control/routes/tasks.ts +66 -58
  262. package/src/control/routes/workspace.ts +56 -25
  263. package/src/control/runtime.ts +69 -33
  264. package/src/control/server.ts +36 -342
  265. package/src/control/shared.ts +77 -11
  266. package/src/direct/directAudit.ts +17 -9
  267. package/src/direct/directGuards.ts +72 -44
  268. package/src/direct/directPatch.ts +95 -8
  269. package/src/direct/directSessionStore.ts +211 -55
  270. package/src/direct/directVerification.ts +9 -23
  271. package/src/doctor.ts +73 -59
  272. package/src/goal/acceptanceEngine.ts +1 -1
  273. package/src/goal/goalProgress.ts +17 -13
  274. package/src/goal/goalReport.ts +5 -13
  275. package/src/goal/goalStatus.ts +19 -3
  276. package/src/goal/goalStore.ts +241 -54
  277. package/src/goal/handoffExport.ts +6 -6
  278. package/src/goal/specKitImport.ts +12 -12
  279. package/src/goal/subgoalSync.ts +11 -8
  280. package/src/goal/worktreeManager.ts +139 -22
  281. package/src/httpServer.ts +113 -30
  282. package/src/logging.ts +10 -3
  283. package/src/policy/projectPolicy.ts +5 -2
  284. package/src/release/releaseGate.ts +74 -27
  285. package/src/runner/agentInvocation.ts +126 -4
  286. package/src/runner/changeCapture.ts +291 -57
  287. package/src/runner/postTaskCleanup.ts +41 -17
  288. package/src/runner/processSecurity.ts +433 -0
  289. package/src/runner/runTask.ts +138 -91
  290. package/src/runner/simpleProcess.ts +66 -31
  291. package/src/{taskProgress.ts → runner/taskProgress.ts} +3 -3
  292. package/src/{taskRuntime.ts → runner/taskRuntime.ts} +4 -3
  293. package/src/runner/taskStatusStore.ts +54 -0
  294. package/src/runner/watch.ts +281 -51
  295. package/src/security/contentRedaction.ts +2 -2
  296. package/src/security/discoveryTokenStore.ts +18 -4
  297. package/src/security/loopbackHost.ts +19 -0
  298. package/src/security/pathGuard.ts +35 -16
  299. package/src/security/planGuard.ts +2 -1
  300. package/src/security/runtimeGuard.ts +9 -6
  301. package/src/security/secretComparison.ts +13 -0
  302. package/src/security/sensitiveGuard.ts +27 -8
  303. package/src/security/toolInvocationGuard.ts +2 -2
  304. package/src/security/workspaceRootGuard.ts +53 -0
  305. package/src/smoke-test.ts +25 -24
  306. package/src/tools/catalog/index.ts +4 -0
  307. package/src/tools/{toolCatalog.ts → catalog/toolCatalog.ts} +3 -12
  308. package/src/tools/{toolRegistry.ts → catalog/toolRegistry.ts} +7 -16
  309. package/src/tools/definitions/toolDefs.ts +1264 -0
  310. package/src/tools/{auditSession.ts → diagnostics/auditSession.ts} +2 -2
  311. package/src/tools/{auditTask.ts → diagnostics/auditTask.ts} +99 -32
  312. package/src/tools/{healthCheck.ts → diagnostics/healthCheck.ts} +8 -8
  313. package/src/tools/diagnostics/index.ts +6 -0
  314. package/src/tools/{safeStatus.ts → diagnostics/safeStatus.ts} +7 -7
  315. package/src/tools/{safeViews.ts → diagnostics/safeViews.ts} +27 -17
  316. package/src/tools/{schemaDriftCheck.ts → diagnostics/schemaDriftCheck.ts} +3 -3
  317. package/src/tools/{createDirectSession.ts → direct/createDirectSession.ts} +6 -6
  318. package/src/tools/{finalizeDirectSession.ts → direct/finalizeDirectSession.ts} +7 -5
  319. package/src/tools/direct/index.ts +3 -0
  320. package/src/tools/{runDirectVerificationBundle.ts → direct/runDirectVerificationBundle.ts} +2 -2
  321. package/src/tools/{discoverTools.ts → discovery/discoverTools.ts} +6 -6
  322. package/src/tools/{explainTool.ts → discovery/explainTool.ts} +3 -3
  323. package/src/tools/discovery/index.ts +3 -0
  324. package/src/tools/{invokeDiscoveredTool.ts → discovery/invokeDiscoveredTool.ts} +7 -7
  325. package/src/tools/dispatch/coreDispatch.ts +36 -31
  326. package/src/tools/dispatch/diagnosticDispatch.ts +26 -21
  327. package/src/tools/dispatch/directDispatch.ts +11 -10
  328. package/src/tools/dispatch/goalDispatch.ts +5 -4
  329. package/src/tools/dispatch/releaseDispatch.ts +3 -2
  330. package/src/tools/dispatch/validation.ts +78 -0
  331. package/src/tools/{getPlan.ts → goals/getPlan.ts} +4 -4
  332. package/src/tools/{goalSubgoalTask.ts → goals/goalSubgoalTask.ts} +41 -26
  333. package/src/tools/goals/index.ts +3 -0
  334. package/src/tools/{savePlan.ts → goals/savePlan.ts} +38 -8
  335. package/src/tools/registry.ts +17 -1261
  336. package/src/tools/{checkReleaseGate.ts → release/checkReleaseGate.ts} +3 -3
  337. package/src/tools/release/index.ts +2 -0
  338. package/src/tools/{releaseMode.ts → release/releaseMode.ts} +42 -24
  339. package/src/tools/tasks/cancelTask.ts +109 -0
  340. package/src/tools/{createTask.ts → tasks/createTask.ts} +49 -26
  341. package/src/tools/{diagnoseTask.ts → tasks/diagnoseTask.ts} +8 -8
  342. package/src/tools/{evidencePack.ts → tasks/evidencePack.ts} +36 -22
  343. package/src/tools/{getTaskFile.ts → tasks/getTaskFile.ts} +4 -4
  344. package/src/tools/{getTaskStatus.ts → tasks/getTaskStatus.ts} +7 -5
  345. package/src/tools/{getTaskStdoutTail.ts → tasks/getTaskStdoutTail.ts} +13 -11
  346. package/src/tools/{getTaskSummary.ts → tasks/getTaskSummary.ts} +44 -33
  347. package/src/tools/tasks/index.ts +18 -0
  348. package/src/tools/{listTasks.ts → tasks/listTasks.ts} +4 -4
  349. package/src/tools/{reconcileTasks.ts → tasks/reconcileTasks.ts} +68 -66
  350. package/src/tools/tasks/retryTask.ts +69 -0
  351. package/src/tools/{runTaskLoop.ts → tasks/runTaskLoop.ts} +69 -34
  352. package/src/tools/{runVerification.ts → tasks/runVerification.ts} +6 -3
  353. package/src/tools/{taskLineage.ts → tasks/taskLineage.ts} +8 -7
  354. package/src/tools/{taskOutputs.ts → tasks/taskOutputs.ts} +27 -20
  355. package/src/tools/{androidDoctor.ts → workspace/androidDoctor.ts} +15 -10
  356. package/src/tools/{applyPatch.ts → workspace/applyPatch.ts} +38 -16
  357. package/src/tools/{discardWorktree.ts → workspace/discardWorktree.ts} +3 -3
  358. package/src/tools/workspace/index.ts +10 -0
  359. package/src/tools/{listAgents.ts → workspace/listAgents.ts} +11 -4
  360. package/src/tools/{listWorkspace.ts → workspace/listWorkspace.ts} +3 -3
  361. package/src/tools/{mergeWorktree.ts → workspace/mergeWorktree.ts} +3 -3
  362. package/src/tools/{readWorkspaceFile.ts → workspace/readWorkspaceFile.ts} +8 -8
  363. package/src/tools/{recommendAgentForTask.ts → workspace/recommendAgentForTask.ts} +3 -3
  364. package/src/tools/{searchWorkspace.ts → workspace/searchWorkspace.ts} +5 -5
  365. package/src/tools/workspace/syncFile.ts +292 -0
  366. package/src/utils/atomicFile.ts +58 -0
  367. package/src/utils/boundedFile.ts +116 -0
  368. package/src/utils/lockedJsonFile.ts +251 -0
  369. package/src/utils/platform.ts +31 -0
  370. package/src/utils/stableJson.ts +12 -0
  371. package/src/version.ts +3 -2
  372. package/src/watcherStatus.ts +19 -1
  373. package/ui/desktop-bootstrap.js +11 -0
  374. package/ui/desktop-bridge.js +36 -0
  375. package/ui/desktop.css +160 -0
  376. package/ui/getting-started.js +93 -0
  377. package/ui/i18n.js +484 -0
  378. package/ui/log-parser.js +30 -0
  379. package/ui/pages/audit.html +12 -0
  380. package/ui/pages/dashboard.html +90 -147
  381. package/ui/pages/direct-sessions.html +123 -26
  382. package/ui/pages/getting-started.html +43 -0
  383. package/ui/pages/logs.html +105 -22
  384. package/ui/pages/settings.html +101 -0
  385. package/ui/pages/task-detail.html +12 -0
  386. package/ui/pages/tasks.html +54 -8
  387. package/ui/pages/workspace.html +38 -1
  388. package/ui/settings.js +245 -0
  389. package/PatchWarden-Control.cmd +0 -6
  390. package/Restart-PatchWarden-Control.cmd +0 -6
  391. package/dist/test/unit/acceptance-engine.test.d.ts +0 -1
  392. package/dist/test/unit/acceptance-engine.test.js +0 -228
  393. package/dist/test/unit/agent-router.test.d.ts +0 -1
  394. package/dist/test/unit/agent-router.test.js +0 -287
  395. package/dist/test/unit/android-doctor.test.d.ts +0 -1
  396. package/dist/test/unit/android-doctor.test.js +0 -118
  397. package/dist/test/unit/apply-patch.test.d.ts +0 -1
  398. package/dist/test/unit/apply-patch.test.js +0 -225
  399. package/dist/test/unit/audit-checks.test.d.ts +0 -1
  400. package/dist/test/unit/audit-checks.test.js +0 -350
  401. package/dist/test/unit/chinese-path.test.d.ts +0 -1
  402. package/dist/test/unit/chinese-path.test.js +0 -91
  403. package/dist/test/unit/command-guard.test.d.ts +0 -1
  404. package/dist/test/unit/command-guard.test.js +0 -160
  405. package/dist/test/unit/create-task.test.d.ts +0 -1
  406. package/dist/test/unit/create-task.test.js +0 -197
  407. package/dist/test/unit/diagnose-task.test.d.ts +0 -1
  408. package/dist/test/unit/diagnose-task.test.js +0 -457
  409. package/dist/test/unit/direct-guards.test.d.ts +0 -1
  410. package/dist/test/unit/direct-guards.test.js +0 -328
  411. package/dist/test/unit/discovery-token-store.test.d.ts +0 -1
  412. package/dist/test/unit/discovery-token-store.test.js +0 -139
  413. package/dist/test/unit/evidence-pack.test.d.ts +0 -1
  414. package/dist/test/unit/evidence-pack.test.js +0 -224
  415. package/dist/test/unit/get-task-status.test.d.ts +0 -1
  416. package/dist/test/unit/get-task-status.test.js +0 -174
  417. package/dist/test/unit/get-task-summary.test.d.ts +0 -1
  418. package/dist/test/unit/get-task-summary.test.js +0 -146
  419. package/dist/test/unit/goal-graph.test.d.ts +0 -1
  420. package/dist/test/unit/goal-graph.test.js +0 -298
  421. package/dist/test/unit/goal-progress.test.d.ts +0 -1
  422. package/dist/test/unit/goal-progress.test.js +0 -381
  423. package/dist/test/unit/goal-report.test.d.ts +0 -1
  424. package/dist/test/unit/goal-report.test.js +0 -159
  425. package/dist/test/unit/goal-status.test.d.ts +0 -1
  426. package/dist/test/unit/goal-status.test.js +0 -215
  427. package/dist/test/unit/goal-store.test.d.ts +0 -1
  428. package/dist/test/unit/goal-store.test.js +0 -253
  429. package/dist/test/unit/goal-subgoal-task.test.d.ts +0 -1
  430. package/dist/test/unit/goal-subgoal-task.test.js +0 -55
  431. package/dist/test/unit/goal-tools-registry.test.d.ts +0 -1
  432. package/dist/test/unit/goal-tools-registry.test.js +0 -192
  433. package/dist/test/unit/handoff-export.test.d.ts +0 -1
  434. package/dist/test/unit/handoff-export.test.js +0 -263
  435. package/dist/test/unit/invoke-discovered-tool.test.d.ts +0 -1
  436. package/dist/test/unit/invoke-discovered-tool.test.js +0 -167
  437. package/dist/test/unit/logging.test.d.ts +0 -1
  438. package/dist/test/unit/logging.test.js +0 -397
  439. package/dist/test/unit/path-guard.test.d.ts +0 -1
  440. package/dist/test/unit/path-guard.test.js +0 -133
  441. package/dist/test/unit/post-task-cleanup.test.d.ts +0 -1
  442. package/dist/test/unit/post-task-cleanup.test.js +0 -48
  443. package/dist/test/unit/project-policy-release-mode.test.d.ts +0 -1
  444. package/dist/test/unit/project-policy-release-mode.test.js +0 -125
  445. package/dist/test/unit/reconcile-tasks.test.d.ts +0 -1
  446. package/dist/test/unit/reconcile-tasks.test.js +0 -456
  447. package/dist/test/unit/release-gate.test.d.ts +0 -1
  448. package/dist/test/unit/release-gate.test.js +0 -242
  449. package/dist/test/unit/run-task-loop.test.d.ts +0 -1
  450. package/dist/test/unit/run-task-loop.test.js +0 -380
  451. package/dist/test/unit/safe-status.test.d.ts +0 -1
  452. package/dist/test/unit/safe-status.test.js +0 -165
  453. package/dist/test/unit/safe-views.test.d.ts +0 -1
  454. package/dist/test/unit/safe-views.test.js +0 -171
  455. package/dist/test/unit/schema-drift-check.test.d.ts +0 -1
  456. package/dist/test/unit/schema-drift-check.test.js +0 -176
  457. package/dist/test/unit/sensitive-guard.test.d.ts +0 -1
  458. package/dist/test/unit/sensitive-guard.test.js +0 -104
  459. package/dist/test/unit/spec-kit-import.test.d.ts +0 -1
  460. package/dist/test/unit/spec-kit-import.test.js +0 -341
  461. package/dist/test/unit/subgoal-sync.test.d.ts +0 -1
  462. package/dist/test/unit/subgoal-sync.test.js +0 -183
  463. package/dist/test/unit/sync-file.test.d.ts +0 -1
  464. package/dist/test/unit/sync-file.test.js +0 -154
  465. package/dist/test/unit/tool-invocation-guard.test.d.ts +0 -1
  466. package/dist/test/unit/tool-invocation-guard.test.js +0 -432
  467. package/dist/test/unit/tool-usage-stats.test.d.ts +0 -1
  468. package/dist/test/unit/tool-usage-stats.test.js +0 -300
  469. package/dist/test/unit/toolSearch.test.d.ts +0 -1
  470. package/dist/test/unit/toolSearch.test.js +0 -571
  471. package/dist/test/unit/wait-for-task.test.d.ts +0 -1
  472. package/dist/test/unit/wait-for-task.test.js +0 -144
  473. package/dist/test/unit/watcher-status.test.d.ts +0 -1
  474. package/dist/test/unit/watcher-status.test.js +0 -169
  475. package/dist/test/unit/worktree-manager.test.d.ts +0 -1
  476. package/dist/test/unit/worktree-manager.test.js +0 -176
  477. package/dist/tools/applyPatch.js +0 -41
  478. package/dist/tools/cancelTask.d.ts +0 -30
  479. package/dist/tools/cancelTask.js +0 -64
  480. package/dist/tools/finalizeDirectSession.js +0 -84
  481. package/dist/tools/goalSubgoalTask.js +0 -110
  482. package/dist/tools/killTask.d.ts +0 -15
  483. package/dist/tools/retryTask.js +0 -45
  484. package/dist/tools/runVerification.js +0 -36
  485. package/dist/tools/syncFile.js +0 -65
  486. package/docs/control-center/control-center-daily-driver.md +0 -211
  487. package/docs/control-center/control-center-mvp.md +0 -205
  488. package/docs/control-center/control-center-phase2.md +0 -159
  489. package/docs/execution-plan-2026-07-09.md +0 -315
  490. package/docs/release-v0.6.0.md +0 -71
  491. package/docs/release-v0.6.1.md +0 -75
  492. package/docs/release-v0.6.4.md +0 -45
  493. package/docs/roadmap-execution-and-acceptance.md +0 -365
  494. package/src/test/unit/acceptance-engine.test.ts +0 -261
  495. package/src/test/unit/agent-router.test.ts +0 -342
  496. package/src/test/unit/android-doctor.test.ts +0 -158
  497. package/src/test/unit/apply-patch.test.ts +0 -293
  498. package/src/test/unit/audit-checks.test.ts +0 -567
  499. package/src/test/unit/chinese-path.test.ts +0 -106
  500. package/src/test/unit/command-guard.test.ts +0 -221
  501. package/src/test/unit/create-task.test.ts +0 -255
  502. package/src/test/unit/diagnose-task.test.ts +0 -544
  503. package/src/test/unit/direct-guards.test.ts +0 -467
  504. package/src/test/unit/discovery-token-store.test.ts +0 -181
  505. package/src/test/unit/evidence-pack.test.ts +0 -251
  506. package/src/test/unit/get-task-status.test.ts +0 -203
  507. package/src/test/unit/get-task-summary.test.ts +0 -173
  508. package/src/test/unit/goal-graph.test.ts +0 -347
  509. package/src/test/unit/goal-progress.test.ts +0 -538
  510. package/src/test/unit/goal-report.test.ts +0 -189
  511. package/src/test/unit/goal-status.test.ts +0 -270
  512. package/src/test/unit/goal-store.test.ts +0 -318
  513. package/src/test/unit/goal-subgoal-task.test.ts +0 -72
  514. package/src/test/unit/goal-tools-registry.test.ts +0 -245
  515. package/src/test/unit/handoff-export.test.ts +0 -295
  516. package/src/test/unit/invoke-discovered-tool.test.ts +0 -216
  517. package/src/test/unit/logging.test.ts +0 -497
  518. package/src/test/unit/path-guard.test.ts +0 -180
  519. package/src/test/unit/post-task-cleanup.test.ts +0 -53
  520. package/src/test/unit/project-policy-release-mode.test.ts +0 -156
  521. package/src/test/unit/reconcile-tasks.test.ts +0 -551
  522. package/src/test/unit/release-gate.test.ts +0 -314
  523. package/src/test/unit/run-task-loop.test.ts +0 -425
  524. package/src/test/unit/safe-status.test.ts +0 -187
  525. package/src/test/unit/safe-views.test.ts +0 -184
  526. package/src/test/unit/schema-drift-check.test.ts +0 -260
  527. package/src/test/unit/sensitive-guard.test.ts +0 -124
  528. package/src/test/unit/spec-kit-import.test.ts +0 -429
  529. package/src/test/unit/subgoal-sync.test.ts +0 -236
  530. package/src/test/unit/sync-file.test.ts +0 -231
  531. package/src/test/unit/tool-invocation-guard.test.ts +0 -542
  532. package/src/test/unit/tool-usage-stats.test.ts +0 -384
  533. package/src/test/unit/toolSearch.test.ts +0 -756
  534. package/src/test/unit/wait-for-task.test.ts +0 -176
  535. package/src/test/unit/watcher-status.test.ts +0 -190
  536. package/src/test/unit/worktree-manager.test.ts +0 -247
  537. package/src/tools/cancelTask.ts +0 -70
  538. package/src/tools/retryTask.ts +0 -53
  539. package/src/tools/syncFile.ts +0 -122
  540. /package/dist/tools/{toolCatalog.d.ts → catalog/toolCatalog.d.ts} +0 -0
  541. /package/dist/tools/{toolSearch.d.ts → catalog/toolSearch.d.ts} +0 -0
  542. /package/dist/tools/{toolSearch.js → catalog/toolSearch.js} +0 -0
  543. /package/dist/tools/{toolUsageStats.d.ts → catalog/toolUsageStats.d.ts} +0 -0
  544. /package/dist/tools/{toolUsageStats.js → catalog/toolUsageStats.js} +0 -0
  545. /package/dist/tools/{createDirectSession.d.ts → direct/createDirectSession.d.ts} +0 -0
  546. /package/dist/tools/{runDirectVerificationBundle.d.ts → direct/runDirectVerificationBundle.d.ts} +0 -0
  547. /package/dist/tools/{getPlan.d.ts → goals/getPlan.d.ts} +0 -0
  548. /package/dist/tools/{savePlan.d.ts → goals/savePlan.d.ts} +0 -0
  549. /package/dist/tools/{evidencePack.d.ts → tasks/evidencePack.d.ts} +0 -0
  550. /package/dist/tools/{getTaskFile.d.ts → tasks/getTaskFile.d.ts} +0 -0
  551. /package/dist/tools/{getTaskProgress.d.ts → tasks/getTaskProgress.d.ts} +0 -0
  552. /package/dist/tools/{getTaskProgress.js → tasks/getTaskProgress.js} +0 -0
  553. /package/dist/tools/{getTaskStdoutTail.d.ts → tasks/getTaskStdoutTail.d.ts} +0 -0
  554. /package/dist/tools/{getTaskSummary.d.ts → tasks/getTaskSummary.d.ts} +0 -0
  555. /package/dist/tools/{killTask.js → tasks/killTask.js} +0 -0
  556. /package/dist/tools/{retryTask.d.ts → tasks/retryTask.d.ts} +0 -0
  557. /package/dist/tools/{runVerification.d.ts → tasks/runVerification.d.ts} +0 -0
  558. /package/dist/tools/{taskLineage.d.ts → tasks/taskLineage.d.ts} +0 -0
  559. /package/dist/tools/{taskOutputs.d.ts → tasks/taskOutputs.d.ts} +0 -0
  560. /package/dist/tools/{waitForTask.d.ts → tasks/waitForTask.d.ts} +0 -0
  561. /package/dist/tools/{waitForTask.js → tasks/waitForTask.js} +0 -0
  562. /package/dist/tools/{androidDoctor.d.ts → workspace/androidDoctor.d.ts} +0 -0
  563. /package/dist/tools/{discardWorktree.d.ts → workspace/discardWorktree.d.ts} +0 -0
  564. /package/dist/tools/{listWorkspace.d.ts → workspace/listWorkspace.d.ts} +0 -0
  565. /package/dist/tools/{mergeWorktree.d.ts → workspace/mergeWorktree.d.ts} +0 -0
  566. /package/dist/tools/{readWorkspaceFile.d.ts → workspace/readWorkspaceFile.d.ts} +0 -0
  567. /package/dist/tools/{recommendAgentForTask.d.ts → workspace/recommendAgentForTask.d.ts} +0 -0
  568. /package/dist/tools/{searchWorkspace.d.ts → workspace/searchWorkspace.d.ts} +0 -0
  569. /package/src/tools/{toolSearch.ts → catalog/toolSearch.ts} +0 -0
  570. /package/src/tools/{toolUsageStats.ts → catalog/toolUsageStats.ts} +0 -0
  571. /package/src/tools/{getTaskProgress.ts → tasks/getTaskProgress.ts} +0 -0
  572. /package/src/tools/{killTask.ts → tasks/killTask.ts} +0 -0
  573. /package/src/tools/{waitForTask.ts → tasks/waitForTask.ts} +0 -0
@@ -1,14 +1,14 @@
1
1
  import { setTimeout as sleep } from "node:timers/promises";
2
- import { getConfig } from "../config.js";
3
- import { createWorktree } from "../goal/worktreeManager.js";
4
- import { guardWorkspacePath } from "../security/pathGuard.js";
5
- import { createDirectSession } from "./createDirectSession.js";
2
+ import { getConfig } from "../../config.js";
3
+ import { createWorktree } from "../../goal/worktreeManager.js";
4
+ import { guardWorkspacePath } from "../../security/pathGuard.js";
5
+ import { createDirectSession } from "../direct/createDirectSession.js";
6
6
  import { createTask, type CreateTaskInput } from "./createTask.js";
7
- import { recommendAgentForTask } from "./recommendAgentForTask.js";
8
- import { runDirectVerificationBundle } from "./runDirectVerificationBundle.js";
7
+ import { recommendAgentForTask } from "../workspace/recommendAgentForTask.js";
8
+ import { runDirectVerificationBundle } from "../direct/runDirectVerificationBundle.js";
9
9
  import { waitForTask } from "./waitForTask.js";
10
- import { safeAudit, safeAuditDirectSession, safeFinalizeDirectSession, safeResult, safeTestSummary } from "./safeViews.js";
11
- import type { TaskTemplateName } from "./taskTemplates.js";
10
+ import { safeAudit, safeAuditDirectSession, safeFinalizeDirectSession, safeResult, safeTestSummary } from "../diagnostics/safeViews.js";
11
+ import type { TaskTemplateName } from "../taskTemplates.js";
12
12
  import {
13
13
  createLineageId,
14
14
  writeTaskLineage,
@@ -202,18 +202,23 @@ export async function runTaskLoopWithDeps(
202
202
  timeout_seconds: normalized.task_timeout_seconds,
203
203
  execution_mode: "assess_only",
204
204
  };
205
- const assessment = await deps.createTask(assessmentInput as CreateTaskInput & { execution_mode: "assess_only" }) as any;
205
+ const assessment = asRecord(await deps.createTask(assessmentInput));
206
206
  if (assessment.decision === "blocked") {
207
- return finalize("blocked", "high_risk_blocked", "Risk assessment blocked task execution.", assessment.reason_codes?.join(", "));
207
+ return finalize(
208
+ "blocked",
209
+ "high_risk_blocked",
210
+ "Risk assessment blocked task execution.",
211
+ asArray(assessment.reason_codes).map(String).join(", "),
212
+ );
208
213
  }
209
214
  if (assessment.decision === "needs_confirm") {
210
215
  return finalize("blocked", "user_confirmation_required", "Ask the user to confirm the assessment before executing the loop.");
211
216
  }
212
217
 
213
- const created = await deps.createTask({
218
+ const created = asRecord(await deps.createTask({
214
219
  execution_mode: "execute",
215
220
  assessment_id: String(assessment.assessment_id || ""),
216
- }) as any;
221
+ }));
217
222
  const taskId = String(created.task_id || "");
218
223
  if (!taskId) {
219
224
  return finalize("failed", "policy_blocked", "create_task returned no task_id.", "create_task returned no task_id");
@@ -226,9 +231,9 @@ export async function runTaskLoopWithDeps(
226
231
  return finalize("blocked", wait.stop_reason, wait.next_action, wait.error);
227
232
  }
228
233
 
229
- const result = deps.safeResult(taskId, { max_items: 8 }) as any;
230
- const tests = deps.safeTestSummary(taskId) as any;
231
- const audit = deps.safeAudit(taskId, { max_items: 8 }) as any;
234
+ const result = asRecord(deps.safeResult(taskId, { max_items: 8 }));
235
+ const tests = asRecord(deps.safeTestSummary(taskId));
236
+ const audit = asRecord(deps.safeAudit(taskId, { max_items: 8 }));
232
237
  const round = buildRound(iteration, taskId, role, result, tests, audit);
233
238
  lineage.rounds.push(round);
234
239
  lineage.updated_at = deps.now().toISOString();
@@ -267,7 +272,7 @@ async function waitUntilTerminal(
267
272
  ): Promise<{ stop_reason?: TaskLoopStopReason; next_action: string; error?: string }> {
268
273
  const deadline = Date.now() + timeoutSeconds * 1000;
269
274
  while (Date.now() < deadline) {
270
- const waited = await deps.waitForTask(taskId, 30) as any;
275
+ const waited = await deps.waitForTask(taskId, 30);
271
276
  if (waited.terminal || TERMINAL_STATUSES.has(String(waited.status))) {
272
277
  return { next_action: waited.next_action || "safe_audit" };
273
278
  }
@@ -291,23 +296,35 @@ function buildRound(
291
296
  iteration: number,
292
297
  taskId: string,
293
298
  role: TaskLineageRound["role"],
294
- result: any,
295
- tests: any,
296
- audit: any
299
+ resultValue: unknown,
300
+ testsValue: unknown,
301
+ auditValue: unknown,
297
302
  ): TaskLineageRound {
298
- const failChecks = Array.isArray(audit.fail_checks) ? audit.fail_checks.map((entry: any) => String(entry.name || entry)) : [];
299
- const warnChecks = Array.isArray(audit.warn_checks) ? audit.warn_checks.map((entry: any) => String(entry.name || entry)) : [];
303
+ const result = asRecord(resultValue);
304
+ const tests = asRecord(testsValue);
305
+ const audit = asRecord(auditValue);
306
+ const resultVerification = asRecord(result.verification);
307
+ const auditAcceptance = asRecord(audit.acceptance);
308
+ const failChecks = asArray(audit.fail_checks).map((entry) => {
309
+ const check = asRecord(entry);
310
+ return String(check.name || entry);
311
+ });
312
+ const warnChecks = asArray(audit.warn_checks).map((entry) => {
313
+ const check = asRecord(entry);
314
+ return String(check.name || entry);
315
+ });
316
+ const recommendedActions = asArray(audit.recommended_next_actions);
300
317
  return {
301
318
  iteration,
302
319
  task_id: taskId,
303
320
  role,
304
321
  status: String(result.status || "unknown"),
305
322
  terminal: Boolean(result.terminal),
306
- verification_status: String(tests.status || result.verification?.status || "not_available"),
307
- audit_verdict: String(audit.verdict || audit.acceptance?.verdict || "unknown"),
323
+ verification_status: String(tests.status || resultVerification.status || "not_available"),
324
+ audit_verdict: String(audit.verdict || auditAcceptance.verdict || "unknown"),
308
325
  fail_checks: failChecks,
309
326
  warn_checks: warnChecks,
310
- next_action: String(result.next_action || audit.recommended_next_actions?.[0] || "review_task"),
327
+ next_action: String(result.next_action || recommendedActions[0] || "review_task"),
311
328
  };
312
329
  }
313
330
 
@@ -322,21 +339,25 @@ function isSuccessfulRound(round: TaskLineageRound): boolean {
322
339
  );
323
340
  }
324
341
 
325
- function isHardStop(round: TaskLineageRound, result: any, audit: any, stopOnHighRisk: boolean): boolean {
342
+ function isHardStop(round: TaskLineageRound, resultValue: unknown, auditValue: unknown, stopOnHighRisk: boolean): boolean {
326
343
  if (["failed_scope_violation", "failed_policy_violation", "canceled"].includes(round.status)) return true;
327
344
  if (!stopOnHighRisk) return false;
328
345
  const checkNames = [...round.fail_checks, ...round.warn_checks].join(" ").toLowerCase();
329
- const reason = String(result.failure_reason || audit.acceptance?.reason || "").toLowerCase();
346
+ const result = asRecord(resultValue);
347
+ const audit = asRecord(auditValue);
348
+ const reason = String(result.failure_reason || asRecord(audit.acceptance).reason || "").toLowerCase();
330
349
  return /scope|secret|sensitive|publish|release|policy|push/.test(`${checkNames} ${reason}`);
331
350
  }
332
351
 
333
- function hardStopReason(round: TaskLineageRound, result: any): TaskLoopStopReason {
352
+ function hardStopReason(round: TaskLineageRound, resultValue: unknown): TaskLoopStopReason {
353
+ const result = asRecord(resultValue);
334
354
  if (round.status === "failed_scope_violation" || round.status === "failed_policy_violation") return "policy_blocked";
335
355
  if (String(result.failure_reason || "").toLowerCase().includes("timeout")) return "agent_timeout";
336
356
  return "high_risk_blocked";
337
357
  }
338
358
 
339
- function buildFixGoal(originalGoal: string, result: any, round: TaskLineageRound): string {
359
+ function buildFixGoal(originalGoal: string, resultValue: unknown, round: TaskLineageRound): string {
360
+ const result = asRecord(resultValue);
340
361
  const failedCommand = result.failed_command ? ` Failed command: ${result.failed_command}.` : "";
341
362
  return [
342
363
  `Fix the failing verification for this PatchWarden loop without changing unrelated behavior.`,
@@ -413,8 +434,12 @@ async function runDirectVerification(
413
434
  commands: normalized.direct_verify_commands,
414
435
  timeout_seconds: normalized.direct_verify_timeout_seconds,
415
436
  });
416
- const finalized = await deps.safeFinalizeDirectSession(sessionId, { max_items: 8 }) as any;
417
- const audit = deps.safeAuditDirectSession(sessionId, { max_items: 8 }) as any;
437
+ const finalized = asRecord(await deps.safeFinalizeDirectSession(sessionId, { max_items: 8 }));
438
+ const audit = asRecord(deps.safeAuditDirectSession(sessionId, { max_items: 8 }));
439
+ const auditEvidence = asRecord(audit.evidence);
440
+ const auditDecision = audit.decision === "pass" || audit.decision === "warn" || audit.decision === "fail"
441
+ ? audit.decision
442
+ : "not_run";
418
443
  const evidence: TaskLineageDirectSession = {
419
444
  session_id: sessionId,
420
445
  status: bundle.status,
@@ -422,8 +447,8 @@ async function runDirectVerification(
422
447
  passed_commands: bundle.passed_commands,
423
448
  failed_commands: bundle.failed_commands,
424
449
  timed_out_commands: bundle.timed_out_commands,
425
- audit_decision: audit.decision || "not_run",
426
- changed_files_total: Number(finalized.changed_files_total || audit.evidence?.changed_files_total || 0),
450
+ audit_decision: auditDecision,
451
+ changed_files_total: Number(finalized.changed_files_total || auditEvidence.changed_files_total || 0),
427
452
  next_action: String(audit.next_action || bundle.next_action || "review_direct_session"),
428
453
  };
429
454
  if (bundle.status !== "passed") {
@@ -435,7 +460,7 @@ async function runDirectVerification(
435
460
  error: "Direct verification failed.",
436
461
  };
437
462
  }
438
- if (audit.decision === "fail") {
463
+ if (auditDecision === "fail") {
439
464
  return {
440
465
  evidence,
441
466
  stop_reason: "direct_audit_failed",
@@ -448,7 +473,7 @@ async function runDirectVerification(
448
473
  evidence,
449
474
  final_status: "accepted",
450
475
  next_action: "accept",
451
- warning: audit.decision === "warn" ? "Direct audit completed with warnings." : undefined,
476
+ warning: auditDecision === "warn" ? "Direct audit completed with warnings." : undefined,
452
477
  };
453
478
  } catch (err) {
454
479
  const message = err instanceof Error ? err.message : String(err);
@@ -467,6 +492,16 @@ async function runDirectVerification(
467
492
  }
468
493
  }
469
494
 
495
+ function asRecord(value: unknown): Record<string, unknown> {
496
+ return value && typeof value === "object" && !Array.isArray(value)
497
+ ? value as Record<string, unknown>
498
+ : {};
499
+ }
500
+
501
+ function asArray(value: unknown): unknown[] {
502
+ return Array.isArray(value) ? value : [];
503
+ }
504
+
470
505
  function normalizeInput(input: RunTaskLoopInput): Required<Omit<RunTaskLoopInput, "agent" | "scope_files" | "worktree_base_branch">> & { agent?: string; scope_files?: string[]; worktree_base_branch?: string } {
471
506
  const config = getConfig();
472
507
  const repoPath = String(input.repo_path || "").trim();
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  readDirectSession,
3
3
  appendDirectSessionVerificationRun,
4
- } from "../direct/directSessionStore.js";
5
- import { guardDirectSessionActive } from "../direct/directGuards.js";
6
- import { runDirectVerification } from "../direct/directVerification.js";
4
+ withDirectSessionMutationLockAsync,
5
+ } from "../../direct/directSessionStore.js";
6
+ import { guardDirectSessionActive } from "../../direct/directGuards.js";
7
+ import { runDirectVerification } from "../../direct/directVerification.js";
7
8
 
8
9
  export interface RunVerificationInput {
9
10
  session_id: string;
@@ -29,6 +30,7 @@ export interface RunVerificationOutput {
29
30
  export async function runVerification(
30
31
  input: RunVerificationInput
31
32
  ): Promise<RunVerificationOutput> {
33
+ return withDirectSessionMutationLockAsync(input.session_id, async () => {
32
34
  // 1. Read session and guard active
33
35
  const session = readDirectSession(input.session_id);
34
36
  guardDirectSessionActive(session);
@@ -63,4 +65,5 @@ export async function runVerification(
63
65
  ? "Call finalize_direct_session to complete the session."
64
66
  : "Review the verification output and apply_patch to fix issues.",
65
67
  };
68
+ });
66
69
  }
@@ -1,10 +1,11 @@
1
1
  import { randomBytes } from "node:crypto";
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
3
3
  import { join, resolve } from "node:path";
4
- import { getConfig } from "../config.js";
5
- import { guardReadPath } from "../security/pathGuard.js";
6
- import { redactSensitiveValue } from "../security/contentRedaction.js";
7
- import { PatchWardenError } from "../errors.js";
4
+ import { getConfig } from "../../config.js";
5
+ import { guardReadPath } from "../../security/pathGuard.js";
6
+ import { redactSensitiveValue } from "../../security/contentRedaction.js";
7
+ import { PatchWardenError } from "../../errors.js";
8
+ import { atomicWriteFileSync, atomicWriteJsonFileSync } from "../../utils/atomicFile.js";
8
9
 
9
10
  export type TaskLoopStopReason =
10
11
  | "success"
@@ -119,8 +120,8 @@ export function writeTaskLineage(record: TaskLineageRecord): SafeTaskLineage {
119
120
  const lineageDir = resolve(config.workspaceRoot, ".patchwarden", "lineages", record.lineage_id);
120
121
  mkdirSync(lineageDir, { recursive: true });
121
122
  const safeRecord = redactSensitiveValue(record).value as TaskLineageRecord;
122
- writeFileSync(join(lineageDir, "lineage.json"), JSON.stringify(safeRecord, null, 2) + "\n", "utf-8");
123
- writeFileSync(join(lineageDir, "SUMMARY.md"), buildSummaryMarkdown(safeRecord), "utf-8");
123
+ atomicWriteJsonFileSync(join(lineageDir, "lineage.json"), safeRecord);
124
+ atomicWriteFileSync(join(lineageDir, "SUMMARY.md"), buildSummaryMarkdown(safeRecord));
124
125
  return toSafeTaskLineage(safeRecord);
125
126
  }
126
127
 
@@ -1,9 +1,13 @@
1
1
  import { getTaskFile, GetTaskFileOutput } from "./getTaskFile.js";
2
- import { existsSync, readFileSync, statSync } from "node:fs";
2
+ import { existsSync, statSync } from "node:fs";
3
3
  import { join, resolve } from "node:path";
4
- import { getConfig, getTasksDir } from "../config.js";
5
- import { guardPath } from "../security/pathGuard.js";
6
- import { redactSensitiveContent } from "../security/contentRedaction.js";
4
+ import { getConfig, getTasksDir } from "../../config.js";
5
+ import { guardPath } from "../../security/pathGuard.js";
6
+ import { redactSensitiveContent } from "../../security/contentRedaction.js";
7
+ import {
8
+ readTextFilePrefixSync,
9
+ readTextFileTailLinesSync,
10
+ } from "../../utils/boundedFile.js";
7
11
 
8
12
  export function getResult(taskId: string): GetTaskFileOutput {
9
13
  return getTaskFile(taskId, "result.md");
@@ -23,26 +27,25 @@ export function getDiff(taskId: string): GetTaskFileOutput {
23
27
  }
24
28
  const filePath = existsSync(preferred) ? preferred : fallback;
25
29
  guardPath(filePath, config.workspaceRoot, config.tasksDir);
26
- const size = statSync(filePath).size;
27
- const raw = readFileSync(filePath, "utf-8");
28
- const patchHead = raw.slice(0, config.maxReadFileBytes);
29
- const rawReturnedBytes = Buffer.byteLength(patchHead, "utf-8");
30
+ const bounded = readTextFilePrefixSync(filePath, config.maxReadFileBytes);
31
+ const size = bounded.totalBytes;
32
+ const patchHead = bounded.content;
30
33
  const redaction = redactSensitiveContent(patchHead);
31
34
  const content = redaction.content;
32
- const diff = {
35
+ const diff: GetTaskFileOutput & { truncated: boolean } = {
33
36
  task_id: taskId,
34
37
  filename: existsSync(preferred) ? "diff.patch" : "git.diff",
35
38
  content,
36
39
  path: filePath,
37
40
  available: true,
38
- truncated: size > rawReturnedBytes,
41
+ truncated: bounded.truncated,
39
42
  total_bytes: size,
40
43
  returned_bytes: Buffer.byteLength(content, "utf-8"),
41
44
  patch_head: content,
42
45
  diff_patch_path: filePath,
43
46
  redacted: redaction.redacted,
44
47
  redaction_categories: redaction.redaction_categories,
45
- } as GetTaskFileOutput;
48
+ } as GetTaskFileOutput & { truncated: boolean };
46
49
  try {
47
50
  const evidence = JSON.parse(getTaskFile(taskId, "changed-files.json").content);
48
51
  return {
@@ -51,7 +54,7 @@ export function getDiff(taskId: string): GetTaskFileOutput {
51
54
  diff_available: Boolean(evidence.diff_available),
52
55
  workspace_dirty_before: Boolean(evidence.workspace_dirty_before),
53
56
  workspace_dirty_after: Boolean(evidence.workspace_dirty_after),
54
- diff_truncated: Boolean(evidence.diff_truncated || (diff as any).truncated),
57
+ diff_truncated: Boolean(evidence.diff_truncated || diff.truncated),
55
58
  diff_size_bytes: Number(evidence.diff_size_bytes || size),
56
59
  additions: Number(evidence.additions || 0),
57
60
  deletions: Number(evidence.deletions || 0),
@@ -101,8 +104,7 @@ export function getTaskLogTail(
101
104
 
102
105
  const stat = statSync(filePath);
103
106
  const totalBytes = stat.size;
104
- const raw = readFileSync(filePath, "utf-8");
105
- const tail = raw.split("\n").slice(-maxLines).join("\n");
107
+ const tail = readTextFileTailLinesSync(filePath, maxLines);
106
108
  const content = applyRedact ? redactSensitiveContent(tail) : { content: tail, redacted: false, redaction_categories: [] as string[] };
107
109
 
108
110
  return {
@@ -134,13 +136,18 @@ function getTaskFileTail(
134
136
  }
135
137
 
136
138
  const stat = statSync(filePath);
137
- const raw = readFileSync(filePath, "utf-8");
138
- let content = raw;
139
+ const maxBytes = options.maxBytes > 0
140
+ ? Math.min(options.maxBytes, config.maxReadFileBytes)
141
+ : config.maxReadFileBytes;
142
+ let content: string;
139
143
  if (options.tailLines > 0) {
140
- content = raw.split("\n").slice(-options.tailLines).join("\n");
141
- }
142
- if (options.maxBytes > 0 && Buffer.byteLength(content, "utf-8") > options.maxBytes) {
143
- content = content.slice(0, options.maxBytes);
144
+ content = readTextFileTailLinesSync(
145
+ filePath,
146
+ Math.min(Math.max(1, options.tailLines), 1000),
147
+ maxBytes,
148
+ );
149
+ } else {
150
+ content = readTextFilePrefixSync(filePath, maxBytes).content;
144
151
  }
145
152
  const redaction = redactSensitiveContent(content);
146
153
  return {
@@ -8,9 +8,9 @@
8
8
  * and inspects files/directories/env vars that already exist.
9
9
  */
10
10
 
11
- import { execSync } from "node:child_process";
12
11
  import { existsSync, readFileSync, statSync } from "node:fs";
13
12
  import { join } from "node:path";
13
+ import { runSimpleProcessSync } from "../../runner/simpleProcess.js";
14
14
 
15
15
  // ── Types ──────────────────────────────────────────────────────────
16
16
 
@@ -47,17 +47,22 @@ const SDK_MISSING_REASON =
47
47
  // ── Helpers ────────────────────────────────────────────────────────
48
48
 
49
49
  /**
50
- * Run a shell command and return its trimmed combined stdout/stderr output.
50
+ * Run a shell-free command and return its trimmed combined stdout/stderr output.
51
51
  * Returns an empty string when the command is missing or fails so callers can
52
52
  * treat absence gracefully. A timeout guards against hanging processes.
53
53
  */
54
- function runCmd(cmdStr: string): string {
54
+ function runCmd(command: string, args: readonly string[], cwd = process.cwd()): string {
55
55
  try {
56
- return execSync(cmdStr, {
57
- encoding: "utf-8",
58
- timeout: 8000,
59
- stdio: ["ignore", "pipe", "ignore"],
60
- }).trim();
56
+ const result = runSimpleProcessSync({
57
+ command,
58
+ args: [...args],
59
+ cwd,
60
+ timeoutMs: 8000,
61
+ maxStdoutBytes: 64 * 1024,
62
+ maxStderrBytes: 64 * 1024,
63
+ });
64
+ if (result.exitCode !== 0) return "";
65
+ return `${result.stdout}\n${result.stderr}`.trim();
61
66
  } catch {
62
67
  return "";
63
68
  }
@@ -128,8 +133,8 @@ export function diagnoseAndroidBuild(repoPath: string): AndroidBuildDiagnostic {
128
133
  const sdkExists = sdkRoot !== "" && isDirectory(sdkRoot);
129
134
 
130
135
  // 1. java -version ------------------------------------------------------
131
- // `java -version` writes to stderr; redirect with 2>&1 so execSync captures it.
132
- const javaOutput = runCmd("java -version 2>&1");
136
+ // `java -version` normally writes to stderr; runSimpleProcessSync captures both.
137
+ const javaOutput = runCmd("java", ["-version"], repoPath);
133
138
  const javaVersion = parseJavaVersion(javaOutput);
134
139
  if (javaVersion) {
135
140
  const major = parseJavaMajor(javaVersion);
@@ -1,19 +1,20 @@
1
- import { getConfig } from "../config.js";
1
+ import { getConfig } from "../../config.js";
2
+ import { PatchWardenError } from "../../errors.js";
2
3
  import {
3
4
  readDirectSession,
4
5
  appendDirectSessionOperation,
5
- } from "../direct/directSessionStore.js";
6
+ withDirectSessionMutationLock,
7
+ } from "../../direct/directSessionStore.js";
6
8
  import {
7
9
  guardDirectSessionActive,
8
10
  guardDirectWritePath,
9
11
  guardDirectPatchSize,
10
- } from "../direct/directGuards.js";
12
+ } from "../../direct/directGuards.js";
11
13
  import {
12
14
  applyPatchOperations,
13
- validateExpectedSha256,
14
15
  computeFileSha256,
15
16
  type PatchOperation,
16
- } from "../direct/directPatch.js";
17
+ } from "../../direct/directPatch.js";
17
18
 
18
19
  export interface ApplyPatchInput {
19
20
  session_id: string;
@@ -33,6 +34,7 @@ export interface ApplyPatchOutput {
33
34
 
34
35
  export function applyPatch(input: ApplyPatchInput): ApplyPatchOutput {
35
36
  const config = getConfig();
37
+ return withDirectSessionMutationLock(input.session_id, () => {
36
38
 
37
39
  // 1. Read session and guard active (not expired, not finalized)
38
40
  const session = readDirectSession(input.session_id);
@@ -47,26 +49,45 @@ export function applyPatch(input: ApplyPatchInput): ApplyPatchOutput {
47
49
  );
48
50
 
49
51
  // 3. Calculate patch size and guard against directMaxPatchBytes
50
- const patchBytes = JSON.stringify(input.operations).length;
52
+ const patchBytes = Buffer.byteLength(JSON.stringify(input.operations), "utf-8");
51
53
  guardDirectPatchSize(patchBytes);
52
54
 
53
- // 4. Validate expected_sha256 matches current file hash
54
- const beforeSha256 = validateExpectedSha256(
55
- resolvedPath,
56
- input.expected_sha256
57
- );
58
-
59
- // 5. Apply patch operations
60
- const patchResult = applyPatchOperations(resolvedPath, input.operations);
55
+ // 4. Apply against the same bytes whose hash is validated. Re-resolve the
56
+ // target immediately before replacement to detect link/reparse-point swaps.
57
+ const patchResult = applyPatchOperations(resolvedPath, input.operations, {
58
+ expectedSha256: input.expected_sha256,
59
+ maxFileBytes: config.directMaxFileBytes,
60
+ revalidatePath: () => guardDirectWritePath(
61
+ input.path,
62
+ session.resolved_repo_path,
63
+ config.workspaceRoot,
64
+ ),
65
+ });
66
+ const beforeSha256 = patchResult.before_sha256;
61
67
 
62
68
  // Re-read the file from disk to compute the authoritative after_sha256
63
- const afterSha256 = computeFileSha256(resolvedPath);
69
+ const finalPath = guardDirectWritePath(
70
+ input.path,
71
+ session.resolved_repo_path,
72
+ config.workspaceRoot,
73
+ );
74
+ const afterSha256 = computeFileSha256(finalPath);
75
+ if (afterSha256 !== patchResult.after_sha256) {
76
+ throw new PatchWardenError(
77
+ "direct_target_changed_after_write",
78
+ `Patch target "${input.path}" changed before the operation could be recorded.`,
79
+ "Inspect the file and retry only after concurrent filesystem changes stop.",
80
+ true,
81
+ { path: input.path, expected_sha256: patchResult.after_sha256, actual_sha256: afterSha256 },
82
+ );
83
+ }
64
84
 
65
85
  // 6. Append operation record to session
66
86
  appendDirectSessionOperation(input.session_id, {
67
- index: session.operations.length,
87
+ index: 0,
68
88
  timestamp: new Date().toISOString(),
69
89
  path: input.path,
90
+ operation_type: "patch",
70
91
  before_sha256: beforeSha256,
71
92
  after_sha256: afterSha256,
72
93
  operations_applied: patchResult.operations_applied,
@@ -83,4 +104,5 @@ export function applyPatch(input: ApplyPatchInput): ApplyPatchOutput {
83
104
  next_action:
84
105
  "Call run_verification to test the changes, or apply_patch for more edits.",
85
106
  };
107
+ }, config);
86
108
  }
@@ -5,9 +5,9 @@
5
5
  * 参考 src/tools/auditTask.ts 的导出/返回风格。
6
6
  */
7
7
 
8
- import { getConfig } from "../config.js";
9
- import { guardWorkspacePath } from "../security/pathGuard.js";
10
- import { discardWorktree } from "../goal/worktreeManager.js";
8
+ import { getConfig } from "../../config.js";
9
+ import { guardWorkspacePath } from "../../security/pathGuard.js";
10
+ import { discardWorktree } from "../../goal/worktreeManager.js";
11
11
 
12
12
  export interface DiscardWorktreeInput {
13
13
  worktree_id: string;
@@ -0,0 +1,10 @@
1
+ export * from "./androidDoctor.js";
2
+ export * from "./applyPatch.js";
3
+ export * from "./discardWorktree.js";
4
+ export * from "./listAgents.js";
5
+ export * from "./listWorkspace.js";
6
+ export * from "./mergeWorktree.js";
7
+ export * from "./readWorkspaceFile.js";
8
+ export * from "./recommendAgentForTask.js";
9
+ export * from "./searchWorkspace.js";
10
+ export * from "./syncFile.js";
@@ -1,6 +1,7 @@
1
1
  import { existsSync, statSync } from "node:fs";
2
2
  import { basename, delimiter, extname, isAbsolute, join } from "node:path";
3
- import { getConfig } from "../config.js";
3
+ import { getConfig } from "../../config.js";
4
+ import { sanitizeTrustedPath } from "../../runner/processSecurity.js";
4
5
 
5
6
  export interface AgentAvailability {
6
7
  name: string;
@@ -9,6 +10,9 @@ export interface AgentAvailability {
9
10
  command: string;
10
11
  reason: string | null;
11
12
  checked_at: string;
13
+ adapter: string | null;
14
+ model: string | null;
15
+ capabilities: { model_override: boolean };
12
16
  }
13
17
 
14
18
  export function listAgents(): { agents: AgentAvailability[]; total: number } {
@@ -17,7 +21,7 @@ export function listAgents(): { agents: AgentAvailability[]; total: number } {
17
21
  const agents = Object.entries(config.agents)
18
22
  .sort(([left], [right]) => left.localeCompare(right))
19
23
  .map(([name, agent]) => {
20
- const available = commandExists(agent.command);
24
+ const available = commandExists(agent.command, config.workspaceRoot);
21
25
  return {
22
26
  name,
23
27
  configured: true as const,
@@ -25,17 +29,20 @@ export function listAgents(): { agents: AgentAvailability[]; total: number } {
25
29
  command: basename(agent.command),
26
30
  reason: available ? null : "Configured executable was not found on disk or PATH.",
27
31
  checked_at: checkedAt,
32
+ adapter: typeof agent.adapter === "string" ? agent.adapter : ["codex", "opencode"].includes(name) ? name : null,
33
+ model: typeof agent.model === "string" ? agent.model : null,
34
+ capabilities: { model_override: typeof agent.adapter === "string" || ["codex", "opencode"].includes(name) },
28
35
  };
29
36
  });
30
37
  return { agents, total: agents.length };
31
38
  }
32
39
 
33
- function commandExists(command: string): boolean {
40
+ function commandExists(command: string, workspaceRoot: string): boolean {
34
41
  if (isAbsolute(command) || command.includes("/") || command.includes("\\")) {
35
42
  return isFile(command);
36
43
  }
37
44
 
38
- const pathEntries = (process.env.PATH || "").split(delimiter).filter(Boolean);
45
+ const pathEntries = sanitizeTrustedPath(process.env.PATH || "", workspaceRoot).split(delimiter).filter(Boolean);
39
46
  const extensions = process.platform === "win32"
40
47
  ? (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";")
41
48
  : [""];
@@ -1,8 +1,8 @@
1
1
  import { readdirSync, statSync, existsSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
- import { getConfig } from "../config.js";
4
- import { guardPath } from "../security/pathGuard.js";
5
- import { guardSensitivePath } from "../security/sensitiveGuard.js";
3
+ import { getConfig } from "../../config.js";
4
+ import { guardPath } from "../../security/pathGuard.js";
5
+ import { guardSensitivePath } from "../../security/sensitiveGuard.js";
6
6
 
7
7
  export interface ListEntry {
8
8
  name: string;
@@ -5,9 +5,9 @@
5
5
  * 参考 src/tools/auditTask.ts 的导出/返回风格。
6
6
  */
7
7
 
8
- import { getConfig } from "../config.js";
9
- import { guardWorkspacePath } from "../security/pathGuard.js";
10
- import { mergeWorktree } from "../goal/worktreeManager.js";
8
+ import { getConfig } from "../../config.js";
9
+ import { guardWorkspacePath } from "../../security/pathGuard.js";
10
+ import { mergeWorktree } from "../../goal/worktreeManager.js";
11
11
 
12
12
  export interface MergeWorktreeInput {
13
13
  worktree_id: string;
@@ -1,14 +1,14 @@
1
1
  import { readFileSync, statSync, existsSync } from "node:fs";
2
2
  import { createHash } from "node:crypto";
3
3
  import { resolve, relative, isAbsolute } from "node:path";
4
- import { getConfig } from "../config.js";
5
- import { guardReadPath } from "../security/pathGuard.js";
6
- import { guardSensitivePath } from "../security/sensitiveGuard.js";
7
- import { redactSensitiveContent } from "../security/contentRedaction.js";
8
- import { PatchWardenError } from "../errors.js";
9
- import { readDirectSession } from "../direct/directSessionStore.js";
10
- import { guardDirectSessionActive, guardDirectReadPath, isBinaryFile, guardDirectFileSize } from "../direct/directGuards.js";
11
- import { resolveToolProfile } from "./toolCatalog.js";
4
+ import { getConfig } from "../../config.js";
5
+ import { guardReadPath } from "../../security/pathGuard.js";
6
+ import { guardSensitivePath } from "../../security/sensitiveGuard.js";
7
+ import { redactSensitiveContent } from "../../security/contentRedaction.js";
8
+ import { PatchWardenError } from "../../errors.js";
9
+ import { readDirectSession } from "../../direct/directSessionStore.js";
10
+ import { guardDirectSessionActive, guardDirectReadPath, isBinaryFile, guardDirectFileSize } from "../../direct/directGuards.js";
11
+ import { resolveToolProfile } from "../catalog/toolCatalog.js";
12
12
 
13
13
  export interface ReadWorkspaceFileOutput {
14
14
  path: string;
@@ -1,6 +1,6 @@
1
- import { getConfig } from "../config.js";
2
- import { guardWorkspacePath } from "../security/pathGuard.js";
3
- import { routeAgent } from "../agents/agentRouter.js";
1
+ import { getConfig } from "../../config.js";
2
+ import { guardWorkspacePath } from "../../security/pathGuard.js";
3
+ import { routeAgent } from "../../agents/agentRouter.js";
4
4
 
5
5
  export interface RecommendAgentForTaskInput {
6
6
  repo_path: string;