patchwarden 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (597) hide show
  1. package/PatchWarden.cmd +32 -2
  2. package/README.en.md +194 -26
  3. package/README.md +160 -22
  4. package/dist/assessments/agentAssessor.d.ts +1 -1
  5. package/dist/assessments/agentAssessor.js +24 -15
  6. package/dist/assessments/assessmentStore.d.ts +1 -1
  7. package/dist/assessments/assessmentStore.js +44 -36
  8. package/dist/assessments/confirmCli.js +5 -4
  9. package/dist/config.d.ts +22 -0
  10. package/dist/config.js +98 -11
  11. package/dist/control/fileManager.d.ts +2 -0
  12. package/dist/control/fileManager.js +39 -0
  13. package/dist/control/middleware/auth.d.ts +16 -0
  14. package/dist/control/middleware/auth.js +17 -0
  15. package/dist/control/middleware/static.d.ts +3 -0
  16. package/dist/control/middleware/static.js +78 -0
  17. package/dist/control/routeTable.d.ts +24 -0
  18. package/dist/control/routeTable.js +263 -0
  19. package/dist/control/routes/audit.d.ts +15 -0
  20. package/dist/control/routes/audit.js +287 -0
  21. package/dist/control/routes/evidence.d.ts +4 -0
  22. package/dist/control/routes/evidence.js +96 -0
  23. package/dist/control/routes/lineage.d.ts +3 -0
  24. package/dist/control/routes/lineage.js +71 -0
  25. package/dist/control/routes/policy.d.ts +3 -0
  26. package/dist/control/routes/policy.js +81 -0
  27. package/dist/control/routes/process.d.ts +12 -0
  28. package/dist/control/routes/process.js +487 -0
  29. package/dist/control/routes/sessions.d.ts +30 -0
  30. package/dist/control/routes/sessions.js +287 -0
  31. package/dist/control/routes/status.d.ts +51 -0
  32. package/dist/control/routes/status.js +307 -0
  33. package/dist/control/routes/taskActions.d.ts +21 -0
  34. package/dist/control/routes/taskActions.js +197 -0
  35. package/dist/control/routes/tasks.d.ts +24 -0
  36. package/dist/control/routes/tasks.js +309 -0
  37. package/dist/control/routes/workspace.d.ts +15 -0
  38. package/dist/control/routes/workspace.js +220 -0
  39. package/dist/control/runtime.d.ts +92 -0
  40. package/dist/control/runtime.js +425 -0
  41. package/dist/control/server.d.ts +13 -0
  42. package/dist/control/server.js +150 -0
  43. package/dist/control/shared.d.ts +59 -0
  44. package/dist/control/shared.js +341 -0
  45. package/dist/controlCenter.d.ts +6 -0
  46. package/dist/controlCenter.js +7 -2197
  47. package/dist/direct/directAudit.js +234 -225
  48. package/dist/direct/directGuards.d.ts +2 -1
  49. package/dist/direct/directGuards.js +72 -37
  50. package/dist/direct/directPatch.d.ts +6 -1
  51. package/dist/direct/directPatch.js +55 -8
  52. package/dist/direct/directSessionStore.d.ts +16 -6
  53. package/dist/direct/directSessionStore.js +127 -35
  54. package/dist/direct/directVerification.js +8 -16
  55. package/dist/doctor.d.ts +18 -1
  56. package/dist/doctor.js +614 -373
  57. package/dist/goal/acceptanceEngine.d.ts +1 -1
  58. package/dist/goal/goalProgress.js +75 -69
  59. package/dist/goal/goalReport.d.ts +54 -0
  60. package/dist/goal/goalReport.js +197 -0
  61. package/dist/goal/goalStatus.d.ts +8 -0
  62. package/dist/goal/goalStatus.js +10 -3
  63. package/dist/goal/goalStore.d.ts +9 -2
  64. package/dist/goal/goalStore.js +152 -45
  65. package/dist/goal/handoffExport.js +6 -6
  66. package/dist/goal/specKitImport.d.ts +63 -0
  67. package/dist/goal/specKitImport.js +221 -0
  68. package/dist/goal/subgoalSync.js +13 -10
  69. package/dist/goal/worktreeManager.d.ts +2 -0
  70. package/dist/goal/worktreeManager.js +209 -136
  71. package/dist/httpServer.js +126 -44
  72. package/dist/index.js +7 -4
  73. package/dist/logging.d.ts +7 -1
  74. package/dist/logging.js +13 -3
  75. package/dist/policy/projectPolicy.js +5 -2
  76. package/dist/release/releaseGate.d.ts +1 -1
  77. package/dist/release/releaseGate.js +78 -25
  78. package/dist/runner/agentInvocation.d.ts +14 -0
  79. package/dist/runner/agentInvocation.js +96 -4
  80. package/dist/runner/changeCapture.d.ts +14 -6
  81. package/dist/runner/changeCapture.js +287 -81
  82. package/dist/runner/cli.js +7 -6
  83. package/dist/runner/postTaskCleanup.js +60 -7
  84. package/dist/runner/processSecurity.d.ts +56 -0
  85. package/dist/runner/processSecurity.js +373 -0
  86. package/dist/runner/runTask.d.ts +1 -1
  87. package/dist/runner/runTask.js +339 -287
  88. package/dist/runner/simpleProcess.d.ts +3 -0
  89. package/dist/runner/simpleProcess.js +52 -38
  90. package/dist/{taskProgress.d.ts → runner/taskProgress.d.ts} +1 -1
  91. package/dist/{taskProgress.js → runner/taskProgress.js} +2 -2
  92. package/dist/{taskRuntime.d.ts → runner/taskRuntime.d.ts} +1 -1
  93. package/dist/{taskRuntime.js → runner/taskRuntime.js} +3 -2
  94. package/dist/runner/taskStatusStore.d.ts +11 -0
  95. package/dist/runner/taskStatusStore.js +24 -0
  96. package/dist/runner/watch.d.ts +14 -1
  97. package/dist/runner/watch.js +265 -54
  98. package/dist/security/contentRedaction.d.ts +6 -0
  99. package/dist/security/contentRedaction.js +24 -2
  100. package/dist/security/discoveryTokenStore.d.ts +3 -2
  101. package/dist/security/discoveryTokenStore.js +17 -2
  102. package/dist/security/loopbackHost.d.ts +2 -0
  103. package/dist/security/loopbackHost.js +16 -0
  104. package/dist/security/pathGuard.js +32 -17
  105. package/dist/security/planGuard.js +2 -1
  106. package/dist/security/runtimeGuard.js +9 -6
  107. package/dist/security/secretComparison.d.ts +3 -0
  108. package/dist/security/secretComparison.js +11 -0
  109. package/dist/security/sensitiveGuard.d.ts +5 -0
  110. package/dist/security/sensitiveGuard.js +27 -8
  111. package/dist/security/toolInvocationGuard.d.ts +2 -2
  112. package/dist/security/toolInvocationGuard.js +1 -1
  113. package/dist/security/workspaceRootGuard.d.ts +8 -0
  114. package/dist/security/workspaceRootGuard.js +47 -0
  115. package/dist/smoke-test.js +280 -273
  116. package/dist/tools/catalog/index.d.ts +4 -0
  117. package/dist/tools/catalog/index.js +4 -0
  118. package/dist/tools/{toolCatalog.js → catalog/toolCatalog.js} +3 -12
  119. package/dist/tools/{toolRegistry.d.ts → catalog/toolRegistry.d.ts} +3 -3
  120. package/dist/tools/{toolRegistry.js → catalog/toolRegistry.js} +28 -15
  121. package/dist/tools/definitions/toolDefs.d.ts +18 -0
  122. package/dist/tools/definitions/toolDefs.js +1177 -0
  123. package/dist/tools/{auditSession.d.ts → diagnostics/auditSession.d.ts} +1 -1
  124. package/dist/tools/{auditSession.js → diagnostics/auditSession.js} +2 -2
  125. package/dist/tools/{auditTask.d.ts → diagnostics/auditTask.d.ts} +8 -63
  126. package/dist/tools/{auditTask.js → diagnostics/auditTask.js} +111 -37
  127. package/dist/tools/{healthCheck.d.ts → diagnostics/healthCheck.d.ts} +6 -6
  128. package/dist/tools/{healthCheck.js → diagnostics/healthCheck.js} +10 -10
  129. package/dist/tools/diagnostics/index.d.ts +6 -0
  130. package/dist/tools/diagnostics/index.js +6 -0
  131. package/dist/tools/{safeStatus.d.ts → diagnostics/safeStatus.d.ts} +3 -3
  132. package/dist/tools/{safeStatus.js → diagnostics/safeStatus.js} +6 -6
  133. package/dist/tools/{safeViews.d.ts → diagnostics/safeViews.d.ts} +14 -10
  134. package/dist/tools/{safeViews.js → diagnostics/safeViews.js} +25 -15
  135. package/dist/tools/{schemaDriftCheck.d.ts → diagnostics/schemaDriftCheck.d.ts} +1 -1
  136. package/dist/tools/{schemaDriftCheck.js → diagnostics/schemaDriftCheck.js} +2 -2
  137. package/dist/tools/{createDirectSession.d.ts → direct/createDirectSession.d.ts} +1 -1
  138. package/dist/tools/{createDirectSession.js → direct/createDirectSession.js} +8 -8
  139. package/dist/tools/{finalizeDirectSession.d.ts → direct/finalizeDirectSession.d.ts} +2 -2
  140. package/dist/tools/direct/finalizeDirectSession.js +86 -0
  141. package/dist/tools/direct/index.d.ts +3 -0
  142. package/dist/tools/direct/index.js +3 -0
  143. package/dist/tools/{runDirectVerificationBundle.js → direct/runDirectVerificationBundle.js} +2 -2
  144. package/dist/tools/{discoverTools.d.ts → discovery/discoverTools.d.ts} +2 -2
  145. package/dist/tools/{discoverTools.js → discovery/discoverTools.js} +5 -5
  146. package/dist/tools/{explainTool.d.ts → discovery/explainTool.d.ts} +2 -2
  147. package/dist/tools/{explainTool.js → discovery/explainTool.js} +2 -2
  148. package/dist/tools/discovery/index.d.ts +3 -0
  149. package/dist/tools/discovery/index.js +3 -0
  150. package/dist/tools/{invokeDiscoveredTool.d.ts → discovery/invokeDiscoveredTool.d.ts} +2 -2
  151. package/dist/tools/{invokeDiscoveredTool.js → discovery/invokeDiscoveredTool.js} +5 -5
  152. package/dist/tools/dispatch/coreDispatch.d.ts +9 -0
  153. package/dist/tools/dispatch/coreDispatch.js +283 -0
  154. package/dist/tools/dispatch/diagnosticDispatch.d.ts +12 -0
  155. package/dist/tools/dispatch/diagnosticDispatch.js +80 -0
  156. package/dist/tools/dispatch/directDispatch.d.ts +8 -0
  157. package/dist/tools/dispatch/directDispatch.js +116 -0
  158. package/dist/tools/dispatch/goalDispatch.d.ts +8 -0
  159. package/dist/tools/dispatch/goalDispatch.js +92 -0
  160. package/dist/tools/dispatch/releaseDispatch.d.ts +8 -0
  161. package/dist/tools/dispatch/releaseDispatch.js +46 -0
  162. package/dist/tools/dispatch/types.d.ts +23 -0
  163. package/dist/tools/dispatch/types.js +15 -0
  164. package/dist/tools/dispatch/validation.d.ts +7 -0
  165. package/dist/tools/dispatch/validation.js +71 -0
  166. package/dist/tools/{getPlan.js → goals/getPlan.js} +4 -4
  167. package/dist/tools/{goalSubgoalTask.d.ts → goals/goalSubgoalTask.d.ts} +2 -2
  168. package/dist/tools/goals/goalSubgoalTask.js +118 -0
  169. package/dist/tools/goals/index.d.ts +3 -0
  170. package/dist/tools/goals/index.js +3 -0
  171. package/dist/tools/{savePlan.js → goals/savePlan.js} +28 -8
  172. package/dist/tools/registry.d.ts +10 -14
  173. package/dist/tools/registry.js +47 -1651
  174. package/dist/tools/{checkReleaseGate.d.ts → release/checkReleaseGate.d.ts} +1 -1
  175. package/dist/tools/{checkReleaseGate.js → release/checkReleaseGate.js} +3 -3
  176. package/dist/tools/release/index.d.ts +2 -0
  177. package/dist/tools/release/index.js +2 -0
  178. package/dist/tools/{releaseMode.d.ts → release/releaseMode.d.ts} +2 -2
  179. package/dist/tools/{releaseMode.js → release/releaseMode.js} +46 -26
  180. package/dist/tools/tasks/cancelTask.d.ts +11 -0
  181. package/dist/tools/tasks/cancelTask.js +85 -0
  182. package/dist/tools/{createTask.d.ts → tasks/createTask.d.ts} +12 -4
  183. package/dist/tools/{createTask.js → tasks/createTask.js} +46 -31
  184. package/dist/tools/{diagnoseTask.d.ts → tasks/diagnoseTask.d.ts} +1 -1
  185. package/dist/tools/{diagnoseTask.js → tasks/diagnoseTask.js} +8 -8
  186. package/dist/tools/{evidencePack.d.ts → tasks/evidencePack.d.ts} +6 -0
  187. package/dist/tools/tasks/evidencePack.js +387 -0
  188. package/dist/tools/{getTaskFile.js → tasks/getTaskFile.js} +4 -4
  189. package/dist/tools/{getTaskStatus.d.ts → tasks/getTaskStatus.d.ts} +6 -1
  190. package/dist/tools/{getTaskStatus.js → tasks/getTaskStatus.js} +5 -5
  191. package/dist/tools/{getTaskStdoutTail.js → tasks/getTaskStdoutTail.js} +13 -11
  192. package/dist/tools/{getTaskSummary.js → tasks/getTaskSummary.js} +33 -26
  193. package/dist/tools/tasks/index.d.ts +18 -0
  194. package/dist/tools/tasks/index.js +18 -0
  195. package/dist/tools/tasks/killTask.d.ts +1 -0
  196. package/dist/tools/{listTasks.d.ts → tasks/listTasks.d.ts} +1 -1
  197. package/dist/tools/{listTasks.js → tasks/listTasks.js} +3 -3
  198. package/dist/tools/{reconcileTasks.d.ts → tasks/reconcileTasks.d.ts} +1 -1
  199. package/dist/tools/{reconcileTasks.js → tasks/reconcileTasks.js} +64 -66
  200. package/dist/tools/{retryTask.d.ts → tasks/retryTask.d.ts} +2 -2
  201. package/dist/tools/tasks/retryTask.js +60 -0
  202. package/dist/tools/{runTaskLoop.d.ts → tasks/runTaskLoop.d.ts} +6 -6
  203. package/dist/tools/{runTaskLoop.js → tasks/runTaskLoop.js} +59 -31
  204. package/dist/tools/tasks/runVerification.js +38 -0
  205. package/dist/tools/{taskLineage.js → tasks/taskLineage.js} +8 -7
  206. package/dist/tools/{taskOutputs.js → tasks/taskOutputs.js} +17 -16
  207. package/dist/tools/{androidDoctor.js → workspace/androidDoctor.js} +16 -10
  208. package/dist/tools/{applyPatch.d.ts → workspace/applyPatch.d.ts} +1 -1
  209. package/dist/tools/workspace/applyPatch.js +53 -0
  210. package/dist/tools/{discardWorktree.js → workspace/discardWorktree.js} +3 -3
  211. package/dist/tools/workspace/index.d.ts +10 -0
  212. package/dist/tools/workspace/index.js +10 -0
  213. package/dist/tools/{listAgents.d.ts → workspace/listAgents.d.ts} +5 -0
  214. package/dist/tools/{listAgents.js → workspace/listAgents.js} +8 -4
  215. package/dist/tools/{listWorkspace.js → workspace/listWorkspace.js} +3 -3
  216. package/dist/tools/{mergeWorktree.js → workspace/mergeWorktree.js} +3 -3
  217. package/dist/tools/{readWorkspaceFile.js → workspace/readWorkspaceFile.js} +8 -8
  218. package/dist/tools/{recommendAgentForTask.js → workspace/recommendAgentForTask.js} +3 -3
  219. package/dist/tools/{searchWorkspace.js → workspace/searchWorkspace.js} +5 -5
  220. package/dist/tools/{syncFile.d.ts → workspace/syncFile.d.ts} +1 -1
  221. package/dist/tools/workspace/syncFile.js +134 -0
  222. package/dist/utils/atomicFile.d.ts +7 -0
  223. package/dist/utils/atomicFile.js +48 -0
  224. package/dist/utils/boundedFile.d.ts +8 -0
  225. package/dist/utils/boundedFile.js +93 -0
  226. package/dist/utils/lockedJsonFile.d.ts +15 -0
  227. package/dist/utils/lockedJsonFile.js +224 -0
  228. package/dist/utils/platform.d.ts +11 -0
  229. package/dist/utils/platform.js +26 -0
  230. package/dist/utils/stableJson.d.ts +2 -0
  231. package/dist/utils/stableJson.js +12 -0
  232. package/dist/version.d.ts +3 -2
  233. package/dist/version.js +3 -2
  234. package/dist/watcherStatus.d.ts +2 -2
  235. package/dist/watcherStatus.js +18 -0
  236. package/docs/CODE_WIKI.md +1648 -0
  237. package/docs/agentseal-integration.md +150 -0
  238. package/docs/architecture.md +23 -0
  239. package/docs/assets/patchwarden-desktop-onboarding.png +0 -0
  240. package/docs/assets/patchwarden-oss-demo.gif +0 -0
  241. package/docs/control-center/README.md +4 -4
  242. package/docs/dashboard-overview.md +86 -0
  243. package/docs/demo.md +8 -0
  244. package/docs/desktop-app.md +175 -0
  245. package/docs/direct-session-workflow.md +98 -0
  246. package/docs/evidence-pack-schema.md +215 -0
  247. package/docs/lineage-evidence-pack-workflow.md +127 -0
  248. package/docs/mcp-inspector-testing.md +200 -0
  249. package/docs/open-source-application.md +168 -0
  250. package/docs/opencode-worker.md +151 -0
  251. package/docs/openhands-worker.md +181 -0
  252. package/docs/release-checklist.md +1 -1
  253. package/docs/release-evidence.md +82 -0
  254. package/docs/spec-kit-integration.md +131 -0
  255. package/docs/task-safe-review-workflow.md +98 -0
  256. package/docs/threat-model.md +97 -0
  257. package/docs/user-feedback.md +40 -0
  258. package/docs/why-patchwarden.md +110 -0
  259. package/examples/config.example.json +4 -2
  260. package/package.json +28 -11
  261. package/scripts/README.md +15 -6
  262. package/scripts/build.js +11 -0
  263. package/scripts/checks/brand-check.js +3 -0
  264. package/scripts/checks/build-output-check.js +37 -0
  265. package/scripts/checks/control-center-smoke.js +447 -6
  266. package/scripts/checks/control-smoke.js +19 -8
  267. package/scripts/checks/http-mcp-smoke.js +82 -4
  268. package/scripts/checks/lifecycle-smoke.js +39 -33
  269. package/scripts/checks/mcp-manifest-check.js +1 -1
  270. package/scripts/checks/mcp-smoke.js +30 -4
  271. package/scripts/checks/package-manifest-check.js +20 -7
  272. package/scripts/checks/unit-tests.js +3 -5
  273. package/scripts/checks/watcher-supervisor-smoke.js +9 -0
  274. package/scripts/control/get-patchwarden-health.ps1 +1 -1
  275. package/scripts/control/manage-patchwarden.ps1 +69 -4
  276. package/scripts/control/provision-patchwarden-tunnel.ps1 +127 -0
  277. package/scripts/control/run-background-supervisor.ps1 +41 -0
  278. package/scripts/control/start-patchwarden-tunnel.ps1 +126 -32
  279. package/scripts/generate-demo-gif.py +320 -0
  280. package/{PatchWarden-Control-Tray.cmd → scripts/launchers/PatchWarden-Control-Tray.cmd} +3 -3
  281. package/scripts/launchers/PatchWarden-Control.cmd +6 -0
  282. package/{PatchWarden-Desktop.cmd → scripts/launchers/PatchWarden-Desktop.cmd} +2 -2
  283. package/scripts/launchers/Restart-PatchWarden-Control.cmd +6 -0
  284. package/{Stop-PatchWarden.cmd → scripts/launchers/Stop-PatchWarden.cmd} +2 -2
  285. package/scripts/lib/clean-generated-output.js +11 -0
  286. package/scripts/lib/file-discovery.js +12 -0
  287. package/scripts/release/desktop-preflight.js +211 -0
  288. package/scripts/release/pack-clean.js +59 -14
  289. package/src/assessments/agentAssessor.ts +29 -15
  290. package/src/assessments/assessmentStore.ts +55 -43
  291. package/src/assessments/confirmCli.ts +5 -4
  292. package/src/config.ts +105 -11
  293. package/src/control/fileManager.ts +40 -0
  294. package/src/control/middleware/auth.ts +35 -0
  295. package/src/control/middleware/static.ts +84 -0
  296. package/src/control/routeTable.ts +301 -0
  297. package/src/control/routes/audit.ts +329 -0
  298. package/src/control/routes/evidence.ts +107 -0
  299. package/src/control/routes/lineage.ts +92 -0
  300. package/src/control/routes/policy.ts +81 -0
  301. package/src/control/routes/process.ts +505 -0
  302. package/src/control/routes/sessions.ts +314 -0
  303. package/src/control/routes/status.ts +405 -0
  304. package/src/control/routes/taskActions.ts +214 -0
  305. package/src/control/routes/tasks.ts +331 -0
  306. package/src/control/routes/workspace.ts +234 -0
  307. package/src/control/runtime.ts +508 -0
  308. package/src/control/server.ts +165 -0
  309. package/src/control/shared.ts +360 -0
  310. package/src/controlCenter.ts +7 -2347
  311. package/src/direct/directAudit.ts +17 -9
  312. package/src/direct/directGuards.ts +100 -51
  313. package/src/direct/directPatch.ts +95 -8
  314. package/src/direct/directSessionStore.ts +211 -55
  315. package/src/direct/directVerification.ts +9 -23
  316. package/src/doctor.ts +766 -492
  317. package/src/goal/acceptanceEngine.ts +1 -1
  318. package/src/goal/goalProgress.ts +17 -13
  319. package/src/goal/goalReport.ts +263 -0
  320. package/src/goal/goalStatus.ts +25 -3
  321. package/src/goal/goalStore.ts +241 -54
  322. package/src/goal/handoffExport.ts +6 -6
  323. package/src/goal/specKitImport.ts +355 -0
  324. package/src/goal/subgoalSync.ts +15 -10
  325. package/src/goal/worktreeManager.ts +139 -22
  326. package/src/httpServer.ts +130 -44
  327. package/src/index.ts +7 -4
  328. package/src/logging.ts +20 -4
  329. package/src/policy/projectPolicy.ts +5 -2
  330. package/src/release/releaseGate.ts +74 -27
  331. package/src/runner/agentInvocation.ts +126 -4
  332. package/src/runner/changeCapture.ts +342 -80
  333. package/src/runner/cli.ts +7 -6
  334. package/src/runner/postTaskCleanup.ts +55 -7
  335. package/src/runner/processSecurity.ts +433 -0
  336. package/src/runner/runTask.ts +441 -292
  337. package/src/runner/simpleProcess.ts +68 -33
  338. package/src/{taskProgress.ts → runner/taskProgress.ts} +3 -3
  339. package/src/{taskRuntime.ts → runner/taskRuntime.ts} +4 -3
  340. package/src/runner/taskStatusStore.ts +54 -0
  341. package/src/runner/watch.ts +290 -57
  342. package/src/security/contentRedaction.ts +31 -2
  343. package/src/security/discoveryTokenStore.ts +18 -4
  344. package/src/security/loopbackHost.ts +19 -0
  345. package/src/security/pathGuard.ts +35 -16
  346. package/src/security/planGuard.ts +2 -1
  347. package/src/security/runtimeGuard.ts +9 -6
  348. package/src/security/secretComparison.ts +13 -0
  349. package/src/security/sensitiveGuard.ts +27 -8
  350. package/src/security/toolInvocationGuard.ts +2 -2
  351. package/src/security/workspaceRootGuard.ts +53 -0
  352. package/src/smoke-test.ts +276 -273
  353. package/src/tools/catalog/index.ts +4 -0
  354. package/src/tools/{toolCatalog.ts → catalog/toolCatalog.ts} +3 -12
  355. package/src/tools/{toolRegistry.ts → catalog/toolRegistry.ts} +29 -16
  356. package/src/tools/definitions/toolDefs.ts +1264 -0
  357. package/src/tools/{auditSession.ts → diagnostics/auditSession.ts} +2 -2
  358. package/src/tools/{auditTask.ts → diagnostics/auditTask.ts} +196 -89
  359. package/src/tools/{healthCheck.ts → diagnostics/healthCheck.ts} +11 -11
  360. package/src/tools/diagnostics/index.ts +6 -0
  361. package/src/tools/{safeStatus.ts → diagnostics/safeStatus.ts} +7 -7
  362. package/src/tools/{safeViews.ts → diagnostics/safeViews.ts} +29 -19
  363. package/src/tools/{schemaDriftCheck.ts → diagnostics/schemaDriftCheck.ts} +3 -3
  364. package/src/tools/{createDirectSession.ts → direct/createDirectSession.ts} +9 -9
  365. package/src/tools/{finalizeDirectSession.ts → direct/finalizeDirectSession.ts} +11 -9
  366. package/src/tools/direct/index.ts +3 -0
  367. package/src/tools/{runDirectVerificationBundle.ts → direct/runDirectVerificationBundle.ts} +2 -2
  368. package/src/tools/{discoverTools.ts → discovery/discoverTools.ts} +6 -6
  369. package/src/tools/{explainTool.ts → discovery/explainTool.ts} +3 -3
  370. package/src/tools/discovery/index.ts +3 -0
  371. package/src/tools/{invokeDiscoveredTool.ts → discovery/invokeDiscoveredTool.ts} +7 -7
  372. package/src/tools/dispatch/coreDispatch.ts +379 -0
  373. package/src/tools/dispatch/diagnosticDispatch.ts +106 -0
  374. package/src/tools/dispatch/directDispatch.ts +168 -0
  375. package/src/tools/dispatch/goalDispatch.ts +128 -0
  376. package/src/tools/dispatch/releaseDispatch.ts +66 -0
  377. package/src/tools/dispatch/types.ts +24 -0
  378. package/src/tools/dispatch/validation.ts +78 -0
  379. package/src/tools/{getPlan.ts → goals/getPlan.ts} +4 -4
  380. package/src/tools/{goalSubgoalTask.ts → goals/goalSubgoalTask.ts} +43 -28
  381. package/src/tools/goals/index.ts +3 -0
  382. package/src/tools/{savePlan.ts → goals/savePlan.ts} +38 -8
  383. package/src/tools/registry.ts +54 -1858
  384. package/src/tools/{checkReleaseGate.ts → release/checkReleaseGate.ts} +3 -3
  385. package/src/tools/release/index.ts +2 -0
  386. package/src/tools/{releaseMode.ts → release/releaseMode.ts} +42 -24
  387. package/src/tools/tasks/cancelTask.ts +109 -0
  388. package/src/tools/{createTask.ts → tasks/createTask.ts} +56 -33
  389. package/src/tools/{diagnoseTask.ts → tasks/diagnoseTask.ts} +8 -8
  390. package/src/tools/tasks/evidencePack.ts +504 -0
  391. package/src/tools/{getTaskFile.ts → tasks/getTaskFile.ts} +4 -4
  392. package/src/tools/{getTaskStatus.ts → tasks/getTaskStatus.ts} +7 -5
  393. package/src/tools/{getTaskStdoutTail.ts → tasks/getTaskStdoutTail.ts} +13 -11
  394. package/src/tools/{getTaskSummary.ts → tasks/getTaskSummary.ts} +44 -33
  395. package/src/tools/tasks/index.ts +18 -0
  396. package/src/tools/{listTasks.ts → tasks/listTasks.ts} +4 -4
  397. package/src/tools/{reconcileTasks.ts → tasks/reconcileTasks.ts} +68 -66
  398. package/src/tools/tasks/retryTask.ts +69 -0
  399. package/src/tools/{runTaskLoop.ts → tasks/runTaskLoop.ts} +70 -35
  400. package/src/tools/{runVerification.ts → tasks/runVerification.ts} +6 -3
  401. package/src/tools/{taskLineage.ts → tasks/taskLineage.ts} +8 -7
  402. package/src/tools/{taskOutputs.ts → tasks/taskOutputs.ts} +27 -20
  403. package/src/tools/{androidDoctor.ts → workspace/androidDoctor.ts} +15 -10
  404. package/src/tools/{applyPatch.ts → workspace/applyPatch.ts} +38 -16
  405. package/src/tools/{discardWorktree.ts → workspace/discardWorktree.ts} +3 -3
  406. package/src/tools/workspace/index.ts +10 -0
  407. package/src/tools/{listAgents.ts → workspace/listAgents.ts} +11 -4
  408. package/src/tools/{listWorkspace.ts → workspace/listWorkspace.ts} +3 -3
  409. package/src/tools/{mergeWorktree.ts → workspace/mergeWorktree.ts} +3 -3
  410. package/src/tools/{readWorkspaceFile.ts → workspace/readWorkspaceFile.ts} +8 -8
  411. package/src/tools/{recommendAgentForTask.ts → workspace/recommendAgentForTask.ts} +3 -3
  412. package/src/tools/{searchWorkspace.ts → workspace/searchWorkspace.ts} +5 -5
  413. package/src/tools/workspace/syncFile.ts +292 -0
  414. package/src/utils/atomicFile.ts +58 -0
  415. package/src/utils/boundedFile.ts +116 -0
  416. package/src/utils/lockedJsonFile.ts +251 -0
  417. package/src/utils/platform.ts +31 -0
  418. package/src/utils/stableJson.ts +12 -0
  419. package/src/version.ts +3 -2
  420. package/src/watcherStatus.ts +19 -1
  421. package/ui/desktop-bootstrap.js +11 -0
  422. package/ui/desktop-bridge.js +36 -0
  423. package/ui/desktop.css +160 -0
  424. package/ui/getting-started.js +93 -0
  425. package/ui/i18n.js +484 -0
  426. package/ui/log-parser.js +30 -0
  427. package/ui/pages/audit.html +204 -3
  428. package/ui/pages/dashboard.html +937 -79
  429. package/ui/pages/direct-sessions.html +609 -60
  430. package/ui/pages/getting-started.html +43 -0
  431. package/ui/pages/logs.html +105 -22
  432. package/ui/pages/settings.html +101 -0
  433. package/ui/pages/task-detail.html +468 -438
  434. package/ui/pages/tasks.html +648 -65
  435. package/ui/pages/workspace.html +38 -1
  436. package/ui/settings.js +245 -0
  437. package/PatchWarden-Control.cmd +0 -6
  438. package/Restart-PatchWarden-Control.cmd +0 -6
  439. package/dist/test/unit/acceptance-engine.test.d.ts +0 -1
  440. package/dist/test/unit/acceptance-engine.test.js +0 -228
  441. package/dist/test/unit/agent-router.test.d.ts +0 -1
  442. package/dist/test/unit/agent-router.test.js +0 -287
  443. package/dist/test/unit/android-doctor.test.d.ts +0 -1
  444. package/dist/test/unit/android-doctor.test.js +0 -118
  445. package/dist/test/unit/audit-checks.test.d.ts +0 -1
  446. package/dist/test/unit/audit-checks.test.js +0 -350
  447. package/dist/test/unit/chinese-path.test.d.ts +0 -1
  448. package/dist/test/unit/chinese-path.test.js +0 -91
  449. package/dist/test/unit/command-guard.test.d.ts +0 -1
  450. package/dist/test/unit/command-guard.test.js +0 -160
  451. package/dist/test/unit/diagnose-task.test.d.ts +0 -1
  452. package/dist/test/unit/diagnose-task.test.js +0 -457
  453. package/dist/test/unit/direct-guards.test.d.ts +0 -1
  454. package/dist/test/unit/direct-guards.test.js +0 -213
  455. package/dist/test/unit/discovery-token-store.test.d.ts +0 -1
  456. package/dist/test/unit/discovery-token-store.test.js +0 -139
  457. package/dist/test/unit/evidence-pack.test.d.ts +0 -1
  458. package/dist/test/unit/evidence-pack.test.js +0 -130
  459. package/dist/test/unit/goal-graph.test.d.ts +0 -1
  460. package/dist/test/unit/goal-graph.test.js +0 -298
  461. package/dist/test/unit/goal-progress.test.d.ts +0 -1
  462. package/dist/test/unit/goal-progress.test.js +0 -381
  463. package/dist/test/unit/goal-status.test.d.ts +0 -1
  464. package/dist/test/unit/goal-status.test.js +0 -215
  465. package/dist/test/unit/goal-store.test.d.ts +0 -1
  466. package/dist/test/unit/goal-store.test.js +0 -253
  467. package/dist/test/unit/goal-subgoal-task.test.d.ts +0 -1
  468. package/dist/test/unit/goal-subgoal-task.test.js +0 -55
  469. package/dist/test/unit/goal-tools-registry.test.d.ts +0 -1
  470. package/dist/test/unit/goal-tools-registry.test.js +0 -190
  471. package/dist/test/unit/handoff-export.test.d.ts +0 -1
  472. package/dist/test/unit/handoff-export.test.js +0 -263
  473. package/dist/test/unit/invoke-discovered-tool.test.d.ts +0 -1
  474. package/dist/test/unit/invoke-discovered-tool.test.js +0 -167
  475. package/dist/test/unit/logging.test.d.ts +0 -1
  476. package/dist/test/unit/logging.test.js +0 -397
  477. package/dist/test/unit/path-guard.test.d.ts +0 -1
  478. package/dist/test/unit/path-guard.test.js +0 -109
  479. package/dist/test/unit/post-task-cleanup.test.d.ts +0 -1
  480. package/dist/test/unit/post-task-cleanup.test.js +0 -48
  481. package/dist/test/unit/project-policy-release-mode.test.d.ts +0 -1
  482. package/dist/test/unit/project-policy-release-mode.test.js +0 -125
  483. package/dist/test/unit/reconcile-tasks.test.d.ts +0 -1
  484. package/dist/test/unit/reconcile-tasks.test.js +0 -456
  485. package/dist/test/unit/release-gate.test.d.ts +0 -1
  486. package/dist/test/unit/release-gate.test.js +0 -242
  487. package/dist/test/unit/run-task-loop.test.d.ts +0 -1
  488. package/dist/test/unit/run-task-loop.test.js +0 -380
  489. package/dist/test/unit/safe-status.test.d.ts +0 -1
  490. package/dist/test/unit/safe-status.test.js +0 -165
  491. package/dist/test/unit/safe-views.test.d.ts +0 -1
  492. package/dist/test/unit/safe-views.test.js +0 -171
  493. package/dist/test/unit/schema-drift-check.test.d.ts +0 -1
  494. package/dist/test/unit/schema-drift-check.test.js +0 -176
  495. package/dist/test/unit/sensitive-guard.test.d.ts +0 -1
  496. package/dist/test/unit/sensitive-guard.test.js +0 -104
  497. package/dist/test/unit/subgoal-sync.test.d.ts +0 -1
  498. package/dist/test/unit/subgoal-sync.test.js +0 -183
  499. package/dist/test/unit/sync-file.test.d.ts +0 -1
  500. package/dist/test/unit/sync-file.test.js +0 -154
  501. package/dist/test/unit/tool-invocation-guard.test.d.ts +0 -1
  502. package/dist/test/unit/tool-invocation-guard.test.js +0 -432
  503. package/dist/test/unit/tool-usage-stats.test.d.ts +0 -1
  504. package/dist/test/unit/tool-usage-stats.test.js +0 -300
  505. package/dist/test/unit/toolSearch.test.d.ts +0 -1
  506. package/dist/test/unit/toolSearch.test.js +0 -571
  507. package/dist/test/unit/watcher-status.test.d.ts +0 -1
  508. package/dist/test/unit/watcher-status.test.js +0 -169
  509. package/dist/test/unit/worktree-manager.test.d.ts +0 -1
  510. package/dist/test/unit/worktree-manager.test.js +0 -176
  511. package/dist/tools/applyPatch.js +0 -41
  512. package/dist/tools/cancelTask.d.ts +0 -30
  513. package/dist/tools/cancelTask.js +0 -64
  514. package/dist/tools/evidencePack.js +0 -168
  515. package/dist/tools/finalizeDirectSession.js +0 -84
  516. package/dist/tools/goalSubgoalTask.js +0 -110
  517. package/dist/tools/killTask.d.ts +0 -15
  518. package/dist/tools/retryTask.js +0 -45
  519. package/dist/tools/runVerification.js +0 -36
  520. package/dist/tools/syncFile.js +0 -65
  521. package/docs/control-center/control-center-daily-driver.md +0 -211
  522. package/docs/control-center/control-center-mvp.md +0 -205
  523. package/docs/control-center/control-center-phase2.md +0 -159
  524. package/docs/release-v0.6.0.md +0 -71
  525. package/docs/release-v0.6.1.md +0 -75
  526. package/docs/release-v0.6.4.md +0 -45
  527. package/src/test/unit/acceptance-engine.test.ts +0 -261
  528. package/src/test/unit/agent-router.test.ts +0 -342
  529. package/src/test/unit/android-doctor.test.ts +0 -158
  530. package/src/test/unit/audit-checks.test.ts +0 -567
  531. package/src/test/unit/chinese-path.test.ts +0 -106
  532. package/src/test/unit/command-guard.test.ts +0 -221
  533. package/src/test/unit/diagnose-task.test.ts +0 -544
  534. package/src/test/unit/direct-guards.test.ts +0 -297
  535. package/src/test/unit/discovery-token-store.test.ts +0 -181
  536. package/src/test/unit/evidence-pack.test.ts +0 -142
  537. package/src/test/unit/goal-graph.test.ts +0 -347
  538. package/src/test/unit/goal-progress.test.ts +0 -538
  539. package/src/test/unit/goal-status.test.ts +0 -270
  540. package/src/test/unit/goal-store.test.ts +0 -318
  541. package/src/test/unit/goal-subgoal-task.test.ts +0 -72
  542. package/src/test/unit/goal-tools-registry.test.ts +0 -243
  543. package/src/test/unit/handoff-export.test.ts +0 -295
  544. package/src/test/unit/invoke-discovered-tool.test.ts +0 -216
  545. package/src/test/unit/logging.test.ts +0 -497
  546. package/src/test/unit/path-guard.test.ts +0 -150
  547. package/src/test/unit/post-task-cleanup.test.ts +0 -53
  548. package/src/test/unit/project-policy-release-mode.test.ts +0 -156
  549. package/src/test/unit/reconcile-tasks.test.ts +0 -551
  550. package/src/test/unit/release-gate.test.ts +0 -314
  551. package/src/test/unit/run-task-loop.test.ts +0 -425
  552. package/src/test/unit/safe-status.test.ts +0 -187
  553. package/src/test/unit/safe-views.test.ts +0 -184
  554. package/src/test/unit/schema-drift-check.test.ts +0 -260
  555. package/src/test/unit/sensitive-guard.test.ts +0 -124
  556. package/src/test/unit/subgoal-sync.test.ts +0 -236
  557. package/src/test/unit/sync-file.test.ts +0 -231
  558. package/src/test/unit/tool-invocation-guard.test.ts +0 -542
  559. package/src/test/unit/tool-usage-stats.test.ts +0 -384
  560. package/src/test/unit/toolSearch.test.ts +0 -756
  561. package/src/test/unit/watcher-status.test.ts +0 -190
  562. package/src/test/unit/worktree-manager.test.ts +0 -247
  563. package/src/tools/cancelTask.ts +0 -70
  564. package/src/tools/evidencePack.ts +0 -205
  565. package/src/tools/retryTask.ts +0 -53
  566. package/src/tools/syncFile.ts +0 -122
  567. /package/dist/tools/{toolCatalog.d.ts → catalog/toolCatalog.d.ts} +0 -0
  568. /package/dist/tools/{toolSearch.d.ts → catalog/toolSearch.d.ts} +0 -0
  569. /package/dist/tools/{toolSearch.js → catalog/toolSearch.js} +0 -0
  570. /package/dist/tools/{toolUsageStats.d.ts → catalog/toolUsageStats.d.ts} +0 -0
  571. /package/dist/tools/{toolUsageStats.js → catalog/toolUsageStats.js} +0 -0
  572. /package/dist/tools/{runDirectVerificationBundle.d.ts → direct/runDirectVerificationBundle.d.ts} +0 -0
  573. /package/dist/tools/{getPlan.d.ts → goals/getPlan.d.ts} +0 -0
  574. /package/dist/tools/{savePlan.d.ts → goals/savePlan.d.ts} +0 -0
  575. /package/dist/tools/{getTaskFile.d.ts → tasks/getTaskFile.d.ts} +0 -0
  576. /package/dist/tools/{getTaskProgress.d.ts → tasks/getTaskProgress.d.ts} +0 -0
  577. /package/dist/tools/{getTaskProgress.js → tasks/getTaskProgress.js} +0 -0
  578. /package/dist/tools/{getTaskStdoutTail.d.ts → tasks/getTaskStdoutTail.d.ts} +0 -0
  579. /package/dist/tools/{getTaskSummary.d.ts → tasks/getTaskSummary.d.ts} +0 -0
  580. /package/dist/tools/{killTask.js → tasks/killTask.js} +0 -0
  581. /package/dist/tools/{runVerification.d.ts → tasks/runVerification.d.ts} +0 -0
  582. /package/dist/tools/{taskLineage.d.ts → tasks/taskLineage.d.ts} +0 -0
  583. /package/dist/tools/{taskOutputs.d.ts → tasks/taskOutputs.d.ts} +0 -0
  584. /package/dist/tools/{waitForTask.d.ts → tasks/waitForTask.d.ts} +0 -0
  585. /package/dist/tools/{waitForTask.js → tasks/waitForTask.js} +0 -0
  586. /package/dist/tools/{androidDoctor.d.ts → workspace/androidDoctor.d.ts} +0 -0
  587. /package/dist/tools/{discardWorktree.d.ts → workspace/discardWorktree.d.ts} +0 -0
  588. /package/dist/tools/{listWorkspace.d.ts → workspace/listWorkspace.d.ts} +0 -0
  589. /package/dist/tools/{mergeWorktree.d.ts → workspace/mergeWorktree.d.ts} +0 -0
  590. /package/dist/tools/{readWorkspaceFile.d.ts → workspace/readWorkspaceFile.d.ts} +0 -0
  591. /package/dist/tools/{recommendAgentForTask.d.ts → workspace/recommendAgentForTask.d.ts} +0 -0
  592. /package/dist/tools/{searchWorkspace.d.ts → workspace/searchWorkspace.d.ts} +0 -0
  593. /package/src/tools/{toolSearch.ts → catalog/toolSearch.ts} +0 -0
  594. /package/src/tools/{toolUsageStats.ts → catalog/toolUsageStats.ts} +0 -0
  595. /package/src/tools/{getTaskProgress.ts → tasks/getTaskProgress.ts} +0 -0
  596. /package/src/tools/{killTask.ts → tasks/killTask.ts} +0 -0
  597. /package/src/tools/{waitForTask.ts → tasks/waitForTask.ts} +0 -0
