patchwarden 1.5.1 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (573) hide show
  1. package/PatchWarden.cmd +32 -2
  2. package/README.en.md +152 -25
  3. package/README.md +120 -23
  4. package/dist/assessments/agentAssessor.js +21 -12
  5. package/dist/assessments/assessmentStore.js +42 -34
  6. package/dist/config.d.ts +15 -0
  7. package/dist/config.js +66 -13
  8. package/dist/control/fileManager.d.ts +2 -0
  9. package/dist/control/fileManager.js +39 -0
  10. package/dist/control/middleware/auth.d.ts +6 -0
  11. package/dist/control/middleware/auth.js +14 -5
  12. package/dist/control/middleware/static.js +16 -3
  13. package/dist/control/routeTable.d.ts +24 -0
  14. package/dist/control/routeTable.js +263 -0
  15. package/dist/control/routes/audit.js +17 -7
  16. package/dist/control/routes/evidence.js +1 -1
  17. package/dist/control/routes/lineage.js +1 -1
  18. package/dist/control/routes/process.d.ts +7 -0
  19. package/dist/control/routes/process.js +329 -42
  20. package/dist/control/routes/sessions.d.ts +9 -1
  21. package/dist/control/routes/sessions.js +84 -21
  22. package/dist/control/routes/status.d.ts +46 -1
  23. package/dist/control/routes/status.js +72 -15
  24. package/dist/control/routes/taskActions.js +24 -60
  25. package/dist/control/routes/tasks.d.ts +4 -0
  26. package/dist/control/routes/tasks.js +61 -62
  27. package/dist/control/routes/workspace.js +50 -23
  28. package/dist/control/runtime.d.ts +3 -2
  29. package/dist/control/runtime.js +63 -30
  30. package/dist/control/server.js +36 -365
  31. package/dist/control/shared.d.ts +25 -1
  32. package/dist/control/shared.js +64 -11
  33. package/dist/direct/directAudit.js +234 -225
  34. package/dist/direct/directGuards.d.ts +2 -1
  35. package/dist/direct/directGuards.js +42 -29
  36. package/dist/direct/directPatch.d.ts +6 -1
  37. package/dist/direct/directPatch.js +55 -8
  38. package/dist/direct/directSessionStore.d.ts +16 -6
  39. package/dist/direct/directSessionStore.js +127 -35
  40. package/dist/direct/directVerification.js +8 -16
  41. package/dist/doctor.js +62 -52
  42. package/dist/goal/acceptanceEngine.d.ts +1 -1
  43. package/dist/goal/goalProgress.js +75 -69
  44. package/dist/goal/goalReport.js +5 -12
  45. package/dist/goal/goalStatus.d.ts +2 -0
  46. package/dist/goal/goalStatus.js +10 -3
  47. package/dist/goal/goalStore.d.ts +9 -2
  48. package/dist/goal/goalStore.js +152 -45
  49. package/dist/goal/handoffExport.js +6 -6
  50. package/dist/goal/specKitImport.js +97 -96
  51. package/dist/goal/subgoalSync.js +11 -9
  52. package/dist/goal/worktreeManager.d.ts +2 -0
  53. package/dist/goal/worktreeManager.js +209 -136
  54. package/dist/httpServer.js +111 -32
  55. package/dist/logging.js +5 -3
  56. package/dist/policy/projectPolicy.js +5 -2
  57. package/dist/release/releaseGate.d.ts +1 -1
  58. package/dist/release/releaseGate.js +78 -25
  59. package/dist/runner/agentInvocation.d.ts +14 -0
  60. package/dist/runner/agentInvocation.js +96 -4
  61. package/dist/runner/changeCapture.d.ts +13 -5
  62. package/dist/runner/changeCapture.js +243 -61
  63. package/dist/runner/postTaskCleanup.js +48 -19
  64. package/dist/runner/processSecurity.d.ts +56 -0
  65. package/dist/runner/processSecurity.js +373 -0
  66. package/dist/runner/runTask.d.ts +1 -1
  67. package/dist/runner/runTask.js +115 -87
  68. package/dist/runner/simpleProcess.d.ts +3 -0
  69. package/dist/runner/simpleProcess.js +50 -36
  70. package/dist/{taskProgress.d.ts → runner/taskProgress.d.ts} +1 -1
  71. package/dist/{taskProgress.js → runner/taskProgress.js} +2 -2
  72. package/dist/{taskRuntime.d.ts → runner/taskRuntime.d.ts} +1 -1
  73. package/dist/{taskRuntime.js → runner/taskRuntime.js} +3 -2
  74. package/dist/runner/taskStatusStore.d.ts +11 -0
  75. package/dist/runner/taskStatusStore.js +24 -0
  76. package/dist/runner/watch.d.ts +14 -1
  77. package/dist/runner/watch.js +256 -48
  78. package/dist/security/contentRedaction.js +2 -2
  79. package/dist/security/discoveryTokenStore.d.ts +3 -2
  80. package/dist/security/discoveryTokenStore.js +17 -2
  81. package/dist/security/loopbackHost.d.ts +2 -0
  82. package/dist/security/loopbackHost.js +16 -0
  83. package/dist/security/pathGuard.js +32 -17
  84. package/dist/security/planGuard.js +2 -1
  85. package/dist/security/runtimeGuard.js +9 -6
  86. package/dist/security/secretComparison.d.ts +3 -0
  87. package/dist/security/secretComparison.js +11 -0
  88. package/dist/security/sensitiveGuard.d.ts +5 -0
  89. package/dist/security/sensitiveGuard.js +27 -8
  90. package/dist/security/toolInvocationGuard.d.ts +2 -2
  91. package/dist/security/toolInvocationGuard.js +1 -1
  92. package/dist/security/workspaceRootGuard.d.ts +8 -0
  93. package/dist/security/workspaceRootGuard.js +47 -0
  94. package/dist/smoke-test.js +24 -23
  95. package/dist/tools/catalog/index.d.ts +4 -0
  96. package/dist/tools/catalog/index.js +4 -0
  97. package/dist/tools/{toolCatalog.js → catalog/toolCatalog.js} +3 -12
  98. package/dist/tools/{toolRegistry.d.ts → catalog/toolRegistry.d.ts} +3 -3
  99. package/dist/tools/{toolRegistry.js → catalog/toolRegistry.js} +6 -15
  100. package/dist/tools/definitions/toolDefs.d.ts +18 -0
  101. package/dist/tools/definitions/toolDefs.js +1177 -0
  102. package/dist/tools/{auditSession.d.ts → diagnostics/auditSession.d.ts} +1 -1
  103. package/dist/tools/{auditSession.js → diagnostics/auditSession.js} +2 -2
  104. package/dist/tools/{auditTask.d.ts → diagnostics/auditTask.d.ts} +1 -1
  105. package/dist/tools/{auditTask.js → diagnostics/auditTask.js} +99 -29
  106. package/dist/tools/{healthCheck.d.ts → diagnostics/healthCheck.d.ts} +6 -6
  107. package/dist/tools/{healthCheck.js → diagnostics/healthCheck.js} +7 -7
  108. package/dist/tools/diagnostics/index.d.ts +6 -0
  109. package/dist/tools/diagnostics/index.js +6 -0
  110. package/dist/tools/{safeStatus.d.ts → diagnostics/safeStatus.d.ts} +3 -3
  111. package/dist/tools/{safeStatus.js → diagnostics/safeStatus.js} +6 -6
  112. package/dist/tools/{safeViews.d.ts → diagnostics/safeViews.d.ts} +12 -8
  113. package/dist/tools/{safeViews.js → diagnostics/safeViews.js} +23 -13
  114. package/dist/tools/{schemaDriftCheck.d.ts → diagnostics/schemaDriftCheck.d.ts} +1 -1
  115. package/dist/tools/{schemaDriftCheck.js → diagnostics/schemaDriftCheck.js} +2 -2
  116. package/dist/tools/{createDirectSession.js → direct/createDirectSession.js} +6 -6
  117. package/dist/tools/{finalizeDirectSession.d.ts → direct/finalizeDirectSession.d.ts} +1 -1
  118. package/dist/tools/direct/finalizeDirectSession.js +86 -0
  119. package/dist/tools/direct/index.d.ts +3 -0
  120. package/dist/tools/direct/index.js +3 -0
  121. package/dist/tools/{runDirectVerificationBundle.js → direct/runDirectVerificationBundle.js} +2 -2
  122. package/dist/tools/{discoverTools.d.ts → discovery/discoverTools.d.ts} +2 -2
  123. package/dist/tools/{discoverTools.js → discovery/discoverTools.js} +5 -5
  124. package/dist/tools/{explainTool.d.ts → discovery/explainTool.d.ts} +2 -2
  125. package/dist/tools/{explainTool.js → discovery/explainTool.js} +2 -2
  126. package/dist/tools/discovery/index.d.ts +3 -0
  127. package/dist/tools/discovery/index.js +3 -0
  128. package/dist/tools/{invokeDiscoveredTool.d.ts → discovery/invokeDiscoveredTool.d.ts} +2 -2
  129. package/dist/tools/{invokeDiscoveredTool.js → discovery/invokeDiscoveredTool.js} +5 -5
  130. package/dist/tools/dispatch/coreDispatch.js +32 -31
  131. package/dist/tools/dispatch/diagnosticDispatch.d.ts +3 -5
  132. package/dist/tools/dispatch/diagnosticDispatch.js +70 -68
  133. package/dist/tools/dispatch/directDispatch.js +11 -10
  134. package/dist/tools/dispatch/goalDispatch.js +5 -4
  135. package/dist/tools/dispatch/releaseDispatch.js +3 -2
  136. package/dist/tools/dispatch/validation.d.ts +7 -0
  137. package/dist/tools/dispatch/validation.js +71 -0
  138. package/dist/tools/{getPlan.js → goals/getPlan.js} +4 -4
  139. package/dist/tools/{goalSubgoalTask.d.ts → goals/goalSubgoalTask.d.ts} +1 -1
  140. package/dist/tools/goals/goalSubgoalTask.js +118 -0
  141. package/dist/tools/goals/index.d.ts +3 -0
  142. package/dist/tools/goals/index.js +3 -0
  143. package/dist/tools/{savePlan.js → goals/savePlan.js} +28 -8
  144. package/dist/tools/registry.d.ts +7 -11
  145. package/dist/tools/registry.js +17 -1178
  146. package/dist/tools/{checkReleaseGate.d.ts → release/checkReleaseGate.d.ts} +1 -1
  147. package/dist/tools/{checkReleaseGate.js → release/checkReleaseGate.js} +3 -3
  148. package/dist/tools/release/index.d.ts +2 -0
  149. package/dist/tools/release/index.js +2 -0
  150. package/dist/tools/{releaseMode.d.ts → release/releaseMode.d.ts} +2 -2
  151. package/dist/tools/{releaseMode.js → release/releaseMode.js} +46 -26
  152. package/dist/tools/tasks/cancelTask.d.ts +11 -0
  153. package/dist/tools/tasks/cancelTask.js +85 -0
  154. package/dist/tools/{createTask.d.ts → tasks/createTask.d.ts} +10 -2
  155. package/dist/tools/{createTask.js → tasks/createTask.js} +42 -27
  156. package/dist/tools/{diagnoseTask.d.ts → tasks/diagnoseTask.d.ts} +1 -1
  157. package/dist/tools/{diagnoseTask.js → tasks/diagnoseTask.js} +8 -8
  158. package/dist/tools/{evidencePack.js → tasks/evidencePack.js} +34 -22
  159. package/dist/tools/{getTaskFile.js → tasks/getTaskFile.js} +4 -4
  160. package/dist/tools/{getTaskStatus.d.ts → tasks/getTaskStatus.d.ts} +6 -1
  161. package/dist/tools/{getTaskStatus.js → tasks/getTaskStatus.js} +5 -5
  162. package/dist/tools/{getTaskStdoutTail.js → tasks/getTaskStdoutTail.js} +13 -11
  163. package/dist/tools/{getTaskSummary.js → tasks/getTaskSummary.js} +33 -26
  164. package/dist/tools/tasks/index.d.ts +18 -0
  165. package/dist/tools/tasks/index.js +18 -0
  166. package/dist/tools/tasks/killTask.d.ts +1 -0
  167. package/dist/tools/{listTasks.d.ts → tasks/listTasks.d.ts} +1 -1
  168. package/dist/tools/{listTasks.js → tasks/listTasks.js} +3 -3
  169. package/dist/tools/{reconcileTasks.d.ts → tasks/reconcileTasks.d.ts} +1 -1
  170. package/dist/tools/{reconcileTasks.js → tasks/reconcileTasks.js} +64 -66
  171. package/dist/tools/tasks/retryTask.js +60 -0
  172. package/dist/tools/{runTaskLoop.d.ts → tasks/runTaskLoop.d.ts} +6 -6
  173. package/dist/tools/{runTaskLoop.js → tasks/runTaskLoop.js} +58 -30
  174. package/dist/tools/tasks/runVerification.js +38 -0
  175. package/dist/tools/{taskLineage.js → tasks/taskLineage.js} +8 -7
  176. package/dist/tools/{taskOutputs.js → tasks/taskOutputs.js} +17 -16
  177. package/dist/tools/{androidDoctor.js → workspace/androidDoctor.js} +16 -10
  178. package/dist/tools/{applyPatch.d.ts → workspace/applyPatch.d.ts} +1 -1
  179. package/dist/tools/workspace/applyPatch.js +53 -0
  180. package/dist/tools/{discardWorktree.js → workspace/discardWorktree.js} +3 -3
  181. package/dist/tools/workspace/index.d.ts +10 -0
  182. package/dist/tools/workspace/index.js +10 -0
  183. package/dist/tools/{listAgents.d.ts → workspace/listAgents.d.ts} +5 -0
  184. package/dist/tools/{listAgents.js → workspace/listAgents.js} +8 -4
  185. package/dist/tools/{listWorkspace.js → workspace/listWorkspace.js} +3 -3
  186. package/dist/tools/{mergeWorktree.js → workspace/mergeWorktree.js} +3 -3
  187. package/dist/tools/{readWorkspaceFile.js → workspace/readWorkspaceFile.js} +8 -8
  188. package/dist/tools/{recommendAgentForTask.js → workspace/recommendAgentForTask.js} +3 -3
  189. package/dist/tools/{searchWorkspace.js → workspace/searchWorkspace.js} +5 -5
  190. package/dist/tools/{syncFile.d.ts → workspace/syncFile.d.ts} +1 -1
  191. package/dist/tools/workspace/syncFile.js +134 -0
  192. package/dist/utils/atomicFile.d.ts +7 -0
  193. package/dist/utils/atomicFile.js +48 -0
  194. package/dist/utils/boundedFile.d.ts +8 -0
  195. package/dist/utils/boundedFile.js +93 -0
  196. package/dist/utils/lockedJsonFile.d.ts +15 -0
  197. package/dist/utils/lockedJsonFile.js +224 -0
  198. package/dist/utils/platform.d.ts +11 -0
  199. package/dist/utils/platform.js +26 -0
  200. package/dist/utils/stableJson.d.ts +2 -0
  201. package/dist/utils/stableJson.js +12 -0
  202. package/dist/version.d.ts +3 -2
  203. package/dist/version.js +3 -2
  204. package/dist/watcherStatus.d.ts +2 -2
  205. package/dist/watcherStatus.js +18 -0
  206. package/docs/CODE_WIKI.md +808 -143
  207. package/docs/architecture.md +15 -55
  208. package/docs/assets/patchwarden-desktop-onboarding.png +0 -0
  209. package/docs/control-center/README.md +4 -4
  210. package/docs/dashboard-overview.md +4 -4
  211. package/docs/desktop-app.md +175 -0
  212. package/docs/evidence-pack-schema.md +3 -3
  213. package/docs/open-source-application.md +17 -11
  214. package/docs/release-checklist.md +1 -1
  215. package/docs/release-evidence.md +39 -29
  216. package/docs/task-safe-review-workflow.md +5 -5
  217. package/docs/threat-model.md +19 -1
  218. package/examples/config.example.json +4 -2
  219. package/package.json +27 -10
  220. package/scripts/README.md +15 -6
  221. package/scripts/build.js +11 -0
  222. package/scripts/checks/brand-check.js +3 -0
  223. package/scripts/checks/build-output-check.js +37 -0
  224. package/scripts/checks/control-center-smoke.js +91 -6
  225. package/scripts/checks/control-smoke.js +19 -8
  226. package/scripts/checks/http-mcp-smoke.js +82 -4
  227. package/scripts/checks/lifecycle-smoke.js +10 -10
  228. package/scripts/checks/mcp-manifest-check.js +1 -1
  229. package/scripts/checks/mcp-smoke.js +27 -3
  230. package/scripts/checks/package-manifest-check.js +20 -7
  231. package/scripts/checks/unit-tests.js +3 -5
  232. package/scripts/checks/watcher-supervisor-smoke.js +9 -0
  233. package/scripts/control/get-patchwarden-health.ps1 +1 -1
  234. package/scripts/control/manage-patchwarden.ps1 +69 -4
  235. package/scripts/control/provision-patchwarden-tunnel.ps1 +127 -0
  236. package/scripts/control/run-background-supervisor.ps1 +41 -0
  237. package/scripts/control/start-patchwarden-tunnel.ps1 +126 -32
  238. package/{PatchWarden-Control-Tray.cmd → scripts/launchers/PatchWarden-Control-Tray.cmd} +3 -3
  239. package/scripts/launchers/PatchWarden-Control.cmd +6 -0
  240. package/{PatchWarden-Desktop.cmd → scripts/launchers/PatchWarden-Desktop.cmd} +2 -2
  241. package/scripts/launchers/Restart-PatchWarden-Control.cmd +6 -0
  242. package/{Stop-PatchWarden.cmd → scripts/launchers/Stop-PatchWarden.cmd} +2 -2
  243. package/scripts/lib/clean-generated-output.js +11 -0
  244. package/scripts/lib/file-discovery.js +12 -0
  245. package/scripts/release/desktop-preflight.js +211 -0
  246. package/scripts/release/pack-clean.js +59 -14
  247. package/src/assessments/agentAssessor.ts +26 -12
  248. package/src/assessments/assessmentStore.ts +52 -40
  249. package/src/config.ts +70 -13
  250. package/src/control/fileManager.ts +40 -0
  251. package/src/control/middleware/auth.ts +22 -4
  252. package/src/control/middleware/static.ts +16 -3
  253. package/src/control/routeTable.ts +301 -0
  254. package/src/control/routes/audit.ts +14 -6
  255. package/src/control/routes/evidence.ts +1 -1
  256. package/src/control/routes/lineage.ts +1 -1
  257. package/src/control/routes/process.ts +341 -40
  258. package/src/control/routes/sessions.ts +88 -25
  259. package/src/control/routes/status.ts +97 -17
  260. package/src/control/routes/taskActions.ts +24 -58
  261. package/src/control/routes/tasks.ts +66 -58
  262. package/src/control/routes/workspace.ts +56 -25
  263. package/src/control/runtime.ts +69 -33
  264. package/src/control/server.ts +36 -342
  265. package/src/control/shared.ts +77 -11
  266. package/src/direct/directAudit.ts +17 -9
  267. package/src/direct/directGuards.ts +72 -44
  268. package/src/direct/directPatch.ts +95 -8
  269. package/src/direct/directSessionStore.ts +211 -55
  270. package/src/direct/directVerification.ts +9 -23
  271. package/src/doctor.ts +73 -59
  272. package/src/goal/acceptanceEngine.ts +1 -1
  273. package/src/goal/goalProgress.ts +17 -13
  274. package/src/goal/goalReport.ts +5 -13
  275. package/src/goal/goalStatus.ts +19 -3
  276. package/src/goal/goalStore.ts +241 -54
  277. package/src/goal/handoffExport.ts +6 -6
  278. package/src/goal/specKitImport.ts +12 -12
  279. package/src/goal/subgoalSync.ts +11 -8
  280. package/src/goal/worktreeManager.ts +139 -22
  281. package/src/httpServer.ts +113 -30
  282. package/src/logging.ts +10 -3
  283. package/src/policy/projectPolicy.ts +5 -2
  284. package/src/release/releaseGate.ts +74 -27
  285. package/src/runner/agentInvocation.ts +126 -4
  286. package/src/runner/changeCapture.ts +291 -57
  287. package/src/runner/postTaskCleanup.ts +41 -17
  288. package/src/runner/processSecurity.ts +433 -0
  289. package/src/runner/runTask.ts +138 -91
  290. package/src/runner/simpleProcess.ts +66 -31
  291. package/src/{taskProgress.ts → runner/taskProgress.ts} +3 -3
  292. package/src/{taskRuntime.ts → runner/taskRuntime.ts} +4 -3
  293. package/src/runner/taskStatusStore.ts +54 -0
  294. package/src/runner/watch.ts +281 -51
  295. package/src/security/contentRedaction.ts +2 -2
  296. package/src/security/discoveryTokenStore.ts +18 -4
  297. package/src/security/loopbackHost.ts +19 -0
  298. package/src/security/pathGuard.ts +35 -16
  299. package/src/security/planGuard.ts +2 -1
  300. package/src/security/runtimeGuard.ts +9 -6
  301. package/src/security/secretComparison.ts +13 -0
  302. package/src/security/sensitiveGuard.ts +27 -8
  303. package/src/security/toolInvocationGuard.ts +2 -2
  304. package/src/security/workspaceRootGuard.ts +53 -0
  305. package/src/smoke-test.ts +25 -24
  306. package/src/tools/catalog/index.ts +4 -0
  307. package/src/tools/{toolCatalog.ts → catalog/toolCatalog.ts} +3 -12
  308. package/src/tools/{toolRegistry.ts → catalog/toolRegistry.ts} +7 -16
  309. package/src/tools/definitions/toolDefs.ts +1264 -0
  310. package/src/tools/{auditSession.ts → diagnostics/auditSession.ts} +2 -2
  311. package/src/tools/{auditTask.ts → diagnostics/auditTask.ts} +99 -32
  312. package/src/tools/{healthCheck.ts → diagnostics/healthCheck.ts} +8 -8
  313. package/src/tools/diagnostics/index.ts +6 -0
  314. package/src/tools/{safeStatus.ts → diagnostics/safeStatus.ts} +7 -7
  315. package/src/tools/{safeViews.ts → diagnostics/safeViews.ts} +27 -17
  316. package/src/tools/{schemaDriftCheck.ts → diagnostics/schemaDriftCheck.ts} +3 -3
  317. package/src/tools/{createDirectSession.ts → direct/createDirectSession.ts} +6 -6
  318. package/src/tools/{finalizeDirectSession.ts → direct/finalizeDirectSession.ts} +7 -5
  319. package/src/tools/direct/index.ts +3 -0
  320. package/src/tools/{runDirectVerificationBundle.ts → direct/runDirectVerificationBundle.ts} +2 -2
  321. package/src/tools/{discoverTools.ts → discovery/discoverTools.ts} +6 -6
  322. package/src/tools/{explainTool.ts → discovery/explainTool.ts} +3 -3
  323. package/src/tools/discovery/index.ts +3 -0
  324. package/src/tools/{invokeDiscoveredTool.ts → discovery/invokeDiscoveredTool.ts} +7 -7
  325. package/src/tools/dispatch/coreDispatch.ts +36 -31
  326. package/src/tools/dispatch/diagnosticDispatch.ts +26 -21
  327. package/src/tools/dispatch/directDispatch.ts +11 -10
  328. package/src/tools/dispatch/goalDispatch.ts +5 -4
  329. package/src/tools/dispatch/releaseDispatch.ts +3 -2
  330. package/src/tools/dispatch/validation.ts +78 -0
  331. package/src/tools/{getPlan.ts → goals/getPlan.ts} +4 -4
  332. package/src/tools/{goalSubgoalTask.ts → goals/goalSubgoalTask.ts} +41 -26
  333. package/src/tools/goals/index.ts +3 -0
  334. package/src/tools/{savePlan.ts → goals/savePlan.ts} +38 -8
  335. package/src/tools/registry.ts +17 -1261
  336. package/src/tools/{checkReleaseGate.ts → release/checkReleaseGate.ts} +3 -3
  337. package/src/tools/release/index.ts +2 -0
  338. package/src/tools/{releaseMode.ts → release/releaseMode.ts} +42 -24
  339. package/src/tools/tasks/cancelTask.ts +109 -0
  340. package/src/tools/{createTask.ts → tasks/createTask.ts} +49 -26
  341. package/src/tools/{diagnoseTask.ts → tasks/diagnoseTask.ts} +8 -8
  342. package/src/tools/{evidencePack.ts → tasks/evidencePack.ts} +36 -22
  343. package/src/tools/{getTaskFile.ts → tasks/getTaskFile.ts} +4 -4
  344. package/src/tools/{getTaskStatus.ts → tasks/getTaskStatus.ts} +7 -5
  345. package/src/tools/{getTaskStdoutTail.ts → tasks/getTaskStdoutTail.ts} +13 -11
  346. package/src/tools/{getTaskSummary.ts → tasks/getTaskSummary.ts} +44 -33
  347. package/src/tools/tasks/index.ts +18 -0
  348. package/src/tools/{listTasks.ts → tasks/listTasks.ts} +4 -4
  349. package/src/tools/{reconcileTasks.ts → tasks/reconcileTasks.ts} +68 -66
  350. package/src/tools/tasks/retryTask.ts +69 -0
  351. package/src/tools/{runTaskLoop.ts → tasks/runTaskLoop.ts} +69 -34
  352. package/src/tools/{runVerification.ts → tasks/runVerification.ts} +6 -3
  353. package/src/tools/{taskLineage.ts → tasks/taskLineage.ts} +8 -7
  354. package/src/tools/{taskOutputs.ts → tasks/taskOutputs.ts} +27 -20
  355. package/src/tools/{androidDoctor.ts → workspace/androidDoctor.ts} +15 -10
  356. package/src/tools/{applyPatch.ts → workspace/applyPatch.ts} +38 -16
  357. package/src/tools/{discardWorktree.ts → workspace/discardWorktree.ts} +3 -3
  358. package/src/tools/workspace/index.ts +10 -0
  359. package/src/tools/{listAgents.ts → workspace/listAgents.ts} +11 -4
  360. package/src/tools/{listWorkspace.ts → workspace/listWorkspace.ts} +3 -3
  361. package/src/tools/{mergeWorktree.ts → workspace/mergeWorktree.ts} +3 -3
  362. package/src/tools/{readWorkspaceFile.ts → workspace/readWorkspaceFile.ts} +8 -8
  363. package/src/tools/{recommendAgentForTask.ts → workspace/recommendAgentForTask.ts} +3 -3
  364. package/src/tools/{searchWorkspace.ts → workspace/searchWorkspace.ts} +5 -5
  365. package/src/tools/workspace/syncFile.ts +292 -0
  366. package/src/utils/atomicFile.ts +58 -0
  367. package/src/utils/boundedFile.ts +116 -0
  368. package/src/utils/lockedJsonFile.ts +251 -0
  369. package/src/utils/platform.ts +31 -0
  370. package/src/utils/stableJson.ts +12 -0
  371. package/src/version.ts +3 -2
  372. package/src/watcherStatus.ts +19 -1
  373. package/ui/desktop-bootstrap.js +11 -0
  374. package/ui/desktop-bridge.js +36 -0
  375. package/ui/desktop.css +160 -0
  376. package/ui/getting-started.js +93 -0
  377. package/ui/i18n.js +484 -0
  378. package/ui/log-parser.js +30 -0
  379. package/ui/pages/audit.html +12 -0
  380. package/ui/pages/dashboard.html +90 -147
  381. package/ui/pages/direct-sessions.html +123 -26
  382. package/ui/pages/getting-started.html +43 -0
  383. package/ui/pages/logs.html +105 -22
  384. package/ui/pages/settings.html +101 -0
  385. package/ui/pages/task-detail.html +12 -0
  386. package/ui/pages/tasks.html +54 -8
  387. package/ui/pages/workspace.html +38 -1
  388. package/ui/settings.js +245 -0
  389. package/PatchWarden-Control.cmd +0 -6
  390. package/Restart-PatchWarden-Control.cmd +0 -6
  391. package/dist/test/unit/acceptance-engine.test.d.ts +0 -1
  392. package/dist/test/unit/acceptance-engine.test.js +0 -228
  393. package/dist/test/unit/agent-router.test.d.ts +0 -1
  394. package/dist/test/unit/agent-router.test.js +0 -287
  395. package/dist/test/unit/android-doctor.test.d.ts +0 -1
  396. package/dist/test/unit/android-doctor.test.js +0 -118
  397. package/dist/test/unit/apply-patch.test.d.ts +0 -1
  398. package/dist/test/unit/apply-patch.test.js +0 -225
  399. package/dist/test/unit/audit-checks.test.d.ts +0 -1
  400. package/dist/test/unit/audit-checks.test.js +0 -350
  401. package/dist/test/unit/chinese-path.test.d.ts +0 -1
  402. package/dist/test/unit/chinese-path.test.js +0 -91
  403. package/dist/test/unit/command-guard.test.d.ts +0 -1
  404. package/dist/test/unit/command-guard.test.js +0 -160
  405. package/dist/test/unit/create-task.test.d.ts +0 -1
  406. package/dist/test/unit/create-task.test.js +0 -197
  407. package/dist/test/unit/diagnose-task.test.d.ts +0 -1
  408. package/dist/test/unit/diagnose-task.test.js +0 -457
  409. package/dist/test/unit/direct-guards.test.d.ts +0 -1
  410. package/dist/test/unit/direct-guards.test.js +0 -328
  411. package/dist/test/unit/discovery-token-store.test.d.ts +0 -1
  412. package/dist/test/unit/discovery-token-store.test.js +0 -139
  413. package/dist/test/unit/evidence-pack.test.d.ts +0 -1
  414. package/dist/test/unit/evidence-pack.test.js +0 -224
  415. package/dist/test/unit/get-task-status.test.d.ts +0 -1
  416. package/dist/test/unit/get-task-status.test.js +0 -174
  417. package/dist/test/unit/get-task-summary.test.d.ts +0 -1
  418. package/dist/test/unit/get-task-summary.test.js +0 -146
  419. package/dist/test/unit/goal-graph.test.d.ts +0 -1
  420. package/dist/test/unit/goal-graph.test.js +0 -298
  421. package/dist/test/unit/goal-progress.test.d.ts +0 -1
  422. package/dist/test/unit/goal-progress.test.js +0 -381
  423. package/dist/test/unit/goal-report.test.d.ts +0 -1
  424. package/dist/test/unit/goal-report.test.js +0 -159
  425. package/dist/test/unit/goal-status.test.d.ts +0 -1
  426. package/dist/test/unit/goal-status.test.js +0 -215
  427. package/dist/test/unit/goal-store.test.d.ts +0 -1
  428. package/dist/test/unit/goal-store.test.js +0 -253
  429. package/dist/test/unit/goal-subgoal-task.test.d.ts +0 -1
  430. package/dist/test/unit/goal-subgoal-task.test.js +0 -55
  431. package/dist/test/unit/goal-tools-registry.test.d.ts +0 -1
  432. package/dist/test/unit/goal-tools-registry.test.js +0 -192
  433. package/dist/test/unit/handoff-export.test.d.ts +0 -1
  434. package/dist/test/unit/handoff-export.test.js +0 -263
  435. package/dist/test/unit/invoke-discovered-tool.test.d.ts +0 -1
  436. package/dist/test/unit/invoke-discovered-tool.test.js +0 -167
  437. package/dist/test/unit/logging.test.d.ts +0 -1
  438. package/dist/test/unit/logging.test.js +0 -397
  439. package/dist/test/unit/path-guard.test.d.ts +0 -1
  440. package/dist/test/unit/path-guard.test.js +0 -133
  441. package/dist/test/unit/post-task-cleanup.test.d.ts +0 -1
  442. package/dist/test/unit/post-task-cleanup.test.js +0 -48
  443. package/dist/test/unit/project-policy-release-mode.test.d.ts +0 -1
  444. package/dist/test/unit/project-policy-release-mode.test.js +0 -125
  445. package/dist/test/unit/reconcile-tasks.test.d.ts +0 -1
  446. package/dist/test/unit/reconcile-tasks.test.js +0 -456
  447. package/dist/test/unit/release-gate.test.d.ts +0 -1
  448. package/dist/test/unit/release-gate.test.js +0 -242
  449. package/dist/test/unit/run-task-loop.test.d.ts +0 -1
  450. package/dist/test/unit/run-task-loop.test.js +0 -380
  451. package/dist/test/unit/safe-status.test.d.ts +0 -1
  452. package/dist/test/unit/safe-status.test.js +0 -165
  453. package/dist/test/unit/safe-views.test.d.ts +0 -1
  454. package/dist/test/unit/safe-views.test.js +0 -171
  455. package/dist/test/unit/schema-drift-check.test.d.ts +0 -1
  456. package/dist/test/unit/schema-drift-check.test.js +0 -176
  457. package/dist/test/unit/sensitive-guard.test.d.ts +0 -1
  458. package/dist/test/unit/sensitive-guard.test.js +0 -104
  459. package/dist/test/unit/spec-kit-import.test.d.ts +0 -1
  460. package/dist/test/unit/spec-kit-import.test.js +0 -341
  461. package/dist/test/unit/subgoal-sync.test.d.ts +0 -1
  462. package/dist/test/unit/subgoal-sync.test.js +0 -183
  463. package/dist/test/unit/sync-file.test.d.ts +0 -1
  464. package/dist/test/unit/sync-file.test.js +0 -154
  465. package/dist/test/unit/tool-invocation-guard.test.d.ts +0 -1
  466. package/dist/test/unit/tool-invocation-guard.test.js +0 -432
  467. package/dist/test/unit/tool-usage-stats.test.d.ts +0 -1
  468. package/dist/test/unit/tool-usage-stats.test.js +0 -300
  469. package/dist/test/unit/toolSearch.test.d.ts +0 -1
  470. package/dist/test/unit/toolSearch.test.js +0 -571
  471. package/dist/test/unit/wait-for-task.test.d.ts +0 -1
  472. package/dist/test/unit/wait-for-task.test.js +0 -144
  473. package/dist/test/unit/watcher-status.test.d.ts +0 -1
  474. package/dist/test/unit/watcher-status.test.js +0 -169
  475. package/dist/test/unit/worktree-manager.test.d.ts +0 -1
  476. package/dist/test/unit/worktree-manager.test.js +0 -176
  477. package/dist/tools/applyPatch.js +0 -41
  478. package/dist/tools/cancelTask.d.ts +0 -30
  479. package/dist/tools/cancelTask.js +0 -64
  480. package/dist/tools/finalizeDirectSession.js +0 -84
  481. package/dist/tools/goalSubgoalTask.js +0 -110
  482. package/dist/tools/killTask.d.ts +0 -15
  483. package/dist/tools/retryTask.js +0 -45
  484. package/dist/tools/runVerification.js +0 -36
  485. package/dist/tools/syncFile.js +0 -65
  486. package/docs/control-center/control-center-daily-driver.md +0 -211
  487. package/docs/control-center/control-center-mvp.md +0 -205
  488. package/docs/control-center/control-center-phase2.md +0 -159
  489. package/docs/execution-plan-2026-07-09.md +0 -315
  490. package/docs/release-v0.6.0.md +0 -71
  491. package/docs/release-v0.6.1.md +0 -75
  492. package/docs/release-v0.6.4.md +0 -45
  493. package/docs/roadmap-execution-and-acceptance.md +0 -365
  494. package/src/test/unit/acceptance-engine.test.ts +0 -261
  495. package/src/test/unit/agent-router.test.ts +0 -342
  496. package/src/test/unit/android-doctor.test.ts +0 -158
  497. package/src/test/unit/apply-patch.test.ts +0 -293
  498. package/src/test/unit/audit-checks.test.ts +0 -567
  499. package/src/test/unit/chinese-path.test.ts +0 -106
  500. package/src/test/unit/command-guard.test.ts +0 -221
  501. package/src/test/unit/create-task.test.ts +0 -255
  502. package/src/test/unit/diagnose-task.test.ts +0 -544
  503. package/src/test/unit/direct-guards.test.ts +0 -467
  504. package/src/test/unit/discovery-token-store.test.ts +0 -181
  505. package/src/test/unit/evidence-pack.test.ts +0 -251
  506. package/src/test/unit/get-task-status.test.ts +0 -203
  507. package/src/test/unit/get-task-summary.test.ts +0 -173
  508. package/src/test/unit/goal-graph.test.ts +0 -347
  509. package/src/test/unit/goal-progress.test.ts +0 -538
  510. package/src/test/unit/goal-report.test.ts +0 -189
  511. package/src/test/unit/goal-status.test.ts +0 -270
  512. package/src/test/unit/goal-store.test.ts +0 -318
  513. package/src/test/unit/goal-subgoal-task.test.ts +0 -72
  514. package/src/test/unit/goal-tools-registry.test.ts +0 -245
  515. package/src/test/unit/handoff-export.test.ts +0 -295
  516. package/src/test/unit/invoke-discovered-tool.test.ts +0 -216
  517. package/src/test/unit/logging.test.ts +0 -497
  518. package/src/test/unit/path-guard.test.ts +0 -180
  519. package/src/test/unit/post-task-cleanup.test.ts +0 -53
  520. package/src/test/unit/project-policy-release-mode.test.ts +0 -156
  521. package/src/test/unit/reconcile-tasks.test.ts +0 -551
  522. package/src/test/unit/release-gate.test.ts +0 -314
  523. package/src/test/unit/run-task-loop.test.ts +0 -425
  524. package/src/test/unit/safe-status.test.ts +0 -187
  525. package/src/test/unit/safe-views.test.ts +0 -184
  526. package/src/test/unit/schema-drift-check.test.ts +0 -260
  527. package/src/test/unit/sensitive-guard.test.ts +0 -124
  528. package/src/test/unit/spec-kit-import.test.ts +0 -429
  529. package/src/test/unit/subgoal-sync.test.ts +0 -236
  530. package/src/test/unit/sync-file.test.ts +0 -231
  531. package/src/test/unit/tool-invocation-guard.test.ts +0 -542
  532. package/src/test/unit/tool-usage-stats.test.ts +0 -384
  533. package/src/test/unit/toolSearch.test.ts +0 -756
  534. package/src/test/unit/wait-for-task.test.ts +0 -176
  535. package/src/test/unit/watcher-status.test.ts +0 -190
  536. package/src/test/unit/worktree-manager.test.ts +0 -247
  537. package/src/tools/cancelTask.ts +0 -70
  538. package/src/tools/retryTask.ts +0 -53
  539. package/src/tools/syncFile.ts +0 -122
  540. /package/dist/tools/{toolCatalog.d.ts → catalog/toolCatalog.d.ts} +0 -0
  541. /package/dist/tools/{toolSearch.d.ts → catalog/toolSearch.d.ts} +0 -0
  542. /package/dist/tools/{toolSearch.js → catalog/toolSearch.js} +0 -0
  543. /package/dist/tools/{toolUsageStats.d.ts → catalog/toolUsageStats.d.ts} +0 -0
  544. /package/dist/tools/{toolUsageStats.js → catalog/toolUsageStats.js} +0 -0
  545. /package/dist/tools/{createDirectSession.d.ts → direct/createDirectSession.d.ts} +0 -0
  546. /package/dist/tools/{runDirectVerificationBundle.d.ts → direct/runDirectVerificationBundle.d.ts} +0 -0
  547. /package/dist/tools/{getPlan.d.ts → goals/getPlan.d.ts} +0 -0
  548. /package/dist/tools/{savePlan.d.ts → goals/savePlan.d.ts} +0 -0
  549. /package/dist/tools/{evidencePack.d.ts → tasks/evidencePack.d.ts} +0 -0
  550. /package/dist/tools/{getTaskFile.d.ts → tasks/getTaskFile.d.ts} +0 -0
  551. /package/dist/tools/{getTaskProgress.d.ts → tasks/getTaskProgress.d.ts} +0 -0
  552. /package/dist/tools/{getTaskProgress.js → tasks/getTaskProgress.js} +0 -0
  553. /package/dist/tools/{getTaskStdoutTail.d.ts → tasks/getTaskStdoutTail.d.ts} +0 -0
  554. /package/dist/tools/{getTaskSummary.d.ts → tasks/getTaskSummary.d.ts} +0 -0
  555. /package/dist/tools/{killTask.js → tasks/killTask.js} +0 -0
  556. /package/dist/tools/{retryTask.d.ts → tasks/retryTask.d.ts} +0 -0
  557. /package/dist/tools/{runVerification.d.ts → tasks/runVerification.d.ts} +0 -0
  558. /package/dist/tools/{taskLineage.d.ts → tasks/taskLineage.d.ts} +0 -0
  559. /package/dist/tools/{taskOutputs.d.ts → tasks/taskOutputs.d.ts} +0 -0
  560. /package/dist/tools/{waitForTask.d.ts → tasks/waitForTask.d.ts} +0 -0
  561. /package/dist/tools/{waitForTask.js → tasks/waitForTask.js} +0 -0
  562. /package/dist/tools/{androidDoctor.d.ts → workspace/androidDoctor.d.ts} +0 -0
  563. /package/dist/tools/{discardWorktree.d.ts → workspace/discardWorktree.d.ts} +0 -0
  564. /package/dist/tools/{listWorkspace.d.ts → workspace/listWorkspace.d.ts} +0 -0
  565. /package/dist/tools/{mergeWorktree.d.ts → workspace/mergeWorktree.d.ts} +0 -0
  566. /package/dist/tools/{readWorkspaceFile.d.ts → workspace/readWorkspaceFile.d.ts} +0 -0
  567. /package/dist/tools/{recommendAgentForTask.d.ts → workspace/recommendAgentForTask.d.ts} +0 -0
  568. /package/dist/tools/{searchWorkspace.d.ts → workspace/searchWorkspace.d.ts} +0 -0
  569. /package/src/tools/{toolSearch.ts → catalog/toolSearch.ts} +0 -0
  570. /package/src/tools/{toolUsageStats.ts → catalog/toolUsageStats.ts} +0 -0
  571. /package/src/tools/{getTaskProgress.ts → tasks/getTaskProgress.ts} +0 -0
  572. /package/src/tools/{killTask.ts → tasks/killTask.ts} +0 -0
  573. /package/src/tools/{waitForTask.ts → tasks/waitForTask.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { type DirectSessionAuditOutput } from "../direct/directAudit.js";
1
+ import { type DirectSessionAuditOutput } from "../../direct/directAudit.js";
2
2
  export interface AuditSessionInput {
3
3
  session_id: string;
4
4
  }
@@ -1,5 +1,5 @@
1
- import { auditDirectSession, } from "../direct/directAudit.js";
2
- import { updateDirectSession } from "../direct/directSessionStore.js";
1
+ import { auditDirectSession, } from "../../direct/directAudit.js";
2
+ import { updateDirectSession } from "../../direct/directSessionStore.js";
3
3
  // ── Main function ──────────────────────────────────────────────────
4
4
  export function auditSession(input) {
5
5
  const { session_id } = input;
@@ -32,7 +32,7 @@ export interface AuditTaskOutput {
32
32
  manual_verification_items: string[];
33
33
  recommended_next_actions: string[];
34
34
  }
35
- import type { ChangedFile } from "../runner/changeCapture.js";
35
+ import type { ChangedFile } from "../../runner/changeCapture.js";
36
36
  /**
37
37
  * Check 1: forbidden_scope_violation (fail level).
38
38
  * Returns null when no forbidden patterns are configured (skip).
@@ -1,10 +1,13 @@
1
- import { readFileSync, existsSync, writeFileSync, readdirSync, statSync } from "node:fs";
1
+ import { readFileSync, existsSync, opendirSync, statSync } from "node:fs";
2
2
  import { join, resolve, relative, basename, sep, isAbsolute } from "node:path";
3
- import { getTasksDir, getConfig } from "../config.js";
4
- import { guardReadPath, guardWorkspacePath } from "../security/pathGuard.js";
5
- import { guardSensitivePath, isSensitivePath } from "../security/sensitiveGuard.js";
6
- import { evaluateAcceptance } from "../goal/acceptanceEngine.js";
7
- import { renderAcceptanceMarkdown } from "../goal/acceptanceTemplate.js";
3
+ import { getTasksDir, getConfig } from "../../config.js";
4
+ import { guardReadPath, guardWorkspacePath } from "../../security/pathGuard.js";
5
+ import { guardSensitivePath, isSensitivePath } from "../../security/sensitiveGuard.js";
6
+ import { evaluateAcceptance } from "../../goal/acceptanceEngine.js";
7
+ import { renderAcceptanceMarkdown } from "../../goal/acceptanceTemplate.js";
8
+ import { atomicWriteFileSync } from "../../utils/atomicFile.js";
9
+ import { mutateTaskStatus } from "../../runner/taskStatusStore.js";
10
+ import { readTextFilePrefixSync, readTextFileTailLinesSync, } from "../../utils/boundedFile.js";
8
11
  // Release claim patterns — anything that claims remote publish/release/deploy
9
12
  const RELEASE_PATTERNS = [
10
13
  /npm\s+package\s+version\s+published/i,
@@ -16,6 +19,10 @@ const RELEASE_PATTERNS = [
16
19
  /npm\s+publish\s+completed/i,
17
20
  /deploy(ed|ment)?\s+(to|on)\s+(npm|registry|github)/i,
18
21
  ];
22
+ const MAX_AUDIT_DOC_FILES = 200;
23
+ const MAX_AUDIT_DOC_FILE_BYTES = 512 * 1024;
24
+ const MAX_AUDIT_DOC_TOTAL_BYTES = 4 * 1024 * 1024;
25
+ const MAX_AUDIT_EVIDENCE_BYTES = 1024 * 1024;
19
26
  function scanForReleaseClaims(text) {
20
27
  const found = [];
21
28
  for (const pattern of RELEASE_PATTERNS) {
@@ -25,24 +32,57 @@ function scanForReleaseClaims(text) {
25
32
  }
26
33
  return found;
27
34
  }
28
- function findMdFiles(dir, maxDepth = 3) {
35
+ function findMdFiles(dir, maxDepth = 3, maxFiles = MAX_AUDIT_DOC_FILES) {
29
36
  const results = [];
30
- if (!existsSync(dir) || maxDepth <= 0)
31
- return results;
32
- try {
33
- const entries = readdirSync(dir, { withFileTypes: true });
34
- for (const e of entries) {
35
- const full = join(dir, e.name);
36
- if (e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules") {
37
- results.push(...findMdFiles(full, maxDepth - 1));
37
+ const pending = [{ path: dir, depth: maxDepth }];
38
+ const maxDirectories = maxFiles * 4;
39
+ let visitedDirectories = 0;
40
+ let truncated = false;
41
+ while (pending.length > 0 && results.length < maxFiles && visitedDirectories < maxDirectories) {
42
+ const current = pending.pop();
43
+ if (!existsSync(current.path) || current.depth <= 0)
44
+ continue;
45
+ visitedDirectories += 1;
46
+ let handle;
47
+ try {
48
+ handle = opendirSync(current.path);
49
+ while (results.length < maxFiles) {
50
+ const entry = handle.readSync();
51
+ if (!entry)
52
+ break;
53
+ const full = join(current.path, entry.name);
54
+ if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
55
+ if (pending.length < maxDirectories)
56
+ pending.push({ path: full, depth: current.depth - 1 });
57
+ else
58
+ truncated = true;
59
+ }
60
+ else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
61
+ results.push(full);
62
+ }
38
63
  }
39
- else if (e.isFile() && e.name.endsWith(".md")) {
40
- results.push(full);
64
+ }
65
+ catch { /* skip unreadable dirs */ }
66
+ finally {
67
+ try {
68
+ handle?.closeSync();
41
69
  }
70
+ catch { /* best effort */ }
42
71
  }
43
72
  }
