patchwarden 1.5.1 → 1.6.2

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