@@ -1,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
 
@@ -1,5 +1,3 @@
1
- // @ts-nocheck
2
-
3
1
  interface AuditCheck {
4
2
  name: string;
5
3
  result: "pass" | "warn" | "fail";
@@ -33,13 +31,56 @@ export interface AuditTaskOutput {
33
31
  manual_verification_items: string[];
34
32
  recommended_next_actions: string[];
35
33
  }
36
- import { readFileSync, existsSync, writeFileSync, readdirSync, statSync } from "node:fs";
34
+ import { readFileSync, existsSync, opendirSync, statSync } from "node:fs";
37
35
  import { join, resolve, relative, basename, sep, isAbsolute } from "node:path";
38
- import { getTasksDir, getConfig } from "../config.js";
39
- import { guardReadPath, guardWorkspacePath } from "../security/pathGuard.js";
40
- import { guardSensitivePath, isSensitivePath } from "../security/sensitiveGuard.js";
41
- import { evaluateAcceptance } from "../goal/acceptanceEngine.js";
42
- import { renderAcceptanceMarkdown } from "../goal/acceptanceTemplate.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";
48
+
49
+ interface ExtractedCommand {
50
+ type: "npm-run" | "npm-bare" | "node" | "npx" | "python";
51
+ name: string;
52
+ }
53
+
54
+ interface TaskStatusData {
55
+ status?: string;
56
+ resolved_repo_path?: string;
57
+ repo_path?: string;
58
+ new_out_of_scope_changes?: Array<{ path: string; change: string }>;
59
+ out_of_scope_changes?: Array<{ path: string; change: string }>;
60
+ test_command?: string;
61
+ verify_commands?: string[];
62
+ forbidden?: string[];
63
+ done_evidence?: string[];
64
+ scope?: string[];
65
+ verification?: string[];
66
+ goal?: string;
67
+ artifact_status?: string;
68
+ acceptance_status?: string;
69
+ updated_at?: string;
70
+ }
71
+
72
+ interface ChangedFilesEvidence {
73
+ changed_files?: ChangedFile[];
74
+ artifact_hygiene?: {
75
+ counts?: {
76
+ tracked_build_artifacts?: number | string;
77
+ ignored_untracked_artifacts?: number | string;
78
+ runtime_generated_files?: number | string;
79
+ suspicious_changes?: number | string;
80
+ };
81
+ };
82
+ }
83
+
43
84
  // Release claim patterns — anything that claims remote publish/release/deploy
44
85
  const RELEASE_PATTERNS = [
45
86
  /npm\s+package\s+version\s+published/i,
@@ -51,8 +92,12 @@ const RELEASE_PATTERNS = [
51
92
  /npm\s+publish\s+completed/i,
52
93
  /deploy(ed|ment)?\s+(to|on)\s+(npm|registry|github)/i,
53
94
  ];
54
- function scanForReleaseClaims(text) {
55
- const found = [];
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;
99
+ function scanForReleaseClaims(text: string): string[] {
100
+ const found: string[] = [];
56
101
  for (const pattern of RELEASE_PATTERNS) {
57
102
  const match = text.match(pattern);
58
103
  if (match)
@@ -60,24 +105,50 @@ function scanForReleaseClaims(text) {
60
105
  }
61
106
  return found;
62
107
  }
63
- function findMdFiles(dir, maxDepth = 3) {
64
- const results = [];
65
- if (!existsSync(dir) || maxDepth <= 0)
66
- return results;
67
- try {
68
- const entries = readdirSync(dir, { withFileTypes: true });
69
- for (const e of entries) {
70
- const full = join(dir, e.name);
71
- if (e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules") {
72
- results.push(...findMdFiles(full, maxDepth - 1));
73
- }
74
- else if (e.isFile() && e.name.endsWith(".md")) {
75
- results.push(full);
108
+ function findMdFiles(
109
+ dir: string,
110
+ maxDepth = 3,
111
+ maxFiles = MAX_AUDIT_DOC_FILES,
112
+ ): { files: string[]; truncated: boolean } {
113
+ const results: string[] = [];
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
+ }
76
135
  }
77
- }
136
+ } catch { /* skip unreadable dirs */ }
137
+ finally { try { handle?.closeSync(); } catch { /* best effort */ } }
78
138
  }
79
- catch { /* skip unreadable dirs */ }
80
- 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
+ };
81
152
  }
82
153
  // ── v0.7.2: New audit checks (exported for testing) ────────────────
83
154
  /**
@@ -86,7 +157,7 @@ function findMdFiles(dir, maxDepth = 3) {
86
157
  * `*` matches a single path segment (no `/`).
87
158
  * Path separators in the pattern are expected to be `/`.
88
159
  */
89
- function globToRegExp(pattern) {
160
+ function globToRegExp(pattern: string): RegExp {
90
161
  // Normalize backslashes to forward slashes for matching consistency.
91
162
  const normalized = pattern.replace(/\\/g, "/");
92
163
  let re = "^";
@@ -127,7 +198,7 @@ function globToRegExp(pattern) {
127
198
  * Returns pass when changed files do not match any forbidden pattern.
128
199
  * Returns fail when any changed file path (or old_path) matches a forbidden glob.
129
200
  */
130
- export function checkForbiddenScope(changedFiles, forbidden) {
201
+ export function checkForbiddenScope(changedFiles: ChangedFile[], forbidden: string[] | null): AuditCheck | null {
131
202
  if (!forbidden || forbidden.length === 0)
132
203
  return null;
133
204
  if (changedFiles.length === 0) {
@@ -161,7 +232,7 @@ export function checkForbiddenScope(changedFiles, forbidden) {
161
232
  * Returns pass when all listed files exist in the task directory.
162
233
  * Returns warn when any listed file is missing.
163
234
  */
164
- export function checkDoneEvidenceMissing(taskDir, doneEvidence) {
235
+ export function checkDoneEvidenceMissing(taskDir: string, doneEvidence: string[] | null): AuditCheck | null {
165
236
  if (!doneEvidence || doneEvidence.length === 0)
166
237
  return null;
167
238
  const missing = [];
@@ -189,7 +260,7 @@ const CODE_EXTENSIONS = new Set([
189
260
  * Returns pass when README.md or CHANGELOG.md (basename, case-insensitive) is also changed.
190
261
  * Returns warn when code changed but neither documentation file was updated.
191
262
  */
192
- export function checkReadmeChangelogSync(changedFiles) {
263
+ export function checkReadmeChangelogSync(changedFiles: ChangedFile[]): AuditCheck | null {
193
264
  const paths = changedFiles.map((f) => f.path);
194
265
  const hasCodeChange = paths.some((p) => {
195
266
  const lower = p.toLowerCase();
@@ -223,14 +294,14 @@ export function checkReadmeChangelogSync(changedFiles) {
223
294
  * Returns pass when package.json parses as JSON and has non-empty name and version strings.
224
295
  * Returns warn otherwise.
225
296
  */
226
- export function checkPackageManifestConsistency(changedFiles, repoPathSafe) {
297
+ export function checkPackageManifestConsistency(changedFiles: ChangedFile[], repoPathSafe: string): AuditCheck | null {
227
298
  const includesPackageJson = changedFiles.some((f) => basename(f.path).toLowerCase() === "package.json");
228
299
  if (!includesPackageJson)
229
300
  return null;
230
301
  try {
231
302
  const pkgPath = join(repoPathSafe, "package.json");
232
303
  const raw = readFileSync(pkgPath, "utf-8");
233
- const parsed = JSON.parse(raw);
304
+ const parsed = JSON.parse(raw) as { name?: unknown; version?: unknown };
234
305
  const hasName = typeof parsed.name === "string" && parsed.name.length > 0;
235
306
  const hasVersion = typeof parsed.version === "string" && parsed.version.length > 0;
236
307
  if (hasName && hasVersion) {
@@ -256,7 +327,7 @@ export function checkPackageManifestConsistency(changedFiles, repoPathSafe) {
256
327
  * Returns pass when no changed file path (or old_path) is sensitive.
257
328
  * Returns fail when any changed file path is flagged by isSensitivePath.
258
329
  */
259
- export function checkSensitivePathAccess(changedFiles) {
330
+ export function checkSensitivePathAccess(changedFiles: ChangedFile[]): AuditCheck | null {
260
331
  if (changedFiles.length === 0)
261
332
  return null;
262
333
  const hits = [];
@@ -287,8 +358,8 @@ const HIGH_RISK_COMMAND_PATTERNS = [
287
358
  /\bRemove-Item\b[\s\S]{0,80}\b-Recurse\b/i,
288
359
  /\brm\s+-rf\b/i,
289
360
  ];
290
- function extractCommands(text) {
291
- const found = [];
361
+ function extractCommands(text: string): ExtractedCommand[] {
362
+ const found: ExtractedCommand[] = [];
292
363
  const runRe = /npm(?:\.cmd)?\s+run\s+([a-zA-Z0-9:_-]+)/gi;
293
364
  let m;
294
365
  while ((m = runRe.exec(text)) !== null) found.push({ type: "npm-run", name: m[1] });
@@ -302,31 +373,34 @@ function extractCommands(text) {
302
373
  while ((m = pythonRe.exec(text)) !== null) found.push({ type: "python", name: normalizeCommandName(m[1]) });
303
374
  return found;
304
375
  }
305
- function normalizeCommandName(value) {
376
+ function normalizeCommandName(value: string): string {
306
377
  return value.replace(/\\/g, "/").replace(/^\.\//, "");
307
378
  }
308
- function commandKey(command) {
379
+ function commandKey(command: ExtractedCommand): string {
309
380
  return command.name;
310
381
  }
311
- function readPackageScripts(repoPath) {
382
+ function readPackageScripts(repoPath: string | null): Record<string, string> {
312
383
  if (!repoPath) return {};
313
384
  const pkgJsonPath = join(repoPath, "package.json");
314
385
  if (!existsSync(pkgJsonPath)) return {};
315
386
  try {
316
387
  guardSensitivePath(pkgJsonPath);
317
- const parsed = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
318
- if (!parsed.scripts || typeof parsed.scripts !== "object" || Array.isArray(parsed.scripts)) return {};
319
- return Object.fromEntries(Object.entries(parsed.scripts).filter(([, value]) => typeof value === "string"));
388
+ const parsed = JSON.parse(readFileSync(pkgJsonPath, "utf-8")) as { scripts?: Record<string, unknown> };
389
+ const scripts = parsed.scripts;
390
+ if (!scripts || typeof scripts !== "object" || Array.isArray(scripts)) return {};
391
+ return Object.fromEntries(
392
+ Object.entries(scripts).filter(([, value]) => typeof value === "string")
393
+ ) as Record<string, string>;
320
394
  }
321
395
  catch {
322
396
  return {};
323
397
  }
324
398
  }
325
- function buildCommandWhitelist(verifyCommands, testCommand, repoPath) {
399
+ function buildCommandWhitelist(verifyCommands: string[], testCommand: string | null, repoPath: string | null): { allowed: Set<string>; transitive: Set<string> } {
326
400
  const scripts = readPackageScripts(repoPath);
327
- const allowed = new Set();
328
- const transitive = new Set();
329
- const queue = [];
401
+ const allowed = new Set<string>();
402
+ const transitive = new Set<string>();
403
+ const queue: Array<{ command: ExtractedCommand; depth: number }> = [];
330
404
  const sources = [...verifyCommands];
331
405
  if (testCommand) sources.push(testCommand);
332
406
  for (const src of sources) {
@@ -336,9 +410,9 @@ function buildCommandWhitelist(verifyCommands, testCommand, repoPath) {
336
410
  }
337
411
  }
338
412
  let inspectedFiles = 0;
339
- const seen = new Set();
413
+ const seen = new Set<string>();
340
414
  while (queue.length > 0) {
341
- const { command, depth } = queue.shift();
415
+ const { command, depth } = queue.shift()!;
342
416
  if (depth > 4) continue;
343
417
  const key = `${command.type}:${command.name}`;
344
418
  if (seen.has(key)) continue;
@@ -365,7 +439,7 @@ function buildCommandWhitelist(verifyCommands, testCommand, repoPath) {
365
439
  }
366
440
  return { allowed, transitive };
367
441
  }
368
- function readLocalScript(repoPath, scriptPath) {
442
+ function readLocalScript(repoPath: string, scriptPath: string): string | null {
369
443
  const resolvedRepo = resolve(repoPath);
370
444
  const resolvedScript = resolve(resolvedRepo, scriptPath);
371
445
  const rel = relative(resolvedRepo, resolvedScript);
@@ -380,17 +454,17 @@ function readLocalScript(repoPath, scriptPath) {
380
454
  return null;
381
455
  }
382
456
  }
383
- function findHighRiskCommandEvidence(text) {
384
- const found = [];
457
+ function findHighRiskCommandEvidence(text: string): string[] {
458
+ const found: string[] = [];
385
459
  for (const pattern of HIGH_RISK_COMMAND_PATTERNS) {
386
460
  const match = text.match(pattern);
387
461
  if (match) found.push(match[0]);
388
462
  }
389
463
  return [...new Set(found)];
390
464
  }
391
- export function checkUnrecordedCommandExecution(testLogContent: string | null, resultMdContent: string | null, verifyCommands: string[], testCommand: string | null, repoPath: string | null = null) {
392
- const hasLog = testLogContent && testLogContent.length > 0;
393
- const hasResult = resultMdContent && resultMdContent.length > 0;
465
+ export function checkUnrecordedCommandExecution(testLogContent: string | null, resultMdContent: string | null, verifyCommands: string[], testCommand: string | null, repoPath: string | null = null): AuditCheck | null {
466
+ const hasLog = !!testLogContent && testLogContent.length > 0;
467
+ const hasResult = !!resultMdContent && resultMdContent.length > 0;
394
468
  if (!hasLog && !hasResult) return null;
395
469
  const combined = `${testLogContent || ""}\n${resultMdContent || ""}`;
396
470
  const highRisk = findHighRiskCommandEvidence(combined);
@@ -398,10 +472,10 @@ export function checkUnrecordedCommandExecution(testLogContent: string | null, r
398
472
  return { name: "unrecorded_command_execution", result: "fail", detail: `High-risk command evidence: ${highRisk.join(", ")}` };
399
473
  }
400
474
  const whitelist = buildCommandWhitelist(verifyCommands, testCommand, repoPath);
401
- const discovered = [];
402
- if (hasLog) discovered.push(...extractCommands(testLogContent));
403
- if (hasResult) discovered.push(...extractCommands(resultMdContent));
404
- const unrecorded = new Set();
475
+ const discovered: ExtractedCommand[] = [];
476
+ if (hasLog && testLogContent) discovered.push(...extractCommands(testLogContent));
477
+ if (hasResult && resultMdContent) discovered.push(...extractCommands(resultMdContent));
478
+ const unrecorded = new Set<string>();
405
479
  for (const cmd of discovered) {
406
480
  if (!whitelist.allowed.has(commandKey(cmd))) unrecorded.add(commandKey(cmd));
407
481
  }
@@ -415,7 +489,7 @@ export function checkUnrecordedCommandExecution(testLogContent: string | null, r
415
489
  detail: transitive.length > 0 ? `All commands are whitelisted; transitive_verified_command: ${transitive.join(", ")}` : "All commands in whitelist.",
416
490
  };
417
491
  }
418
- export function auditTask(taskId) {
492
+ export function auditTask(taskId: string): AuditTaskOutput {
419
493
  const config = getConfig();
420
494
  const tasksDir = getTasksDir(config);
421
495
  const taskDir = join(tasksDir, taskId);
@@ -424,17 +498,17 @@ export function auditTask(taskId) {
424
498
  if (!existsSync(statusFile)) {
425
499
  throw new Error(`Task not found: "${taskId}"`);
426
500
  }
427
- const statusData = JSON.parse(readFileSync(statusFile, "utf-8"));
428
- const checks = [];
429
- const risks = [];
430
- const actions = [];
431
- const possibleFalsePositives = [];
432
- const manualVerificationItems = [];
433
- const addManualVerification = (item) => {
501
+ const statusData = JSON.parse(readFileSync(statusFile, "utf-8")) as TaskStatusData;
502
+ const checks: AuditCheck[] = [];
503
+ const risks: AuditRisk[] = [];
504
+ const actions: string[] = [];
505
+ const possibleFalsePositives: Array<{ check: string; reason: string }> = [];
506
+ const manualVerificationItems: string[] = [];
507
+ const addManualVerification = (item: string) => {
434
508
  if (!manualVerificationItems.includes(item))
435
509
  manualVerificationItems.push(item);
436
510
  };
437
- const addPossibleFalsePositive = (check, reason) => {
511
+ const addPossibleFalsePositive = (check: string, reason: string) => {
438
512
  if (!possibleFalsePositives.some((item) => item.check === check && item.reason === reason)) {
439
513
  possibleFalsePositives.push({ check, reason });
440
514
  }
@@ -478,7 +552,7 @@ export function auditTask(taskId) {
478
552
  }
479
553
  if (existsSync(verifyJsonFile)) {
480
554
  try {
481
- const verify = JSON.parse(readFileSync(verifyJsonFile, "utf-8"));
555
+ const verify = JSON.parse(readFileSync(verifyJsonFile, "utf-8")) as { status?: string };
482
556
  checks.push({
483
557
  name: "verify_status",
484
558
  result: verify.status === "passed" ? "pass" : verify.status === "failed" ? "fail" : "warn",
@@ -504,11 +578,11 @@ export function auditTask(taskId) {
504
578
  : "No new out-of-scope changes recorded.",
505
579
  });
506
580
  // Extract changed_files from change evidence (used by several v0.7.2 checks).
507
- let changedFiles = [];
581
+ let changedFiles: ChangedFile[] = [];
508
582
  const changedFilesFile = join(taskDir, "changed-files.json");
509
583
  if (existsSync(changedFilesFile)) {
510
584
  try {
511
- const changeEvidence = JSON.parse(readFileSync(changedFilesFile, "utf-8"));
585
+ const changeEvidence = JSON.parse(readFileSync(changedFilesFile, "utf-8")) as ChangedFilesEvidence;
512
586
  if (Array.isArray(changeEvidence.changed_files)) {
513
587
  changedFiles = changeEvidence.changed_files;
514
588
  }
@@ -596,11 +670,11 @@ export function auditTask(taskId) {
596
670
  risks.push({ severity: "high", description: "repo_path inconsistent with workspace." });
597
671
  // ── 6. package.json scripts ──
598
672
  const pkgJsonPath = join(repoPathSafe, "package.json");
599
- let pkgScripts = [];
673
+ let pkgScripts: string[] = [];
600
674
  if (existsSync(pkgJsonPath)) {
601
675
  try {
602
676
  guardSensitivePath(pkgJsonPath);
603
- const pkgData = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
677
+ const pkgData = JSON.parse(readFileSync(pkgJsonPath, "utf-8")) as { scripts?: Record<string, unknown> };
604
678
  pkgScripts = Object.keys(pkgData.scripts || {});
605
679
  checks.push({
606
680
  name: "package_json_scripts",
@@ -621,20 +695,35 @@ export function auditTask(taskId) {
621
695
  if (existsSync(readmePath))
622
696
  docsToScan.push(readmePath);
623
697
  const docsDir = join(repoPathSafe, "docs");
698
+ let markdownEnumerationTruncated = false;
624
699
  if (existsSync(docsDir)) {
625
- docsToScan.push(...findMdFiles(docsDir));
700
+ const markdown = findMdFiles(docsDir);
701
+ docsToScan.push(...markdown.files);
702
+ markdownEnumerationTruncated = markdown.truncated;
626
703
  }
627
704
  // Collect all npm run references from all docs
628
- const allNpmRunRefs = new Set();
629
- const allReleaseClaims = [];
705
+ const allNpmRunRefs = new Set<string>();
706
+ const allReleaseClaims: string[] = [];
707
+ let remainingDocBytes = MAX_AUDIT_DOC_TOTAL_BYTES;
708
+ let documentScanTruncated = markdownEnumerationTruncated || docsToScan.length > MAX_AUDIT_DOC_FILES;
630
709
  for (const docPath of docsToScan) {
631
- let content;
710
+ if (remainingDocBytes <= 0) {
711
+ documentScanTruncated = true;
712
+ break;
713
+ }
714
+ let content: string;
632
715
  try {
633
716
  if (docPath !== resultFile) {
634
717
  guardReadPath(docPath, config.workspaceRoot);
635
718
  guardSensitivePath(docPath);
636
719
  }
637
- 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;
638
727
  }
639
728
  catch {
640
729
  continue;
@@ -651,6 +740,14 @@ export function auditTask(taskId) {
651
740
  for (const c of claims)
652
741
  allReleaseClaims.push(`[${relative(repoPathSafe, docPath) || docPath}] ${c}`);
653
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
+ }
654
751
  // Cross-check npm run refs against package.json scripts
655
752
  for (const scriptName of allNpmRunRefs) {
656
753
  if (pkgScripts.length > 0 && !pkgScripts.includes(scriptName)) {
@@ -693,11 +790,13 @@ export function auditTask(taskId) {
693
790
  addManualVerification("Verify remote npm, GitHub Release, and Git tag claims against authoritative remote services.");
694
791
  }
695
792
  // ── 9. test.log Exit code check ──
696
- let testLogContent = null;
793
+ let testLogContent: string | null = null;
697
794
  if (hasTestLog) {
698
- let logContent;
795
+ let logContent: string;
699
796
  try {
700
- 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.");
701
800
  }
702
801
  catch {
703
802
  logContent = "";
@@ -732,10 +831,12 @@ export function auditTask(taskId) {
732
831
  }
733
832
  // ── v0.7.2: New audit checks ──
734
833
  // Read result.md content (guarded) for the unrecorded_command_execution check.
735
- let resultMdContent = null;
834
+ let resultMdContent: string | null = null;
736
835
  if (hasResult) {
737
836
  try {
738
- 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.");
739
840
  }
740
841
  catch {
741
842
  resultMdContent = null;
@@ -803,7 +904,7 @@ export function auditTask(taskId) {
803
904
  "## Recommended Actions",
804
905
  ...actions.map((a) => `- ${a}`),
805
906
  ].join("\n");
806
- writeFileSync(join(taskDir, "independent-review.md"), reviewMd, "utf-8");
907
+ atomicWriteFileSync(join(taskDir, "independent-review.md"), reviewMd);
807
908
  // ── v0.7.2: 集成 acceptanceEngine ──
808
909
  const releaseClaimsUnverified = allReleaseClaims.length > 0;
809
910
  const acceptanceEvidence = {
@@ -818,8 +919,10 @@ export function auditTask(taskId) {
818
919
  if (!existsSync(verifyJsonFile))
819
920
  return null;
820
921
  try {
821
- const v = JSON.parse(readFileSync(verifyJsonFile, "utf-8"));
822
- return v.status === "passed" ? "passed" : v.status === "failed" ? "failed" : "skipped";
922
+ const v = JSON.parse(readFileSync(verifyJsonFile, "utf-8")) as { status?: string };
923
+ if (v.status === "passed") return "passed" as const;
924
+ if (v.status === "failed") return "failed" as const;
925
+ return "skipped" as const;
823
926
  }
824
927
  catch {
825
928
  return null;
@@ -838,16 +941,20 @@ export function auditTask(taskId) {
838
941
  const acceptanceResult = evaluateAcceptance(acceptanceEvidence);
839
942
  // 回写 status.json 的 acceptance_status(仅对 done_by_agent 有意义)
840
943
  if (taskStatus === "done_by_agent") {
841
- const updatedStatus = {
842
- ...statusData,
944
+ const statusPatch = {
843
945
  acceptance_status: acceptanceResult.acceptance_status,
844
- updated_at: new Date().toISOString(),
845
946
  };
846
- 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
+ });
847
954
  }
848
955
  // 导出 ACCEPTANCE.md
849
956
  const acceptanceMd = renderAcceptanceMarkdown(taskId, acceptanceResult, acceptanceEvidence);
850
- writeFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd, "utf-8");
957
+ atomicWriteFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd);
851
958
  return {
852
959
  task_id: taskId,
853
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
 
@@ -195,14 +195,14 @@ function directoryStatus(path: string, allowCreatable: boolean, createRoot?: str
195
195
  try {
196
196
  accessSync(parent, constants.R_OK | constants.W_OK);
197
197
  return { available: true, path, readable: false, writable: true, reason: "Directory will be created on first use." };
198
- } catch {}
198
+ } catch {} // probe failure handled by return value
199
199
  }
200
200
  return { available: false, path, readable: false, writable: false, reason: "Directory does not exist." };
201
201
  }
202
202
  let readable = false;
203
203
  let writable = false;
204
- try { accessSync(path, constants.R_OK); readable = true; } catch {}
205
- try { accessSync(path, constants.W_OK); writable = true; } catch {}
204
+ try { accessSync(path, constants.R_OK); readable = true; } catch {} // probe failure handled by return value
205
+ try { accessSync(path, constants.W_OK); writable = true; } catch {} // probe failure handled by return value
206
206
  return {
207
207
  available: readable && writable,
208
208
  path,
@@ -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;