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,8 +1,8 @@
1
1
  import {
2
2
  auditDirectSession,
3
3
  type DirectSessionAuditOutput,
4
- } from "../direct/directAudit.js";
5
- import { updateDirectSession } from "../direct/directSessionStore.js";
4
+ } from "../../direct/directAudit.js";
5
+ import { updateDirectSession } from "../../direct/directSessionStore.js";
6
6
 
7
7
  // ── Types ──────────────────────────────────────────────────────────
8
8
 
@@ -31,14 +31,20 @@ export interface AuditTaskOutput {
31
31
  manual_verification_items: string[];
32
32
  recommended_next_actions: string[];
33
33
  }
34
- import { readFileSync, existsSync, writeFileSync, readdirSync, statSync } from "node:fs";
34
+ import { readFileSync, existsSync, opendirSync, statSync } from "node:fs";
35
35
  import { join, resolve, relative, basename, sep, isAbsolute } from "node:path";
36
- import { getTasksDir, getConfig } from "../config.js";
37
- import { guardReadPath, guardWorkspacePath } from "../security/pathGuard.js";
38
- import { guardSensitivePath, isSensitivePath } from "../security/sensitiveGuard.js";
39
- import { evaluateAcceptance } from "../goal/acceptanceEngine.js";
40
- import { renderAcceptanceMarkdown } from "../goal/acceptanceTemplate.js";
41
- import type { ChangedFile } from "../runner/changeCapture.js";
36
+ import { getTasksDir, getConfig } from "../../config.js";
37
+ import { guardReadPath, guardWorkspacePath } from "../../security/pathGuard.js";
38
+ import { guardSensitivePath, isSensitivePath } from "../../security/sensitiveGuard.js";
39
+ import { evaluateAcceptance } from "../../goal/acceptanceEngine.js";
40
+ import { renderAcceptanceMarkdown } from "../../goal/acceptanceTemplate.js";
41
+ import type { ChangedFile } from "../../runner/changeCapture.js";
42
+ import { atomicWriteFileSync } from "../../utils/atomicFile.js";
43
+ import { mutateTaskStatus } from "../../runner/taskStatusStore.js";
44
+ import {
45
+ readTextFilePrefixSync,
46
+ readTextFileTailLinesSync,
47
+ } from "../../utils/boundedFile.js";
42
48
 
