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,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,84 @@ 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 */ } }
138
+ }
139
+ truncated ||= pending.length > 0 || results.length >= maxFiles || visitedDirectories >= maxDirectories;
140
+ return { files: results, truncated };
141
+ }
142
+
143
+ export function extractNpmRunScriptNames(content: string): string[] {
144
+ const names = new Set<string>();
145
+ const collectCommands = (text: string) => {
146
+ const pattern = /\bnpm(?:\.cmd)?\s+run\s+([a-zA-Z0-9:_-]+)/gi;
147
+ let match: RegExpExecArray | null;
148
+ while ((match = pattern.exec(text)) !== null) {
149
+ if (match[1]) names.add(match[1]);
113
150
  }
114
- catch { /* skip unreadable dirs */ }
115
- return results;
151
+ };
152
+
153
+ // Markdown code blocks are explicit command-bearing regions. Keep their
154
+ // content separate from prose so token boundaries cannot be concatenated.
155
+ const withoutFences = content.replace(/(?:```|~~~)[^\r\n]*\r?\n([\s\S]*?)(?:```|~~~)/g, (_whole, body: string) => {
156
+ collectCommands(body);
157
+ return "\n";
158
+ });
159
+
160
+ // Inline code is also explicit. Remove it from the prose pass afterward to
161
+ // avoid double-counting and accidental cross-node matches.
162
+ const withoutInlineCode = withoutFences.replace(/`([^`\r\n]+)`/g, (_whole, body: string) => {
163
+ collectCommands(body);
164
+ return " ";
165
+ });
166
+
167
+ // In ordinary text, accept only a standalone command line (optionally a
168
+ // list item, shell prompt, or Run:/Command: label). Narrative mentions such
169
+ // as "this guide discusses npm run deploy" are not executable evidence.
170
+ const explicitPlainCommand = /^\s*(?:(?:[-*+]\s+|\d+[.)]\s+|>\s*|\$\s*|PS>\s*)|(?:(?:run|command|命令)\s*[::]\s*))?npm(?:\.cmd)?\s+run\s+[a-zA-Z0-9:_-]+(?:\s+(?:--[^\r\n#]*|#[^\r\n]*))?\s*$/i;
171
+ for (const line of withoutInlineCode.split(/\r?\n/)) {
172
+ if (explicitPlainCommand.test(line)) collectCommands(line);
173
+ }
174
+ return [...names];
175
+ }
176
+
177
+ function readAuditEvidence(path: string): { content: string; truncated: boolean } {
178
+ const half = Math.floor(MAX_AUDIT_EVIDENCE_BYTES / 2);
179
+ const prefix = readTextFilePrefixSync(path, half);
180
+ if (!prefix.truncated) return { content: prefix.content, truncated: false };
181
+ const tail = readTextFileTailLinesSync(path, 1000, half);
182
+ return {
183
+ content: `${prefix.content}\n[...audit evidence truncated...]\n${tail}`,
184
+ truncated: true,
185
+ };
116
186
  }
117
187
  // ── v0.7.2: New audit checks (exported for testing) ────────────────
118
188
  /**
@@ -479,7 +549,7 @@ export function auditTask(taskId: string): AuditTaskOutput {
479
549
  };
480
550
  // ── 1. Task status ──
481
551
  const taskStatus = statusData.status || "unknown";
482
- const failedStatuses = new Set(["failed", "failed_verification", "failed_scope_violation", "failed_policy_violation", "canceled"]);
552
+ const failedStatuses = new Set(["failed", "failed_verification", "failed_scope_violation", "failed_policy_violation", "canceled", "timeout"]);
483
553
  const doneStatuses = new Set(["done", "done_by_agent"]);
484
554
  checks.push({
485
555
  name: "task_status",
@@ -659,36 +729,55 @@ export function auditTask(taskId: string): AuditTaskOutput {
659
729
  if (existsSync(readmePath))
660
730
  docsToScan.push(readmePath);
661
731
  const docsDir = join(repoPathSafe, "docs");
732
+ let markdownEnumerationTruncated = false;
662
733
  if (existsSync(docsDir)) {
663
- docsToScan.push(...findMdFiles(docsDir));
734
+ const markdown = findMdFiles(docsDir);
735
+ docsToScan.push(...markdown.files);
736
+ markdownEnumerationTruncated = markdown.truncated;
664
737
  }
665
738
  // Collect all npm run references from all docs
666
739
  const allNpmRunRefs = new Set<string>();
667
740
  const allReleaseClaims: string[] = [];
741
+ let remainingDocBytes = MAX_AUDIT_DOC_TOTAL_BYTES;
742
+ let documentScanTruncated = markdownEnumerationTruncated || docsToScan.length > MAX_AUDIT_DOC_FILES;
668
743
  for (const docPath of docsToScan) {
744
+ if (remainingDocBytes <= 0) {
745
+ documentScanTruncated = true;
746
+ break;
747
+ }
669
748
  let content: string;
670
749
  try {
671
750
  if (docPath !== resultFile) {
672
751
  guardReadPath(docPath, config.workspaceRoot);
673
752
  guardSensitivePath(docPath);
674
753
  }
675
- content = readFileSync(docPath, "utf-8");
754
+ const bounded = readTextFilePrefixSync(
755
+ docPath,
756
+ Math.min(MAX_AUDIT_DOC_FILE_BYTES, remainingDocBytes),
757
+ );
758
+ content = bounded.content;
759
+ remainingDocBytes -= Buffer.byteLength(content, "utf-8");
760
+ documentScanTruncated ||= bounded.truncated;
676
761
  }
677
762
  catch {
678
763
  continue;
679
764
  }
680
765
  // Extract npm run xxx
681
- const refs = content.match(/npm(?:\.cmd)?\s+run\s+([a-zA-Z0-9:_-]+)/gi) || [];
682
- for (const ref of refs) {
683
- const scriptName = ref.replace(/npm\s+run\s+/i, "").replace(/[^a-zA-Z0-9:_-]/g, "");
684
- if (scriptName)
685
- allNpmRunRefs.add(scriptName);
686
- }
766
+ for (const scriptName of extractNpmRunScriptNames(content))
767
+ allNpmRunRefs.add(scriptName);
687
768
  // Check release claims
688
769
  const claims = scanForReleaseClaims(content);
689
770
  for (const c of claims)
690
771
  allReleaseClaims.push(`[${relative(repoPathSafe, docPath) || docPath}] ${c}`);
691
772
  }
773
+ if (documentScanTruncated) {
774
+ checks.push({
775
+ name: "documentation_scan_bounded",
776
+ result: "warn",
777
+ detail: `Documentation scan reached its ${MAX_AUDIT_DOC_FILES}-file or ${MAX_AUDIT_DOC_TOTAL_BYTES}-byte safety budget.`,
778
+ });
779
+ addManualVerification("Review documentation omitted by the bounded audit scan.");
780
+ }
692
781
  // Cross-check npm run refs against package.json scripts
693
782
  for (const scriptName of allNpmRunRefs) {
694
783
  if (pkgScripts.length > 0 && !pkgScripts.includes(scriptName)) {
@@ -735,7 +824,9 @@ export function auditTask(taskId: string): AuditTaskOutput {
735
824
  if (hasTestLog) {
736
825
  let logContent: string;
737
826
  try {
738
- logContent = readFileSync(testLogFile, "utf-8");
827
+ const evidence = readAuditEvidence(testLogFile);
828
+ logContent = evidence.content;
829
+ if (evidence.truncated) addManualVerification("test.log exceeded the audit read budget; inspect the complete local artifact.");
739
830
  }
740
831
  catch {
741
832
  logContent = "";
@@ -773,7 +864,9 @@ export function auditTask(taskId: string): AuditTaskOutput {
773
864
  let resultMdContent: string | null = null;
774
865
  if (hasResult) {
775
866
  try {
776
- resultMdContent = readFileSync(resultFile, "utf-8");
867
+ const evidence = readAuditEvidence(resultFile);
868
+ resultMdContent = evidence.content;
869
+ if (evidence.truncated) addManualVerification("result.md exceeded the audit read budget; inspect the complete local artifact.");
777
870
  }
778
871
  catch {
779
872
  resultMdContent = null;
@@ -841,7 +934,7 @@ export function auditTask(taskId: string): AuditTaskOutput {
841
934
  "## Recommended Actions",
842
935
  ...actions.map((a) => `- ${a}`),
843
936
  ].join("\n");
844
- writeFileSync(join(taskDir, "independent-review.md"), reviewMd, "utf-8");
937
+ atomicWriteFileSync(join(taskDir, "independent-review.md"), reviewMd);
845
938
  // ── v0.7.2: 集成 acceptanceEngine ──
846
939
  const releaseClaimsUnverified = allReleaseClaims.length > 0;
847
940
  const acceptanceEvidence = {
@@ -878,16 +971,20 @@ export function auditTask(taskId: string): AuditTaskOutput {
878
971
  const acceptanceResult = evaluateAcceptance(acceptanceEvidence);
879
972
  // 回写 status.json 的 acceptance_status(仅对 done_by_agent 有意义)
880
973
  if (taskStatus === "done_by_agent") {
881
- const updatedStatus = {
882
- ...statusData,
974
+ const statusPatch = {
883
975
  acceptance_status: acceptanceResult.acceptance_status,
884
- updated_at: new Date().toISOString(),
885
976
  };
886
- writeFileSync(statusFile, JSON.stringify(updatedStatus, null, 2), "utf-8");
977
+ mutateTaskStatus(statusFile, (current) => {
978
+ if (current.status !== "done_by_agent") {
979
+ return { result: current };
980
+ }
981
+ const next = { ...current, ...statusPatch, updated_at: new Date().toISOString() };
982
+ return { next, result: next };
983
+ });
887
984
  }
888
985
  // 导出 ACCEPTANCE.md
889
986
  const acceptanceMd = renderAcceptanceMarkdown(taskId, acceptanceResult, acceptanceEvidence);
890
- writeFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd, "utf-8");
987
+ atomicWriteFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd);
891
988
  return {
892
989
  task_id: taskId,
893
990
  verdict,
@@ -1,14 +1,15 @@
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
+ import { readLastAssessmentValidationFailure } from "../../assessments/assessmentDiagnostics.js";
12
13
 
13
14
  const SERVER_STARTED_AT = Date.now();
14
15
 
@@ -130,8 +131,23 @@ export function healthCheck(catalog?: ToolCatalogSnapshot, input: HealthCheckInp
130
131
  workspace_root: workspace,
131
132
  tasks_dir: tasks,
132
133
  tunnel,
134
+ config_path: agents.config_path,
135
+ runtime_build_layout: typeof watcher.supervisor?.runtime_build_layout === "string"
136
+ ? watcher.supervisor.runtime_build_layout
137
+ : null,
138
+ watcher_entry_path: typeof watcher.supervisor?.watcher_entry_path === "string"
139
+ ? watcher.supervisor.watcher_entry_path
140
+ : null,
141
+ validator_module_path: typeof watcher.supervisor?.validator_module_path === "string"
142
+ ? watcher.supervisor.validator_module_path
143
+ : null,
133
144
  agents: agents.agents,
134
145
  agent_status: Object.fromEntries(agents.agents.map((agent) => [agent.name, agent.available ? "ok" : "missing"])),
146
+ agent_readiness: Object.fromEntries(agents.agents.map((agent) => [agent.name, {
147
+ executable_available: agent.available,
148
+ provider_status: agent.provider_status,
149
+ availability_scope: agent.availability_scope,
150
+ }])),
135
151
  ...(input.detail === "self_diagnostic" ? { self_diagnostic: buildSelfDiagnostic(config) } : {}),
136
152
  last_error: tunnel.last_error || (!watcher.available ? watcher.reason : null) || mismatchReport[0] || null,
137
153
  };
@@ -140,7 +156,7 @@ export function healthCheck(catalog?: ToolCatalogSnapshot, input: HealthCheckInp
140
156
  function buildSelfDiagnostic(config: ReturnType<typeof getConfig>) {
141
157
  const recent = listTasks({ limit: 20 });
142
158
  const failures = recent.tasks
143
- .filter((task) => task.status.startsWith("failed") || task.status === "canceled")
159
+ .filter((task) => task.status.startsWith("failed") || task.status === "canceled" || task.status === "timeout")
144
160
  .slice(0, 10)
145
161
  .map((task) => ({
146
162
  task_id: task.task_id,
@@ -156,6 +172,7 @@ function buildSelfDiagnostic(config: ReturnType<typeof getConfig>) {
156
172
  configured_agents: Object.keys(config.agents),
157
173
  recent_tasks_returned: recent.tasks.length,
158
174
  recent_failures: failures,
175
+ last_assessment_validation_failure: readLastAssessmentValidationFailure(),
159
176
  };
160
177
  const safe = redactSensitiveValue(diagnostic);
161
178
  return {
@@ -182,6 +199,11 @@ function readWatcherSupervisorStatus(): Record<string, unknown> {
182
199
  restart_attempts: Number.isInteger(Number(raw.restart_attempts)) ? Number(raw.restart_attempts) : 0,
183
200
  last_error: safeText(raw.last_error, 500) || null,
184
201
  checked_at: safeText(raw.checked_at, 80) || null,
202
+ project_root: safeText(raw.project_root, 500) || null,
203
+ config_path: safeText(raw.config_path, 500) || null,
204
+ watcher_entry_path: safeText(raw.watcher_entry_path, 500) || null,
205
+ validator_module_path: safeText(raw.validator_module_path, 500) || null,
206
+ runtime_build_layout: safeText(raw.runtime_build_layout, 80) || null,
185
207
  };
186
208
  } catch {
187
209
  return { observed: true, managed: false, status: "invalid_status_file" };
@@ -242,6 +264,12 @@ function readTunnelStatus(): Record<string, unknown> & { last_error: string | nu
242
264
  : [],
243
265
  tool_manifest_sha256: safeText(raw.tool_manifest_sha256, 80) || null,
244
266
  core_tools_ready: Boolean(raw.core_tools_ready),
267
+ project_root: safeText(raw.project_root, 500) || null,
268
+ config_path: safeText(raw.config_path, 500) || null,
269
+ mcp_entry_path: safeText(raw.mcp_entry_path, 500) || null,
270
+ watcher_entry_path: safeText(raw.watcher_entry_path, 500) || null,
271
+ validator_module_path: safeText(raw.validator_module_path, 500) || null,
272
+ runtime_build_layout: safeText(raw.runtime_build_layout, 80) || null,
245
273
  };
246
274
  const redacted = redactSensitiveContent(JSON.stringify(allowed));
247
275
  return JSON.parse(redacted.content);
@@ -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";