44
- catch { /* skip unreadable dirs */ }
45
- return results;
73
+ truncated ||= pending.length > 0 || results.length >= maxFiles || visitedDirectories >= maxDirectories;
74
+ return { files: results, truncated };
75
+ }
76
+ function readAuditEvidence(path) {
77
+ const half = Math.floor(MAX_AUDIT_EVIDENCE_BYTES / 2);
78
+ const prefix = readTextFilePrefixSync(path, half);
79
+ if (!prefix.truncated)
80
+ return { content: prefix.content, truncated: false };
81
+ const tail = readTextFileTailLinesSync(path, 1000, half);
82
+ return {
83
+ content: `${prefix.content}\n[...audit evidence truncated...]\n${tail}`,
84
+ truncated: true,
85
+ };
46
86
  }
47
87
  // ── v0.7.2: New audit checks (exported for testing) ────────────────
48
88
  /**
@@ -606,20 +646,32 @@ export function auditTask(taskId) {
606
646
  if (existsSync(readmePath))
607
647
  docsToScan.push(readmePath);
608
648
  const docsDir = join(repoPathSafe, "docs");
649
+ let markdownEnumerationTruncated = false;
609
650
  if (existsSync(docsDir)) {
610
- docsToScan.push(...findMdFiles(docsDir));
651
+ const markdown = findMdFiles(docsDir);
652
+ docsToScan.push(...markdown.files);
653
+ markdownEnumerationTruncated = markdown.truncated;
611
654
  }
612
655
  // Collect all npm run references from all docs
613
656
  const allNpmRunRefs = new Set();
614
657
  const allReleaseClaims = [];
658
+ let remainingDocBytes = MAX_AUDIT_DOC_TOTAL_BYTES;
659
+ let documentScanTruncated = markdownEnumerationTruncated || docsToScan.length > MAX_AUDIT_DOC_FILES;
615
660
  for (const docPath of docsToScan) {
661
+ if (remainingDocBytes <= 0) {
662
+ documentScanTruncated = true;
663
+ break;
664
+ }
616
665
  let content;
617
666
  try {
618
667
  if (docPath !== resultFile) {
619
668
  guardReadPath(docPath, config.workspaceRoot);
620
669
  guardSensitivePath(docPath);
621
670
  }
622
- content = readFileSync(docPath, "utf-8");
671
+ const bounded = readTextFilePrefixSync(docPath, Math.min(MAX_AUDIT_DOC_FILE_BYTES, remainingDocBytes));
672
+ content = bounded.content;
673
+ remainingDocBytes -= Buffer.byteLength(content, "utf-8");
674
+ documentScanTruncated ||= bounded.truncated;
623
675
  }
624
676
  catch {
625
677
  continue;
@@ -636,6 +688,14 @@ export function auditTask(taskId) {
636
688
  for (const c of claims)
637
689
  allReleaseClaims.push(`[${relative(repoPathSafe, docPath) || docPath}] ${c}`);
638
690
  }
691
+ if (documentScanTruncated) {
692
+ checks.push({
693
+ name: "documentation_scan_bounded",
694
+ result: "warn",
695
+ detail: `Documentation scan reached its ${MAX_AUDIT_DOC_FILES}-file or ${MAX_AUDIT_DOC_TOTAL_BYTES}-byte safety budget.`,
696
+ });
697
+ addManualVerification("Review documentation omitted by the bounded audit scan.");
698
+ }
639
699
  // Cross-check npm run refs against package.json scripts
640
700
  for (const scriptName of allNpmRunRefs) {
641
701
  if (pkgScripts.length > 0 && !pkgScripts.includes(scriptName)) {
@@ -682,7 +742,10 @@ export function auditTask(taskId) {
682
742
  if (hasTestLog) {
683
743
  let logContent;
684
744
  try {
685
- logContent = readFileSync(testLogFile, "utf-8");
745
+ const evidence = readAuditEvidence(testLogFile);
746
+ logContent = evidence.content;
747
+ if (evidence.truncated)
748
+ addManualVerification("test.log exceeded the audit read budget; inspect the complete local artifact.");
686
749
  }
687
750
  catch {
688
751
  logContent = "";
@@ -720,7 +783,10 @@ export function auditTask(taskId) {
720
783
  let resultMdContent = null;
721
784
  if (hasResult) {
722
785
  try {
723
- resultMdContent = readFileSync(resultFile, "utf-8");
786
+ const evidence = readAuditEvidence(resultFile);
787
+ resultMdContent = evidence.content;
788
+ if (evidence.truncated)
789
+ addManualVerification("result.md exceeded the audit read budget; inspect the complete local artifact.");
724
790
  }
725
791
  catch {
726
792
  resultMdContent = null;
@@ -788,7 +854,7 @@ export function auditTask(taskId) {
788
854
  "## Recommended Actions",
789
855
  ...actions.map((a) => `- ${a}`),
790
856
  ].join("\n");
791
- writeFileSync(join(taskDir, "independent-review.md"), reviewMd, "utf-8");
857
+ atomicWriteFileSync(join(taskDir, "independent-review.md"), reviewMd);
792
858
  // ── v0.7.2: 集成 acceptanceEngine ──
793
859
  const releaseClaimsUnverified = allReleaseClaims.length > 0;
794
860
  const acceptanceEvidence = {
@@ -827,16 +893,20 @@ export function auditTask(taskId) {
827
893
  const acceptanceResult = evaluateAcceptance(acceptanceEvidence);
828
894
  // 回写 status.json 的 acceptance_status(仅对 done_by_agent 有意义)
829
895
  if (taskStatus === "done_by_agent") {
830
- const updatedStatus = {
831
- ...statusData,
896
+ const statusPatch = {
832
897
  acceptance_status: acceptanceResult.acceptance_status,
833
- updated_at: new Date().toISOString(),
834
898
  };
835
- writeFileSync(statusFile, JSON.stringify(updatedStatus, null, 2), "utf-8");
899
+ mutateTaskStatus(statusFile, (current) => {
900
+ if (current.status !== "done_by_agent") {
901
+ return { result: current };
902
+ }
903
+ const next = { ...current, ...statusPatch, updated_at: new Date().toISOString() };
904
+ return { next, result: next };
905
+ });
836
906
  }
837
907
  // 导出 ACCEPTANCE.md
838
908
  const acceptanceMd = renderAcceptanceMarkdown(taskId, acceptanceResult, acceptanceEvidence);
839
- writeFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd, "utf-8");
909
+ atomicWriteFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd);
840
910
  return {
841
911
  task_id: taskId,
842
912
  verdict,
@@ -1,4 +1,4 @@
1
- import type { ToolCatalogSnapshot } from "./toolCatalog.js";
1
+ import type { ToolCatalogSnapshot } from "../catalog/toolCatalog.js";
2
2
  export interface HealthCheckInput {
3
3
  detail?: "standard" | "self_diagnostic";
4
4
  }
@@ -14,9 +14,9 @@ export declare function healthCheck(catalog?: ToolCatalogSnapshot, input?: Healt
14
14
  recent_tasks_returned: number;
15
15
  recent_failures: {
16
16
  task_id: string;
17
- status: import("./createTask.js").TaskStatus;
18
- phase: import("./createTask.js").TaskPhase;
19
- pending_reason: import("../watcherStatus.js").PendingReason;
17
+ status: import("../tasks/createTask.js").TaskStatus;
18
+ phase: import("../tasks/createTask.js").TaskPhase;
19
+ pending_reason: import("../../watcherStatus.js").PendingReason;
20
20
  error: string | null;
21
21
  }[];
22
22
  } | undefined;
@@ -37,7 +37,7 @@ export declare function healthCheck(catalog?: ToolCatalogSnapshot, input?: Healt
37
37
  };
38
38
  watcher: {
39
39
  supervisor: Record<string, unknown>;
40
- status: import("../watcherStatus.js").WatcherState;
40
+ status: import("../../watcherStatus.js").WatcherState;
41
41
  available: boolean;
42
42
  stale_after_seconds: number;
43
43
  last_heartbeat_at: string | null;
@@ -65,7 +65,7 @@ export declare function healthCheck(catalog?: ToolCatalogSnapshot, input?: Healt
65
65
  tunnel: Record<string, unknown> & {
66
66
  last_error: string | null;
67
67
  };
68
- agents: import("./listAgents.js").AgentAvailability[];
68
+ agents: import("../workspace/listAgents.js").AgentAvailability[];
69
69
  agent_status: {
70
70
  [k: string]: string;
71
71
  };
@@ -1,13 +1,13 @@
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 { CHATGPT_CORE_TOOL_NAMES, CHATGPT_DIRECT_TOOL_NAMES, CHATGPT_SEARCH_TOOL_NAMES, resolveToolProfile } from "./toolCatalog.js";
9
- import { readWatcherStatus } from "../watcherStatus.js";
10
- 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 { CHATGPT_CORE_TOOL_NAMES, CHATGPT_DIRECT_TOOL_NAMES, CHATGPT_SEARCH_TOOL_NAMES, resolveToolProfile } from "../catalog/toolCatalog.js";
9
+ import { readWatcherStatus } from "../../watcherStatus.js";
10
+ import { listTasks } from "../tasks/listTasks.js";
11
11
  const SERVER_STARTED_AT = Date.now();
12
12
  export function healthCheck(catalog, input = {}) {
13
13
  const config = getConfig();
@@ -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";
@@ -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,6 +1,6 @@
1
- import { type PatchWardenConfig } from "../config.js";
2
- import type { TaskStatus, TaskPhase, AcceptanceStatus } from "./createTask.js";
3
- import { type DiagnosisType, type DiagnosisConfidence } from "./diagnoseTask.js";
1
+ import { type PatchWardenConfig } from "../../config.js";
2
+ import type { TaskStatus, TaskPhase, AcceptanceStatus } from "../tasks/createTask.js";
3
+ import { type DiagnosisType, type DiagnosisConfidence } from "../tasks/diagnoseTask.js";
4
4
  export interface SafeStatusOutput {
5
5
  task_id: string;
6
6
  status: TaskStatus | "not_found";
@@ -1,11 +1,11 @@
1
1
  import { readFileSync, existsSync } from "node:fs";
2
2
  import { resolve, join } from "node:path";
3
- import { getTasksDir, getConfig } from "../config.js";
4
- import { guardReadPath } from "../security/pathGuard.js";
5
- import { guardSensitivePath } from "../security/sensitiveGuard.js";
6
- import { readTaskRuntime } from "../taskRuntime.js";
7
- import { readWatcherStatus } from "../watcherStatus.js";
8
- import { diagnoseTask } from "./diagnoseTask.js";
3
+ import { getTasksDir, getConfig } from "../../config.js";
4
+ import { guardReadPath } from "../../security/pathGuard.js";
5
+ import { guardSensitivePath } from "../../security/sensitiveGuard.js";
6
+ import { readTaskRuntime } from "../../runner/taskRuntime.js";
7
+ import { readWatcherStatus } from "../../watcherStatus.js";
8
+ import { diagnoseTask } from "../tasks/diagnoseTask.js";
9
9
  export function safeStatus(taskId, config) {
10
10
  const cfg = config || getConfig();
11
11
  const tasksDir = getTasksDir(cfg);
@@ -2,6 +2,7 @@ export interface SafeViewOptions {
2
2
  max_items?: number;
3
3
  }
4
4
  export declare function safeResult(taskId: string, options?: SafeViewOptions): {
5
+ schema_version: string;
5
6
  task_id: string;
6
7
  status: string;
7
8
  terminal: boolean;
@@ -32,6 +33,7 @@ export declare function safeResult(taskId: string, options?: SafeViewOptions): {
32
33
  redaction_categories: string[];
33
34
  };
34
35
  export declare function safeTestSummary(taskId: string): {
36
+ schema_version: string;
35
37
  task_id: string;
36
38
  status: string;
37
39
  command_count: number;
@@ -41,19 +43,20 @@ export declare function safeTestSummary(taskId: string): {
41
43
  commands: {
42
44
  command: string;
43
45
  status: string;
44
- exit_code: any;
46
+ exit_code: {} | null;
45
47
  duration_ms: number;
46
48
  }[];
47
49
  headline: string;
48
50
  };
49
51
  export declare function safeDiffSummary(taskId: string, options?: SafeViewOptions): {
52
+ schema_version: string;
50
53
  task_id: string;
51
54
  changed_files_total: number;
52
55
  additions: number;
53
56
  deletions: number;
54
57
  diff_available: boolean;
55
58
  diff_truncated: boolean;
56
- patch_mode: any;
59
+ patch_mode: {} | null;
57
60
  files: {
58
61
  path: string;
59
62
  old_path: string | null;
@@ -62,13 +65,14 @@ export declare function safeDiffSummary(taskId: string, options?: SafeViewOption
62
65
  tracked: boolean;
63
66
  ignored: boolean;
64
67
  }[];
65
- artifact_hygiene_counts: Record<string, any>;
68
+ artifact_hygiene_counts: Record<string, unknown>;
66
69
  large_diff_omitted: boolean;
67
70
  truncated: boolean;
68
71
  };
69
72
  export declare function safeAudit(taskId: string, options?: SafeViewOptions): {
73
+ schema_version: string;
70
74
  task_id: string;
71
- verdict: "pass" | "warn" | "fail";
75
+ verdict: "warn" | "pass" | "fail";
72
76
  acceptance: {
73
77
  verdict: string;
74
78
  status: string;
@@ -84,17 +88,17 @@ export declare function safeAudit(taskId: string, options?: SafeViewOptions): {
84
88
  };
85
89
  checks: {
86
90
  name: string;
87
- result: "pass" | "warn" | "fail";
91
+ result: "warn" | "pass" | "fail";
88
92
  detail: string;
89
93
  }[];
90
94
  fail_checks: {
91
95
  name: string;
92
- result: "pass" | "warn" | "fail";
96
+ result: "warn" | "pass" | "fail";
93
97
  detail: string;
94
98
  }[];
95
99
  warn_checks: {
96
100
  name: string;
97
- result: "pass" | "warn" | "fail";
101
+ result: "warn" | "pass" | "fail";
98
102
  detail: string;
99
103
  }[];
100
104
  possible_false_positives: {
@@ -238,7 +242,7 @@ export declare function safeFinalizeDirectSession(sessionId: string, options?: S
238
242
  }>;
239
243
  export declare function safeAuditDirectSession(sessionId: string, options?: SafeViewOptions): {
240
244
  session_id: string;
241
- decision: "pass" | "warn" | "fail";
245
+ decision: "warn" | "pass" | "fail";
242
246
  reason_codes: string[];
243
247
  blocking_findings: string[];
244
248
  warnings: string[];
@@ -1,17 +1,19 @@
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 } 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 } from "../direct/directSessionStore.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 } from "../../direct/directSessionStore.js";
11
+ import { ARTIFACT_SCHEMA_VERSION } from "../../version.js";
11
12
  export function safeResult(taskId, options = {}) {
12
13
  const maxItems = normalizeMaxItems(options.max_items);
13
14
  const summary = getTaskSummary(taskId, { view: "compact", max_items: maxItems });
14
15
  return redact({
16
+ schema_version: ARTIFACT_SCHEMA_VERSION,
15
17
  task_id: summary.task_id,
16
18
  status: summary.status,
17
19
  terminal: summary.terminal,
@@ -39,13 +41,17 @@ export function safeTestSummary(taskId) {
39
41
  const { taskDir, config } = getTaskDir(taskId);
40
42
  const verify = readJson(join(taskDir, "verify.json"), config);
41
43
  const summary = getTaskSummary(taskId, { view: "compact", max_items: 8 });
42
- const commands = asArray(verify.commands).map((entry) => ({
43
- command: String(entry.command || ""),
44
- status: String(entry.status || "unknown"),
45
- exit_code: entry.exit_code ?? null,
46
- duration_ms: Number(entry.duration_ms || 0),
47
- }));
44
+ const commands = asArray(verify.commands).map((entry) => {
45
+ const command = asRecord(entry);
46
+ return {
47
+ command: String(command.command || ""),
48
+ status: String(command.status || "unknown"),
49
+ exit_code: command.exit_code ?? null,
50
+ duration_ms: Number(command.duration_ms || 0),
51
+ };
52
+ });
48
53
  return redact({
54
+ schema_version: ARTIFACT_SCHEMA_VERSION,
49
55
  task_id: taskId,
50
56
  status: String(verify.status || summary.verification_summary.status || "not_available"),
51
57
  command_count: commands.length,
@@ -63,6 +69,7 @@ export function safeDiffSummary(taskId, options = {}) {
63
69
  const changedFiles = asArray(changes.changed_files);
64
70
  const hygiene = asRecord(changes.artifact_hygiene);
65
71
  return redact({
72
+ schema_version: ARTIFACT_SCHEMA_VERSION,
66
73
  task_id: taskId,
67
74
  changed_files_total: changedFiles.length,
68
75
  additions: Number(changes.additions || 0),
@@ -128,6 +135,7 @@ function auditToSafe(audit, maxItems) {
128
135
  detail: truncate(check.detail, 240),
129
136
  }));
130
137
  return redact({
138
+ schema_version: ARTIFACT_SCHEMA_VERSION,
131
139
  task_id: audit.task_id,
132
140
  verdict: audit.verdict,
133
141
  acceptance: {
@@ -239,7 +247,9 @@ function asArray(value) {
239
247
  return Array.isArray(value) ? value : [];
240
248
  }
241
249
  function asRecord(value) {
242
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
250
+ return value && typeof value === "object" && !Array.isArray(value)
251
+ ? value
252
+ : {};
243
253
  }
244
254
  function limitStrings(values, maxItems) {
245
255
  return values.slice(0, maxItems).map((value) => truncate(value, 240));
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * 本模块只做检测和报告,不做运行时阻断。
8
8
  */