43
49
  interface ExtractedCommand {
44
50
  type: "npm-run" | "npm-bare" | "node" | "npx" | "python";
@@ -86,6 +92,10 @@ const RELEASE_PATTERNS = [
86
92
  /npm\s+publish\s+completed/i,
87
93
  /deploy(ed|ment)?\s+(to|on)\s+(npm|registry|github)/i,
88
94
  ];
95
+ const MAX_AUDIT_DOC_FILES = 200;
96
+ const MAX_AUDIT_DOC_FILE_BYTES = 512 * 1024;
97
+ const MAX_AUDIT_DOC_TOTAL_BYTES = 4 * 1024 * 1024;
98
+ const MAX_AUDIT_EVIDENCE_BYTES = 1024 * 1024;
89
99
  function scanForReleaseClaims(text: string): string[] {
90
100
  const found: string[] = [];
91
101
  for (const pattern of RELEASE_PATTERNS) {
@@ -95,24 +105,50 @@ function scanForReleaseClaims(text: string): string[] {
95
105
  }
96
106
  return found;
97
107
  }
98
- function findMdFiles(dir: string, maxDepth = 3): string[] {
108
+ function findMdFiles(
109
+ dir: string,
110
+ maxDepth = 3,
111
+ maxFiles = MAX_AUDIT_DOC_FILES,
112
+ ): { files: string[]; truncated: boolean } {
99
113
  const results: string[] = [];
100
- if (!existsSync(dir) || maxDepth <= 0)
101
- return results;
102
- try {
103
- const entries = readdirSync(dir, { withFileTypes: true });
104
- for (const e of entries) {
105
- const full = join(dir, e.name);
106
- if (e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules") {
107
- results.push(...findMdFiles(full, maxDepth - 1));
108
- }
109
- else if (e.isFile() && e.name.endsWith(".md")) {
110
- results.push(full);
114
+ const pending = [{ path: dir, depth: maxDepth }];
115
+ const maxDirectories = maxFiles * 4;
116
+ let visitedDirectories = 0;
117
+ let truncated = false;
118
+ while (pending.length > 0 && results.length < maxFiles && visitedDirectories < maxDirectories) {
119
+ const current = pending.pop()!;
120
+ if (!existsSync(current.path) || current.depth <= 0) continue;
121
+ visitedDirectories += 1;
122
+ let handle;
123
+ try {
124
+ handle = opendirSync(current.path);
125
+ while (results.length < maxFiles) {
126
+ const entry = handle.readSync();
127
+ if (!entry) break;
128
+ const full = join(current.path, entry.name);
129
+ if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
130
+ if (pending.length < maxDirectories) pending.push({ path: full, depth: current.depth - 1 });
131
+ else truncated = true;
132
+ } else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
133
+ results.push(full);
134
+ }
111
135
  }
112
- }
136
+ } catch { /* skip unreadable dirs */ }
137
+ finally { try { handle?.closeSync(); } catch { /* best effort */ } }
113
138
  }
114
- catch { /* skip unreadable dirs */ }
115
- return results;
139
+ truncated ||= pending.length > 0 || results.length >= maxFiles || visitedDirectories >= maxDirectories;
140
+ return { files: results, truncated };
141
+ }
142
+
143
+ function readAuditEvidence(path: string): { content: string; truncated: boolean } {
144
+ const half = Math.floor(MAX_AUDIT_EVIDENCE_BYTES / 2);
145
+ const prefix = readTextFilePrefixSync(path, half);
146
+ if (!prefix.truncated) return { content: prefix.content, truncated: false };
147
+ const tail = readTextFileTailLinesSync(path, 1000, half);
148
+ return {
149
+ content: `${prefix.content}\n[...audit evidence truncated...]\n${tail}`,
150
+ truncated: true,
151
+ };
116
152
  }
117
153
  // ── v0.7.2: New audit checks (exported for testing) ────────────────
118
154
  /**
@@ -659,20 +695,35 @@ export function auditTask(taskId: string): AuditTaskOutput {
659
695
  if (existsSync(readmePath))
660
696
  docsToScan.push(readmePath);
661
697
  const docsDir = join(repoPathSafe, "docs");
698
+ let markdownEnumerationTruncated = false;
662
699
  if (existsSync(docsDir)) {
663
- docsToScan.push(...findMdFiles(docsDir));
700
+ const markdown = findMdFiles(docsDir);
701
+ docsToScan.push(...markdown.files);
702
+ markdownEnumerationTruncated = markdown.truncated;
664
703
  }
665
704
  // Collect all npm run references from all docs
666
705
  const allNpmRunRefs = new Set<string>();
667
706
  const allReleaseClaims: string[] = [];
707
+ let remainingDocBytes = MAX_AUDIT_DOC_TOTAL_BYTES;
708
+ let documentScanTruncated = markdownEnumerationTruncated || docsToScan.length > MAX_AUDIT_DOC_FILES;
668
709
  for (const docPath of docsToScan) {
710
+ if (remainingDocBytes <= 0) {
711
+ documentScanTruncated = true;
712
+ break;
713
+ }
669
714
  let content: string;
670
715
  try {
671
716
  if (docPath !== resultFile) {
672
717
  guardReadPath(docPath, config.workspaceRoot);
673
718
  guardSensitivePath(docPath);
674
719
  }
675
- content = readFileSync(docPath, "utf-8");
720
+ const bounded = readTextFilePrefixSync(
721
+ docPath,
722
+ Math.min(MAX_AUDIT_DOC_FILE_BYTES, remainingDocBytes),
723
+ );
724
+ content = bounded.content;
725
+ remainingDocBytes -= Buffer.byteLength(content, "utf-8");
726
+ documentScanTruncated ||= bounded.truncated;
676
727
  }
677
728
  catch {
678
729
  continue;
@@ -689,6 +740,14 @@ export function auditTask(taskId: string): AuditTaskOutput {
689
740
  for (const c of claims)
690
741
  allReleaseClaims.push(`[${relative(repoPathSafe, docPath) || docPath}] ${c}`);
691
742
  }
743
+ if (documentScanTruncated) {
744
+ checks.push({
745
+ name: "documentation_scan_bounded",
746
+ result: "warn",
747
+ detail: `Documentation scan reached its ${MAX_AUDIT_DOC_FILES}-file or ${MAX_AUDIT_DOC_TOTAL_BYTES}-byte safety budget.`,
748
+ });
749
+ addManualVerification("Review documentation omitted by the bounded audit scan.");
750
+ }
692
751
  // Cross-check npm run refs against package.json scripts
693
752
  for (const scriptName of allNpmRunRefs) {
694
753
  if (pkgScripts.length > 0 && !pkgScripts.includes(scriptName)) {
@@ -735,7 +794,9 @@ export function auditTask(taskId: string): AuditTaskOutput {
735
794
  if (hasTestLog) {
736
795
  let logContent: string;
737
796
  try {
738
- logContent = readFileSync(testLogFile, "utf-8");
797
+ const evidence = readAuditEvidence(testLogFile);
798
+ logContent = evidence.content;
799
+ if (evidence.truncated) addManualVerification("test.log exceeded the audit read budget; inspect the complete local artifact.");
739
800
  }
740
801
  catch {
741
802
  logContent = "";
@@ -773,7 +834,9 @@ export function auditTask(taskId: string): AuditTaskOutput {
773
834
  let resultMdContent: string | null = null;
774
835
  if (hasResult) {
775
836
  try {
776
- resultMdContent = readFileSync(resultFile, "utf-8");
837
+ const evidence = readAuditEvidence(resultFile);
838
+ resultMdContent = evidence.content;
839
+ if (evidence.truncated) addManualVerification("result.md exceeded the audit read budget; inspect the complete local artifact.");
777
840
  }
778
841
  catch {
779
842
  resultMdContent = null;
@@ -841,7 +904,7 @@ export function auditTask(taskId: string): AuditTaskOutput {
841
904
  "## Recommended Actions",
842
905
  ...actions.map((a) => `- ${a}`),
843
906
  ].join("\n");
844
- writeFileSync(join(taskDir, "independent-review.md"), reviewMd, "utf-8");
907
+ atomicWriteFileSync(join(taskDir, "independent-review.md"), reviewMd);
845
908
  // ── v0.7.2: 集成 acceptanceEngine ──
846
909
  const releaseClaimsUnverified = allReleaseClaims.length > 0;
847
910
  const acceptanceEvidence = {
@@ -878,16 +941,20 @@ export function auditTask(taskId: string): AuditTaskOutput {
878
941
  const acceptanceResult = evaluateAcceptance(acceptanceEvidence);
879
942
  // 回写 status.json 的 acceptance_status(仅对 done_by_agent 有意义)
880
943
  if (taskStatus === "done_by_agent") {
881
- const updatedStatus = {
882
- ...statusData,
944
+ const statusPatch = {
883
945
  acceptance_status: acceptanceResult.acceptance_status,
884
- updated_at: new Date().toISOString(),
885
946
  };
886
- writeFileSync(statusFile, JSON.stringify(updatedStatus, null, 2), "utf-8");
947
+ mutateTaskStatus(statusFile, (current) => {
948
+ if (current.status !== "done_by_agent") {
949
+ return { result: current };
950
+ }
951
+ const next = { ...current, ...statusPatch, updated_at: new Date().toISOString() };
952
+ return { next, result: next };
953
+ });
887
954
  }
888
955
  // 导出 ACCEPTANCE.md
889
956
  const acceptanceMd = renderAcceptanceMarkdown(taskId, acceptanceResult, acceptanceEvidence);
890
- writeFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd, "utf-8");
957
+ atomicWriteFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd);
891
958
  return {
892
959
  task_id: taskId,
893
960
  verdict,
@@ -1,14 +1,14 @@
1
1
  import { accessSync, constants, existsSync, readFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
- import { getConfig, getTasksDir, getDirectSessionsDir, resolveWorkspaceRoot } from "../config.js";
5
- import { listAgents } from "./listAgents.js";
6
- import { redactSensitiveContent, redactSensitiveValue } from "../security/contentRedaction.js";
7
- import { PATCHWARDEN_VERSION, TOOL_SCHEMA_EPOCH } from "../version.js";
8
- import type { ToolCatalogSnapshot } from "./toolCatalog.js";
9
- import { CHATGPT_CORE_TOOL_NAMES, CHATGPT_DIRECT_TOOL_NAMES, CHATGPT_SEARCH_TOOL_NAMES, resolveToolProfile } from "./toolCatalog.js";
10
- import { readWatcherStatus } from "../watcherStatus.js";
11
- import { listTasks } from "./listTasks.js";
4
+ import { getConfig, getTasksDir, getDirectSessionsDir, resolveWorkspaceRoot } from "../../config.js";
5
+ import { listAgents } from "../workspace/listAgents.js";
6
+ import { redactSensitiveContent, redactSensitiveValue } from "../../security/contentRedaction.js";
7
+ import { PATCHWARDEN_VERSION, TOOL_SCHEMA_EPOCH } from "../../version.js";
8
+ import type { ToolCatalogSnapshot } from "../catalog/toolCatalog.js";
9
+ import { CHATGPT_CORE_TOOL_NAMES, CHATGPT_DIRECT_TOOL_NAMES, CHATGPT_SEARCH_TOOL_NAMES, resolveToolProfile } from "../catalog/toolCatalog.js";
10
+ import { readWatcherStatus } from "../../watcherStatus.js";
11
+ import { listTasks } from "../tasks/listTasks.js";
12
12
 
13
13
  const SERVER_STARTED_AT = Date.now();
14
14
 
@@ -0,0 +1,6 @@
1
+ export * from "./auditSession.js";
2
+ export * from "./auditTask.js";
3
+ export * from "./healthCheck.js";
4
+ export * from "./safeStatus.js";
5
+ export * from "./safeViews.js";
6
+ export * from "./schemaDriftCheck.js";
@@ -1,12 +1,12 @@
1
1
  import { readFileSync, existsSync } from "node:fs";
2
2
  import { resolve, join } from "node:path";
3
- import { getTasksDir, getConfig, type PatchWardenConfig } from "../config.js";
4
- import { guardReadPath } from "../security/pathGuard.js";
5
- import { guardSensitivePath } from "../security/sensitiveGuard.js";
6
- import type { TaskStatus, TaskPhase, AcceptanceStatus } from "./createTask.js";
7
- import { readTaskRuntime } from "../taskRuntime.js";
8
- import { readWatcherStatus } from "../watcherStatus.js";
9
- import { diagnoseTask, type DiagnosisType, type DiagnosisConfidence } from "./diagnoseTask.js";
3
+ import { getTasksDir, getConfig, type PatchWardenConfig } from "../../config.js";
4
+ import { guardReadPath } from "../../security/pathGuard.js";
5
+ import { guardSensitivePath } from "../../security/sensitiveGuard.js";
6
+ import type { TaskStatus, TaskPhase, AcceptanceStatus } from "../tasks/createTask.js";
7
+ import { readTaskRuntime } from "../../runner/taskRuntime.js";
8
+ import { readWatcherStatus } from "../../watcherStatus.js";
9
+ import { diagnoseTask, type DiagnosisType, type DiagnosisConfidence } from "../tasks/diagnoseTask.js";
10
10
 
11
11
  export interface SafeStatusOutput {
12
12
  task_id: string;
@@ -1,14 +1,15 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
- import { getConfig, getTasksDir } from "../config.js";
3
+ import { getConfig, getTasksDir } from "../../config.js";
4
4
  import { auditSession } from "./auditSession.js";
5
5
  import { auditTask, type AuditTaskOutput } from "./auditTask.js";
6
- import { finalizeDirectSession } from "./finalizeDirectSession.js";
7
- import { getTaskSummary } from "./getTaskSummary.js";
8
- import { guardReadPath } from "../security/pathGuard.js";
9
- import { redactSensitiveValue } from "../security/contentRedaction.js";
10
- import { readDirectSession, type DirectSessionRecord, type DirectSessionVerificationRun } from "../direct/directSessionStore.js";
11
- import type { ChangedFile, ClassifiedChange } from "../runner/changeCapture.js";
6
+ import { finalizeDirectSession } from "../direct/finalizeDirectSession.js";
7
+ import { getTaskSummary } from "../tasks/getTaskSummary.js";
8
+ import { guardReadPath } from "../../security/pathGuard.js";
9
+ import { redactSensitiveValue } from "../../security/contentRedaction.js";
10
+ import { readDirectSession, type DirectSessionRecord, type DirectSessionVerificationRun } from "../../direct/directSessionStore.js";
11
+ import type { ChangedFile, ClassifiedChange } from "../../runner/changeCapture.js";
12
+ import { ARTIFACT_SCHEMA_VERSION } from "../../version.js";
12
13
 
13
14
  export interface SafeViewOptions {
14
15
  max_items?: number;
@@ -18,6 +19,7 @@ export function safeResult(taskId: string, options: SafeViewOptions = {}) {
18
19
  const maxItems = normalizeMaxItems(options.max_items);
19
20
  const summary = getTaskSummary(taskId, { view: "compact", max_items: maxItems });
20
21
  return redact({
22
+ schema_version: ARTIFACT_SCHEMA_VERSION,
21
23
  task_id: summary.task_id,
22
24
  status: summary.status,
23
25
  terminal: summary.terminal,
@@ -46,13 +48,17 @@ export function safeTestSummary(taskId: string) {
46
48
  const { taskDir, config } = getTaskDir(taskId);
47
49
  const verify = readJson(join(taskDir, "verify.json"), config);
48
50
  const summary = getTaskSummary(taskId, { view: "compact", max_items: 8 });
49
- const commands = asArray(verify.commands).map((entry: any) => ({
50
- command: String(entry.command || ""),
51
- status: String(entry.status || "unknown"),
52
- exit_code: entry.exit_code ?? null,
53
- duration_ms: Number(entry.duration_ms || 0),
54
- }));
51
+ const commands = asArray(verify.commands).map((entry) => {
52
+ const command = asRecord(entry);
53
+ return {
54
+ command: String(command.command || ""),
55
+ status: String(command.status || "unknown"),
56
+ exit_code: command.exit_code ?? null,
57
+ duration_ms: Number(command.duration_ms || 0),
58
+ };
59
+ });
55
60
  return redact({
61
+ schema_version: ARTIFACT_SCHEMA_VERSION,
56
62
  task_id: taskId,
57
63
  status: String(verify.status || summary.verification_summary.status || "not_available"),
58
64
  command_count: commands.length,
@@ -71,6 +77,7 @@ export function safeDiffSummary(taskId: string, options: SafeViewOptions = {}) {
71
77
  const changedFiles = asArray(changes.changed_files) as ChangedFile[];
72
78
  const hygiene = asRecord(changes.artifact_hygiene);
73
79
  return redact({
80
+ schema_version: ARTIFACT_SCHEMA_VERSION,
74
81
  task_id: taskId,
75
82
  changed_files_total: changedFiles.length,
76
83
  additions: Number(changes.additions || 0),
@@ -141,6 +148,7 @@ function auditToSafe(audit: AuditTaskOutput, maxItems: number) {
141
148
  detail: truncate(check.detail, 240),
142
149
  }));
143
150
  return redact({
151
+ schema_version: ARTIFACT_SCHEMA_VERSION,
144
152
  task_id: audit.task_id,
145
153
  verdict: audit.verdict,
146
154
  acceptance: {
@@ -233,7 +241,7 @@ function getTaskDir(taskId: string) {
233
241
  return { config, taskDir };
234
242
  }
235
243
 
236
- function readJson(path: string, config: ReturnType<typeof getConfig>): Record<string, any> {
244
+ function readJson(path: string, config: ReturnType<typeof getConfig>): Record<string, unknown> {
237
245
  guardReadPath(path, config.workspaceRoot, config.tasksDir);
238
246
  if (!existsSync(path)) return {};
239
247
  try {
@@ -252,12 +260,14 @@ function normalizeMaxItems(value: number | undefined): number {
252
260
  return value;
253
261
  }
254
262
 
255
- function asArray(value: unknown): any[] {
263
+ function asArray(value: unknown): unknown[] {
256
264
  return Array.isArray(value) ? value : [];
257
265
  }
258
266
 
259
- function asRecord(value: unknown): Record<string, any> {
260
- return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, any> : {};
267
+ function asRecord(value: unknown): Record<string, unknown> {
268
+ return value && typeof value === "object" && !Array.isArray(value)
269
+ ? value as Record<string, unknown>
270
+ : {};
261
271
  }
262
272
 
263
273
  function limitStrings(values: string[], maxItems: number): string[] {
@@ -7,9 +7,9 @@
7
7
  * 本模块只做检测和报告,不做运行时阻断。
8
8
  */
9
9
 
10
- import { computeSchemaDigest } from "./toolRegistry.js";
11
- import type { PatchWardenToolMeta } from "./toolRegistry.js";
12
- import { CHATGPT_CORE_TOOL_NAMES } from "./toolCatalog.js";
10
+ import { computeSchemaDigest } from "../catalog/toolRegistry.js";
11
+ import type { PatchWardenToolMeta } from "../catalog/toolRegistry.js";
12
+ import { CHATGPT_CORE_TOOL_NAMES } from "../catalog/toolCatalog.js";
13
13
 
14
14
  // ── 结果类型 ──────────────────────────────────────────────────────
15
15
 
@@ -1,12 +1,12 @@
1
1
  import { existsSync, statSync } from "node:fs";
2
- import { getConfig } from "../config.js";
3
- import { PatchWardenError } from "../errors.js";
4
- import { guardWorkspacePath } from "../security/pathGuard.js";
5
- import { guardRuntimeSelfModification } from "../security/runtimeGuard.js";
6
- import { captureRepoSnapshot } from "../runner/changeCapture.js";
2
+ import { getConfig } from "../../config.js";
3
+ import { PatchWardenError } from "../../errors.js";
4
+ import { guardWorkspacePath } from "../../security/pathGuard.js";
5
+ import { guardRuntimeSelfModification } from "../../security/runtimeGuard.js";
6
+ import { captureRepoSnapshot } from "../../runner/changeCapture.js";
7
7
  import {
8
8
  createDirectSession as createDirectSessionRecord,
9
- } from "../direct/directSessionStore.js";
9
+ } from "../../direct/directSessionStore.js";
10
10
 
11
11
  // ── Types ──────────────────────────────────────────────────────────
12
12
 
@@ -1,18 +1,18 @@
1
1
  import { join, resolve, relative, isAbsolute } from "node:path";
2
2
  import {
3
3
  readDirectSession,
4
- updateDirectSession,
5
4
  finalizeDirectSessionRecord,
6
5
  getDirectSessionDir,
7
- } from "../direct/directSessionStore.js";
8
- import { guardDirectSessionActive } from "../direct/directGuards.js";
6
+ withDirectSessionMutationLockAsync,
7
+ } from "../../direct/directSessionStore.js";
8
+ import { guardDirectSessionActive } from "../../direct/directGuards.js";
9
9
  import {
10
10
  captureRepoSnapshot,
11
11
  buildChangeArtifacts,
12
12
  type ChangeArtifacts,
13
13
  type ClassifiedChange,
14
14
  type ChangedFile,
15
- } from "../runner/changeCapture.js";
15
+ } from "../../runner/changeCapture.js";
16
16
 
17
17
  // ── Types ──────────────────────────────────────────────────────────
18
18
 
@@ -41,6 +41,7 @@ export async function finalizeDirectSession(
41
41
  input: FinalizeDirectSessionInput
42
42
  ): Promise<FinalizeDirectSessionOutput> {
43
43
  const { session_id } = input;
44
+ return withDirectSessionMutationLockAsync(session_id, async () => {
44
45
 
45
46
  // 1. Read session and guard active (not expired, not finalized)
46
47
  const session = readDirectSession(session_id);
@@ -58,7 +59,7 @@ export async function finalizeDirectSession(
58
59
 
59
60
  // 4. Finalize session record — writes changed-files.json, diff.patch,
60
61
  // summary.json, summary.md and marks the session as finalized.
61
- finalizeDirectSessionRecord(session_id, afterSnapshot, changeArtifacts);
62
+ finalizeDirectSessionRecord(session_id, changeArtifacts);
62
63
 
63
64
  // 5. Build verification summary from session.verification_runs
64
65
  const verification_summary: Record<string, "passed" | "failed"> = {};
@@ -91,6 +92,7 @@ export async function finalizeDirectSession(
91
92
  finalized: true,
92
93
  next_action: "Call audit_session to independently review the changes.",
93
94
  };
95
+ });
94
96
  }
95
97
 
96
98
  // ── Helpers ────────────────────────────────────────────────────────
@@ -0,0 +1,3 @@
1
+ export * from "./createDirectSession.js";
2
+ export * from "./finalizeDirectSession.js";
3
+ export * from "./runDirectVerificationBundle.js";
@@ -1,5 +1,5 @@
1
- import { getConfig } from "../config.js";
2
- import { runVerification } from "./runVerification.js";
1
+ import { getConfig } from "../../config.js";
2
+ import { runVerification } from "../tasks/runVerification.js";
3
3
 
4
4
  export interface RunDirectVerificationBundleInput {
5
5
  session_id: string;
@@ -8,12 +8,12 @@
8
8
  */
9
9
 
10
10
  import { join } from "node:path";
11
- import type { ToolDef } from "./registry.js";
12
- import { buildToolRegistry, type PatchWardenToolMeta } from "./toolRegistry.js";
13
- import { discoverTools as searchDiscover, type DiscoverToolsInput } from "./toolSearch.js";
14
- import { issueToken } from "../security/discoveryTokenStore.js";
15
- import { aggregateUsageStats, type ToolUsageStats } from "./toolUsageStats.js";
16
- import { getConfig } from "../config.js";
11
+ import type { ToolDef } from "../registry.js";
12
+ import { buildToolRegistry, type PatchWardenToolMeta } from "../catalog/toolRegistry.js";
13
+ import { discoverTools as searchDiscover, type DiscoverToolsInput } from "../catalog/toolSearch.js";
14
+ import { issueToken } from "../../security/discoveryTokenStore.js";
15
+ import { aggregateUsageStats, type ToolUsageStats } from "../catalog/toolUsageStats.js";
16
+ import { getConfig } from "../../config.js";
17
17
 
18
18
  export function discoverTools(
19
19
  input: DiscoverToolsInput,
@@ -7,9 +7,9 @@
7
7
  * 检测 registry 与实际 toolDef 之间的 schema drift。
8
8
  */
9
9
 
10
- import type { ToolDef } from "./registry.js";
11
- import { buildToolRegistry, computeSchemaDigest, type PatchWardenToolMeta } from "./toolRegistry.js";
12
- import { explainTool as searchExplain, type ExplainToolInput } from "./toolSearch.js";
10
+ import type { ToolDef } from "../registry.js";
11
+ import { buildToolRegistry, computeSchemaDigest, type PatchWardenToolMeta } from "../catalog/toolRegistry.js";
12
+ import { explainTool as searchExplain, type ExplainToolInput } from "../catalog/toolSearch.js";
13
13
 
14
14
  export function explainTool(
15
15
  input: ExplainToolInput,
@@ -0,0 +1,3 @@
1
+ export * from "./discoverTools.js";
2
+ export * from "./explainTool.js";
3
+ export * from "./invokeDiscoveredTool.js";
@@ -7,13 +7,13 @@
7
7
  * 任一环节失败都记审计日志并返回错误结果,不向上层抛错。
8
8
  */
9
9
 
10
- import { consumeToken, type DiscoveryTokenRecord } from "../security/discoveryTokenStore.js";
11
- import { checkInvocation } from "../security/toolInvocationGuard.js";
12
- import { logToolInvocation, computeArgumentsDigest } from "../logging.js";
13
- import { buildToolRegistry, type PatchWardenToolMeta } from "./toolRegistry.js";
14
- import type { ToolProfile } from "./toolCatalog.js";
15
- import type { ToolDef } from "./registry.js";
16
- import { PatchWardenError } from "../errors.js";
10
+ import { consumeToken, type DiscoveryTokenRecord } from "../../security/discoveryTokenStore.js";
11
+ import { checkInvocation } from "../../security/toolInvocationGuard.js";
12
+ import { logToolInvocation, computeArgumentsDigest } from "../../logging.js";
13
+ import { buildToolRegistry, type PatchWardenToolMeta } from "../catalog/toolRegistry.js";
14
+ import type { ToolProfile } from "../catalog/toolCatalog.js";
15
+ import type { ToolDef } from "../registry.js";
16
+ import { PatchWardenError } from "../../errors.js";
17
17
 
18
18
  // ── 类型定义 ──────────────────────────────────────────────────────
19
19
 
@@ -5,39 +5,44 @@
5
5
  * rewritten. Extracted from the original handleToolCallInternal switch.
6
6
  */
7
7
 
8
- import { savePlan } from "../savePlan.js";
9
- import { getPlan } from "../getPlan.js";
10
- import { createTask } from "../createTask.js";
11
- import { getTaskStatus } from "../getTaskStatus.js";
12
- import { getResult, getResultJson, getDiff, getTestLog, getTaskLogTail } from "../taskOutputs.js";
13
- import { listWorkspace } from "../listWorkspace.js";
14
- import { readWorkspaceFile } from "../readWorkspaceFile.js";
15
- import { listTasks } from "../listTasks.js";
16
- import { cancelTask } from "../cancelTask.js";
17
- import { killTask } from "../killTask.js";
18
- import { retryTask } from "../retryTask.js";
19
- import { getTaskStdoutTail } from "../getTaskStdoutTail.js";
20
- import { getTaskProgress } from "../getTaskProgress.js";
21
- import { listAgents } from "../listAgents.js";
22
- import { healthCheck } from "../healthCheck.js";
23
- import { getTaskSummary } from "../getTaskSummary.js";
24
- import { waitForTask } from "../waitForTask.js";
25
- import { runTaskLoop } from "../runTaskLoop.js";
26
- import { getTaskLineage } from "../taskLineage.js";
27
- import { exportTaskEvidencePack } from "../evidencePack.js";
28
- import { recommendAgentForTask } from "../recommendAgentForTask.js";
29
- import { auditTask } from "../auditTask.js";
30
- import { safeStatus } from "../safeStatus.js";
31
- import { safeAudit, safeDiffSummary, safeResult, safeTestSummary } from "../safeViews.js";
32
- import { diagnoseTask } from "../diagnoseTask.js";
33
- import { reconcileTasks } from "../reconcileTasks.js";
34
- import { checkReleaseGate } from "../checkReleaseGate.js";
35
- import { getProjectPolicyTool } from "../releaseMode.js";
8
+ import { savePlan } from "../goals/savePlan.js";
9
+ import { getPlan } from "../goals/getPlan.js";
10
+ import { createTask } from "../tasks/createTask.js";
11
+ import { getTaskStatus } from "../tasks/getTaskStatus.js";
12
+ import { getResult, getResultJson, getDiff, getTestLog, getTaskLogTail } from "../tasks/taskOutputs.js";
13
+ import { listWorkspace } from "../workspace/listWorkspace.js";
14
+ import { readWorkspaceFile } from "../workspace/readWorkspaceFile.js";
15
+ import { listTasks } from "../tasks/listTasks.js";
16
+ import { cancelTask } from "../tasks/cancelTask.js";
17
+ import { killTask } from "../tasks/killTask.js";
18
+ import { retryTask } from "../tasks/retryTask.js";
19
+ import { getTaskStdoutTail } from "../tasks/getTaskStdoutTail.js";
20
+ import { getTaskProgress } from "../tasks/getTaskProgress.js";
21
+ import { listAgents } from "../workspace/listAgents.js";
22
+ import { healthCheck } from "../diagnostics/healthCheck.js";
23
+ import { getTaskSummary } from "../tasks/getTaskSummary.js";
24
+ import { waitForTask } from "../tasks/waitForTask.js";
25
+ import { runTaskLoop } from "../tasks/runTaskLoop.js";
26
+ import { getTaskLineage } from "../tasks/taskLineage.js";
27
+ import { exportTaskEvidencePack } from "../tasks/evidencePack.js";
28
+ import { recommendAgentForTask } from "../workspace/recommendAgentForTask.js";
29
+ import { auditTask } from "../diagnostics/auditTask.js";
30
+ import { safeStatus } from "../diagnostics/safeStatus.js";
31
+ import { safeAudit, safeDiffSummary, safeResult, safeTestSummary } from "../diagnostics/safeViews.js";
32
+ import { diagnoseTask } from "../tasks/diagnoseTask.js";
33
+ import { reconcileTasks } from "../tasks/reconcileTasks.js";
34
+ import { checkReleaseGate } from "../release/checkReleaseGate.js";
35
+ import { getProjectPolicyTool } from "../release/releaseMode.js";
36
36
  import { runTask } from "../../runner/runTask.js";
37
37
  import { getConfig } from "../../config.js";
38
38
  import { getToolCatalogSnapshot } from "../registry.js";
39
39
  import type { ToolHandlerMap } from "./types.js";
40
40
  import { toResult } from "./types.js";
41
+ import {
42
+ parseOptionalTaskTemplate,
43
+ parseReleaseStage,
44
+ parseTaskLogFile,
45
+ } from "./validation.js";
41
46
 
42
47
  // ── Local helpers (moved verbatim from registry.ts) ───────────────
43
48
 
@@ -82,7 +87,7 @@ export const coreHandlers: ToolHandlerMap = {
82
87
  plan_id: args?.plan_id ? String(args.plan_id) : undefined,
83
88
  inline_plan: args?.inline_plan ? String(args.inline_plan) : undefined,
84
89
  plan_title: args?.plan_title ? String(args.plan_title) : undefined,
85
- template: args?.template ? (String(args.template) as any) : undefined,
90
+ template: parseOptionalTaskTemplate(args?.template),
86
91
  goal: args?.goal ? String(args.goal) : undefined,
87
92
  source_task_id: args?.source_task_id ? String(args.source_task_id) : undefined,
88
93
  agent: String(args?.agent ?? ""),
@@ -259,7 +264,7 @@ export const coreHandlers: ToolHandlerMap = {
259
264
  return toResult(
260
265
  getTaskLogTail(
261
266
  String(args?.task_id ?? ""),
262
- (args?.file as "stdout" | "stderr" | "test" | "verify") || "stdout",
267
+ parseTaskLogFile(args?.file),
263
268
  {
264
269
  lines: args?.lines ? Number(args.lines) : undefined,
265
270
  redact: args?.redact !== undefined ? Boolean(args.redact) : undefined,
@@ -349,7 +354,7 @@ export const coreHandlers: ToolHandlerMap = {
349
354
  return toResult(
350
355
  await checkReleaseGate({
351
356
  repo_path: String(args?.repo_path ?? ""),
352
- target_stage: String(args?.target_stage ?? "local_ready") as any,
357
+ target_stage: parseReleaseStage(args?.target_stage),
353
358
  package_name: args?.package_name ? String(args.package_name) : undefined,
354
359
  version: args?.version ? String(args.version) : undefined,
355
360
  github_repo: args?.github_repo ? String(args.github_repo) : undefined,