9
- import type { PatchWardenToolMeta } from "./toolRegistry.js";
9
+ import type { PatchWardenToolMeta } from "../catalog/toolRegistry.js";
10
10
  export interface SchemaDriftResult {
11
11
  /** true 表示无 drift,false 表示有 drift */
12
12
  ok: boolean;
@@ -6,8 +6,8 @@
6
6
  *
7
7
  * 本模块只做检测和报告,不做运行时阻断。
8
8
  */
9
- import { computeSchemaDigest } from "./toolRegistry.js";
10
- import { CHATGPT_CORE_TOOL_NAMES } from "./toolCatalog.js";
9
+ import { computeSchemaDigest } from "../catalog/toolRegistry.js";
10
+ import { CHATGPT_CORE_TOOL_NAMES } from "../catalog/toolCatalog.js";
11
11
  /** chatgpt_core profile 的预期工具数(来自 CHATGPT_CORE_TOOL_NAMES)。 */
12
12
  const EXPECTED_CORE_COUNT = CHATGPT_CORE_TOOL_NAMES.length;
13
13
  // ── 检查 1: registry schema digest 一致性 ─────────────────────────
@@ -1,10 +1,10 @@
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";
7
- import { createDirectSession as createDirectSessionRecord, } from "../direct/directSessionStore.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
+ import { createDirectSession as createDirectSessionRecord, } from "../../direct/directSessionStore.js";
8
8
  // ── Tool implementation ────────────────────────────────────────────
9
9
  export async function createDirectSession(input) {
10
10
  const config = getConfig();
@@ -1,4 +1,4 @@
1
- import { type ClassifiedChange } from "../runner/changeCapture.js";
1
+ import { type ClassifiedChange } from "../../runner/changeCapture.js";
2
2
  export interface FinalizeDirectSessionInput {
3
3
  session_id: string;
4
4
  }
@@ -0,0 +1,86 @@
1
+ import { join, resolve, relative, isAbsolute } from "node:path";
2
+ import { readDirectSession, finalizeDirectSessionRecord, getDirectSessionDir, withDirectSessionMutationLockAsync, } from "../../direct/directSessionStore.js";
3
+ import { guardDirectSessionActive } from "../../direct/directGuards.js";
4
+ import { captureRepoSnapshot, buildChangeArtifacts, } from "../../runner/changeCapture.js";
5
+ // ── Main function ──────────────────────────────────────────────────
6
+ export async function finalizeDirectSession(input) {
7
+ const { session_id } = input;
8
+ return withDirectSessionMutationLockAsync(session_id, async () => {
9
+ // 1. Read session and guard active (not expired, not finalized)
10
+ const session = readDirectSession(session_id);
11
+ guardDirectSessionActive(session);
12
+ // 2. Capture after snapshot
13
+ const afterSnapshot = await captureRepoSnapshot(session.resolved_repo_path);
14
+ // 3. Build change artifacts from before/after snapshots
15
+ const changeArtifacts = await buildChangeArtifacts(session.resolved_repo_path, session.workspace_snapshot_before, afterSnapshot);
16
+ // 4. Finalize session record — writes changed-files.json, diff.patch,
17
+ // summary.json, summary.md and marks the session as finalized.
18
+ finalizeDirectSessionRecord(session_id, changeArtifacts);
19
+ // 5. Build verification summary from session.verification_runs
20
+ const verification_summary = {};
21
+ for (const run of session.verification_runs) {
22
+ verification_summary[run.command] = run.passed ? "passed" : "failed";
23
+ }
24
+ // 6. Identify out-of-scope changes (paths outside resolved_repo_path)
25
+ const out_of_scope_changes = findOutOfScopeChanges(changeArtifacts, session.resolved_repo_path);
26
+ // 7. Build compact summary with categorized changes
27
+ const sessionDir = getDirectSessionDir(session_id);
28
+ return {
29
+ session_id,
30
+ changed_files_total: changeArtifacts.changed_files.length,
31
+ source_changes: changeArtifacts.artifact_hygiene.source_changes,
32
+ tracked_build_artifacts: changeArtifacts.artifact_hygiene.tracked_build_artifacts,
33
+ runtime_generated_files: changeArtifacts.artifact_hygiene.runtime_generated_files,
34
+ suspicious_changes: changeArtifacts.artifact_hygiene.suspicious_changes,
35
+ out_of_scope_changes,
36
+ verification_summary,
37
+ diff_path: join(sessionDir, "diff.patch"),
38
+ summary_path: join(sessionDir, "summary.md"),
39
+ finalized: true,
40
+ next_action: "Call audit_session to independently review the changes.",
41
+ };
42
+ });
43
+ }
44
+ // ── Helpers ────────────────────────────────────────────────────────
45
+ /**
46
+ * Filter changeArtifacts.changed_files for paths that resolve outside the
47
+ * session's resolved_repo_path and map them to ClassifiedChange format.
48
+ */
49
+ function findOutOfScopeChanges(artifacts, resolvedRepoPath) {
50
+ const normalizedRepo = resolve(resolvedRepoPath);
51
+ return artifacts.changed_files
52
+ .filter((file) => {
53
+ const fullPath = resolve(normalizedRepo, file.path);
54
+ const rel = relative(normalizedRepo, fullPath);
55
+ return isAbsolute(rel) || rel.startsWith("..");
56
+ })
57
+ .map((file) => toClassifiedChange(file));
58
+ }
59
+ /**
60
+ * Map a ChangedFile to the ClassifiedChange format by adding a reason string.
61
+ */
62
+ function toClassifiedChange(file) {
63
+ return {
64
+ path: file.path,
65
+ change: file.change,
66
+ tracked: file.tracked,
67
+ ignored: file.ignored,
68
+ kind: file.kind,
69
+ reason: classificationReason(file),
70
+ };
71
+ }
72
+ /**
73
+ * Produce a human-readable reason for a changed file classification.
74
+ * Mirrors the logic in changeCapture.ts classifyArtifactHygiene.
75
+ */
76
+ function classificationReason(change) {
77
+ if (change.ignored)
78
+ return "untracked path is ignored by repository Git rules";
79
+ if (change.kind === "build_artifact" && change.tracked)
80
+ return "artifact-like path is tracked by Git and requires review";
81
+ if (change.kind === "build_artifact")
82
+ return "artifact-like path is not ignored and requires review";
83
+ if (change.kind === "runtime_generated")
84
+ return "runtime-generated path is not ignored and requires review";
85
+ return change.tracked ? "tracked source change" : "untracked source change";
86
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./createDirectSession.js";
2
+ export * from "./finalizeDirectSession.js";
3
+ export * from "./runDirectVerificationBundle.js";
@@ -0,0 +1,3 @@
1
+ export * from "./createDirectSession.js";
2
+ export * from "./finalizeDirectSession.js";
3
+ export * from "./runDirectVerificationBundle.js";