patchwarden 1.5.1 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (591) hide show
  1. package/PatchWarden.cmd +32 -2
  2. package/README.en.md +158 -26
  3. package/README.md +124 -24
  4. package/dist/assessments/agentAssessor.js +21 -12
  5. package/dist/assessments/assessmentDiagnostics.d.ts +29 -0
  6. package/dist/assessments/assessmentDiagnostics.js +132 -0
  7. package/dist/assessments/assessmentStore.d.ts +39 -0
  8. package/dist/assessments/assessmentStore.js +207 -45
  9. package/dist/assessments/securitySnapshot.d.ts +50 -0
  10. package/dist/assessments/securitySnapshot.js +158 -0
  11. package/dist/config.d.ts +15 -0
  12. package/dist/config.js +66 -13
  13. package/dist/control/fileManager.d.ts +2 -0
  14. package/dist/control/fileManager.js +39 -0
  15. package/dist/control/middleware/auth.d.ts +6 -0
  16. package/dist/control/middleware/auth.js +14 -5
  17. package/dist/control/middleware/static.js +16 -3
  18. package/dist/control/routeTable.d.ts +24 -0
  19. package/dist/control/routeTable.js +263 -0
  20. package/dist/control/routes/audit.js +17 -7
  21. package/dist/control/routes/evidence.js +1 -1
  22. package/dist/control/routes/lineage.js +1 -1
  23. package/dist/control/routes/process.d.ts +7 -0
  24. package/dist/control/routes/process.js +329 -42
  25. package/dist/control/routes/sessions.d.ts +9 -1
  26. package/dist/control/routes/sessions.js +84 -21
  27. package/dist/control/routes/status.d.ts +60 -1
  28. package/dist/control/routes/status.js +94 -15
  29. package/dist/control/routes/taskActions.js +24 -60
  30. package/dist/control/routes/tasks.d.ts +4 -0
  31. package/dist/control/routes/tasks.js +61 -62
  32. package/dist/control/routes/workspace.js +50 -23
  33. package/dist/control/runtime.d.ts +3 -2
  34. package/dist/control/runtime.js +65 -40
  35. package/dist/control/server.js +37 -365
  36. package/dist/control/shared.d.ts +25 -1
  37. package/dist/control/shared.js +64 -11
  38. package/dist/diagnostics/allowedTestCommandSafety.d.ts +1 -0
  39. package/dist/diagnostics/allowedTestCommandSafety.js +11 -0
  40. package/dist/direct/directAudit.js +234 -225
  41. package/dist/direct/directGuards.d.ts +2 -1
  42. package/dist/direct/directGuards.js +42 -29
  43. package/dist/direct/directPatch.d.ts +6 -1
  44. package/dist/direct/directPatch.js +55 -8
  45. package/dist/direct/directSessionStore.d.ts +16 -6
  46. package/dist/direct/directSessionStore.js +128 -35
  47. package/dist/direct/directVerification.js +8 -16
  48. package/dist/doctor.js +65 -57
  49. package/dist/goal/acceptanceEngine.d.ts +1 -1
  50. package/dist/goal/goalProgress.js +75 -69
  51. package/dist/goal/goalReport.js +5 -12
  52. package/dist/goal/goalStatus.d.ts +2 -0
  53. package/dist/goal/goalStatus.js +10 -3
  54. package/dist/goal/goalStore.d.ts +9 -2
  55. package/dist/goal/goalStore.js +152 -45
  56. package/dist/goal/handoffExport.js +6 -6
  57. package/dist/goal/specKitImport.js +97 -96
  58. package/dist/goal/subgoalSync.js +11 -9
  59. package/dist/goal/worktreeManager.d.ts +2 -0
  60. package/dist/goal/worktreeManager.js +209 -136
  61. package/dist/httpServer.js +111 -32
  62. package/dist/logging.js +5 -3
  63. package/dist/policy/projectPolicy.js +5 -2
  64. package/dist/release/releaseGate.d.ts +1 -1
  65. package/dist/release/releaseGate.js +78 -25
  66. package/dist/runner/agentInvocation.d.ts +14 -0
  67. package/dist/runner/agentInvocation.js +96 -4
  68. package/dist/runner/changeCapture.d.ts +13 -5
  69. package/dist/runner/changeCapture.js +243 -61
  70. package/dist/runner/postTaskCleanup.js +48 -19
  71. package/dist/runner/processSecurity.d.ts +56 -0
  72. package/dist/runner/processSecurity.js +373 -0
  73. package/dist/runner/runTask.d.ts +2 -1
  74. package/dist/runner/runTask.js +162 -93
  75. package/dist/runner/simpleProcess.d.ts +3 -0
  76. package/dist/runner/simpleProcess.js +50 -36
  77. package/dist/{taskProgress.d.ts → runner/taskProgress.d.ts} +1 -1
  78. package/dist/{taskProgress.js → runner/taskProgress.js} +2 -2
  79. package/dist/{taskRuntime.d.ts → runner/taskRuntime.d.ts} +3 -1
  80. package/dist/{taskRuntime.js → runner/taskRuntime.js} +3 -2
  81. package/dist/runner/taskStatusStore.d.ts +11 -0
  82. package/dist/runner/taskStatusStore.js +35 -0
  83. package/dist/runner/watch.d.ts +14 -1
  84. package/dist/runner/watch.js +320 -49
  85. package/dist/security/contentRedaction.js +2 -2
  86. package/dist/security/discoveryTokenStore.d.ts +3 -2
  87. package/dist/security/discoveryTokenStore.js +17 -2
  88. package/dist/security/loopbackHost.d.ts +2 -0
  89. package/dist/security/loopbackHost.js +16 -0
  90. package/dist/security/pathGuard.js +32 -17
  91. package/dist/security/planGuard.js +2 -1
  92. package/dist/security/runtimeGuard.js +9 -6
  93. package/dist/security/secretComparison.d.ts +3 -0
  94. package/dist/security/secretComparison.js +11 -0
  95. package/dist/security/sensitiveGuard.d.ts +5 -0
  96. package/dist/security/sensitiveGuard.js +27 -8
  97. package/dist/security/toolInvocationGuard.d.ts +2 -2
  98. package/dist/security/toolInvocationGuard.js +1 -1
  99. package/dist/security/workspaceRootGuard.d.ts +8 -0
  100. package/dist/security/workspaceRootGuard.js +47 -0
  101. package/dist/smoke-test.js +27 -26
  102. package/dist/tools/catalog/index.d.ts +4 -0
  103. package/dist/tools/catalog/index.js +4 -0
  104. package/dist/tools/{toolCatalog.js → catalog/toolCatalog.js} +3 -12
  105. package/dist/tools/{toolRegistry.d.ts → catalog/toolRegistry.d.ts} +3 -3
  106. package/dist/tools/{toolRegistry.js → catalog/toolRegistry.js} +6 -15
  107. package/dist/tools/definitions/toolDefs.d.ts +18 -0
  108. package/dist/tools/definitions/toolDefs.js +1177 -0
  109. package/dist/tools/{auditSession.d.ts → diagnostics/auditSession.d.ts} +1 -1
  110. package/dist/tools/{auditSession.js → diagnostics/auditSession.js} +2 -2
  111. package/dist/tools/{auditTask.d.ts → diagnostics/auditTask.d.ts} +2 -1
  112. package/dist/tools/{auditTask.js → diagnostics/auditTask.js} +134 -36
  113. package/dist/tools/{healthCheck.d.ts → diagnostics/healthCheck.d.ts} +18 -6
  114. package/dist/tools/{healthCheck.js → diagnostics/healthCheck.js} +36 -8
  115. package/dist/tools/diagnostics/index.d.ts +6 -0
  116. package/dist/tools/diagnostics/index.js +6 -0
  117. package/dist/tools/{safeStatus.d.ts → diagnostics/safeStatus.d.ts} +3 -3
  118. package/dist/tools/{safeStatus.js → diagnostics/safeStatus.js} +6 -6
  119. package/dist/tools/{safeViews.d.ts → diagnostics/safeViews.d.ts} +12 -8
  120. package/dist/tools/{safeViews.js → diagnostics/safeViews.js} +23 -13
  121. package/dist/tools/{schemaDriftCheck.d.ts → diagnostics/schemaDriftCheck.d.ts} +1 -1
  122. package/dist/tools/{schemaDriftCheck.js → diagnostics/schemaDriftCheck.js} +2 -2
  123. package/dist/tools/{createDirectSession.js → direct/createDirectSession.js} +6 -6
  124. package/dist/tools/{finalizeDirectSession.d.ts → direct/finalizeDirectSession.d.ts} +1 -1
  125. package/dist/tools/direct/finalizeDirectSession.js +86 -0
  126. package/dist/tools/direct/index.d.ts +3 -0
  127. package/dist/tools/direct/index.js +3 -0
  128. package/dist/tools/{runDirectVerificationBundle.js → direct/runDirectVerificationBundle.js} +2 -2
  129. package/dist/tools/{discoverTools.d.ts → discovery/discoverTools.d.ts} +2 -2
  130. package/dist/tools/{discoverTools.js → discovery/discoverTools.js} +5 -5
  131. package/dist/tools/{explainTool.d.ts → discovery/explainTool.d.ts} +2 -2
  132. package/dist/tools/{explainTool.js → discovery/explainTool.js} +2 -2
  133. package/dist/tools/discovery/index.d.ts +3 -0
  134. package/dist/tools/discovery/index.js +3 -0
  135. package/dist/tools/{invokeDiscoveredTool.d.ts → discovery/invokeDiscoveredTool.d.ts} +2 -2
  136. package/dist/tools/{invokeDiscoveredTool.js → discovery/invokeDiscoveredTool.js} +5 -5
  137. package/dist/tools/dispatch/coreDispatch.js +32 -31
  138. package/dist/tools/dispatch/diagnosticDispatch.d.ts +3 -5
  139. package/dist/tools/dispatch/diagnosticDispatch.js +70 -68
  140. package/dist/tools/dispatch/directDispatch.js +11 -10
  141. package/dist/tools/dispatch/goalDispatch.js +5 -4
  142. package/dist/tools/dispatch/releaseDispatch.js +3 -2
  143. package/dist/tools/dispatch/validation.d.ts +7 -0
  144. package/dist/tools/dispatch/validation.js +71 -0
  145. package/dist/tools/{getPlan.js → goals/getPlan.js} +4 -4
  146. package/dist/tools/{goalSubgoalTask.d.ts → goals/goalSubgoalTask.d.ts} +1 -1
  147. package/dist/tools/goals/goalSubgoalTask.js +118 -0
  148. package/dist/tools/goals/index.d.ts +3 -0
  149. package/dist/tools/goals/index.js +3 -0
  150. package/dist/tools/{savePlan.js → goals/savePlan.js} +28 -8
  151. package/dist/tools/registry.d.ts +7 -11
  152. package/dist/tools/registry.js +17 -1178
  153. package/dist/tools/{checkReleaseGate.d.ts → release/checkReleaseGate.d.ts} +1 -1
  154. package/dist/tools/{checkReleaseGate.js → release/checkReleaseGate.js} +3 -3
  155. package/dist/tools/release/index.d.ts +2 -0
  156. package/dist/tools/release/index.js +2 -0
  157. package/dist/tools/{releaseMode.d.ts → release/releaseMode.d.ts} +2 -2
  158. package/dist/tools/{releaseMode.js → release/releaseMode.js} +46 -26
  159. package/dist/tools/tasks/cancelTask.d.ts +11 -0
  160. package/dist/tools/tasks/cancelTask.js +86 -0
  161. package/dist/tools/{createTask.d.ts → tasks/createTask.d.ts} +12 -4
  162. package/dist/tools/{createTask.js → tasks/createTask.js} +110 -34
  163. package/dist/tools/{diagnoseTask.d.ts → tasks/diagnoseTask.d.ts} +1 -1
  164. package/dist/tools/{diagnoseTask.js → tasks/diagnoseTask.js} +12 -16
  165. package/dist/tools/{evidencePack.js → tasks/evidencePack.js} +34 -22
  166. package/dist/tools/{getTaskFile.js → tasks/getTaskFile.js} +4 -4
  167. package/dist/tools/{getTaskStatus.d.ts → tasks/getTaskStatus.d.ts} +6 -1
  168. package/dist/tools/{getTaskStatus.js → tasks/getTaskStatus.js} +11 -6
  169. package/dist/tools/{getTaskStdoutTail.js → tasks/getTaskStdoutTail.js} +13 -11
  170. package/dist/tools/{getTaskSummary.js → tasks/getTaskSummary.js} +35 -36
  171. package/dist/tools/tasks/index.d.ts +18 -0
  172. package/dist/tools/tasks/index.js +18 -0
  173. package/dist/tools/tasks/killTask.d.ts +1 -0
  174. package/dist/tools/{listTasks.d.ts → tasks/listTasks.d.ts} +1 -1
  175. package/dist/tools/{listTasks.js → tasks/listTasks.js} +5 -4
  176. package/dist/tools/{reconcileTasks.d.ts → tasks/reconcileTasks.d.ts} +3 -2
  177. package/dist/tools/tasks/reconcileTasks.js +496 -0
  178. package/dist/tools/tasks/retryTask.js +60 -0
  179. package/dist/tools/{runTaskLoop.d.ts → tasks/runTaskLoop.d.ts} +6 -6
  180. package/dist/tools/{runTaskLoop.js → tasks/runTaskLoop.js} +63 -41
  181. package/dist/tools/tasks/runVerification.js +38 -0
  182. package/dist/tools/{taskLineage.js → tasks/taskLineage.js} +8 -7
  183. package/dist/tools/{taskOutputs.d.ts → tasks/taskOutputs.d.ts} +2 -2
  184. package/dist/tools/{taskOutputs.js → tasks/taskOutputs.js} +17 -16
  185. package/dist/tools/tasks/taskStates.d.ts +6 -0
  186. package/dist/tools/tasks/taskStates.js +52 -0
  187. package/dist/tools/{waitForTask.js → tasks/waitForTask.js} +3 -11
  188. package/dist/tools/{androidDoctor.js → workspace/androidDoctor.js} +16 -10
  189. package/dist/tools/{applyPatch.d.ts → workspace/applyPatch.d.ts} +1 -1
  190. package/dist/tools/workspace/applyPatch.js +53 -0
  191. package/dist/tools/{discardWorktree.js → workspace/discardWorktree.js} +3 -3
  192. package/dist/tools/workspace/index.d.ts +10 -0
  193. package/dist/tools/workspace/index.js +10 -0
  194. package/dist/tools/workspace/listAgents.d.ts +23 -0
  195. package/dist/tools/workspace/listAgents.js +56 -0
  196. package/dist/tools/{listWorkspace.js → workspace/listWorkspace.js} +3 -3
  197. package/dist/tools/{mergeWorktree.js → workspace/mergeWorktree.js} +3 -3
  198. package/dist/tools/{readWorkspaceFile.js → workspace/readWorkspaceFile.js} +8 -8
  199. package/dist/tools/{recommendAgentForTask.js → workspace/recommendAgentForTask.js} +3 -3
  200. package/dist/tools/{searchWorkspace.js → workspace/searchWorkspace.js} +5 -5
  201. package/dist/tools/{syncFile.d.ts → workspace/syncFile.d.ts} +1 -1
  202. package/dist/tools/workspace/syncFile.js +134 -0
  203. package/dist/utils/atomicFile.d.ts +7 -0
  204. package/dist/utils/atomicFile.js +67 -0
  205. package/dist/utils/boundedFile.d.ts +8 -0
  206. package/dist/utils/boundedFile.js +93 -0
  207. package/dist/utils/lockedJsonFile.d.ts +15 -0
  208. package/dist/utils/lockedJsonFile.js +224 -0
  209. package/dist/utils/platform.d.ts +11 -0
  210. package/dist/utils/platform.js +26 -0
  211. package/dist/utils/stableJson.d.ts +2 -0
  212. package/dist/utils/stableJson.js +12 -0
  213. package/dist/version.d.ts +3 -2
  214. package/dist/version.js +3 -2
  215. package/dist/watcherStatus.d.ts +2 -2
  216. package/dist/watcherStatus.js +18 -0
  217. package/docs/CODE_WIKI.md +808 -143
  218. package/docs/architecture.md +15 -55
  219. package/docs/assets/patchwarden-desktop-onboarding.png +0 -0
  220. package/docs/control-center/README.md +4 -4
  221. package/docs/dashboard-overview.md +4 -4
  222. package/docs/desktop-app.md +175 -0
  223. package/docs/evidence-pack-schema.md +3 -3
  224. package/docs/open-source-application.md +16 -11
  225. package/docs/release-checklist.md +1 -1
  226. package/docs/release-evidence.md +35 -39
  227. package/docs/task-safe-review-workflow.md +5 -5
  228. package/docs/threat-model.md +19 -1
  229. package/examples/config.example.json +4 -2
  230. package/package.json +27 -10
  231. package/scripts/README.md +15 -6
  232. package/scripts/build.js +11 -0
  233. package/scripts/checks/brand-check.js +3 -0
  234. package/scripts/checks/build-output-check.js +37 -0
  235. package/scripts/checks/control-center-smoke.js +102 -10
  236. package/scripts/checks/control-smoke.js +19 -8
  237. package/scripts/checks/http-mcp-smoke.js +82 -4
  238. package/scripts/checks/lifecycle-smoke.js +15 -12
  239. package/scripts/checks/mcp-manifest-check.js +1 -1
  240. package/scripts/checks/mcp-smoke.js +58 -4
  241. package/scripts/checks/package-manifest-check.js +20 -7
  242. package/scripts/checks/unit-tests.js +3 -5
  243. package/scripts/checks/watcher-supervisor-smoke.js +38 -1
  244. package/scripts/control/get-patchwarden-health.ps1 +1 -1
  245. package/scripts/control/manage-patchwarden.ps1 +69 -4
  246. package/scripts/control/provision-patchwarden-tunnel.ps1 +127 -0
  247. package/scripts/control/run-background-supervisor.ps1 +41 -0
  248. package/scripts/control/start-patchwarden-tunnel.ps1 +191 -33
  249. package/scripts/e2e/demo-runtime.mjs +153 -0
  250. package/{PatchWarden-Control-Tray.cmd → scripts/launchers/PatchWarden-Control-Tray.cmd} +3 -3
  251. package/scripts/launchers/PatchWarden-Control.cmd +6 -0
  252. package/{PatchWarden-Desktop.cmd → scripts/launchers/PatchWarden-Desktop.cmd} +2 -2
  253. package/scripts/launchers/Restart-PatchWarden-Control.cmd +6 -0
  254. package/{Stop-PatchWarden.cmd → scripts/launchers/Stop-PatchWarden.cmd} +2 -2
  255. package/scripts/lib/clean-generated-output.js +11 -0
  256. package/scripts/lib/file-discovery.js +12 -0
  257. package/scripts/release/desktop-preflight.js +211 -0
  258. package/scripts/release/pack-clean.js +59 -14
  259. package/src/assessments/agentAssessor.ts +26 -12
  260. package/src/assessments/assessmentDiagnostics.ts +172 -0
  261. package/src/assessments/assessmentStore.ts +288 -51
  262. package/src/assessments/securitySnapshot.ts +231 -0
  263. package/src/config.ts +70 -13
  264. package/src/control/fileManager.ts +40 -0
  265. package/src/control/middleware/auth.ts +22 -4
  266. package/src/control/middleware/static.ts +16 -3
  267. package/src/control/routeTable.ts +301 -0
  268. package/src/control/routes/audit.ts +14 -6
  269. package/src/control/routes/evidence.ts +1 -1
  270. package/src/control/routes/lineage.ts +1 -1
  271. package/src/control/routes/process.ts +341 -40
  272. package/src/control/routes/sessions.ts +88 -25
  273. package/src/control/routes/status.ts +134 -17
  274. package/src/control/routes/taskActions.ts +24 -58
  275. package/src/control/routes/tasks.ts +66 -58
  276. package/src/control/routes/workspace.ts +56 -25
  277. package/src/control/runtime.ts +71 -43
  278. package/src/control/server.ts +37 -342
  279. package/src/control/shared.ts +77 -11
  280. package/src/diagnostics/allowedTestCommandSafety.ts +12 -0
  281. package/src/direct/directAudit.ts +17 -9
  282. package/src/direct/directGuards.ts +72 -44
  283. package/src/direct/directPatch.ts +95 -8
  284. package/src/direct/directSessionStore.ts +213 -55
  285. package/src/direct/directVerification.ts +9 -23
  286. package/src/doctor.ts +76 -64
  287. package/src/goal/acceptanceEngine.ts +1 -1
  288. package/src/goal/goalProgress.ts +17 -13
  289. package/src/goal/goalReport.ts +5 -13
  290. package/src/goal/goalStatus.ts +19 -3
  291. package/src/goal/goalStore.ts +241 -54
  292. package/src/goal/handoffExport.ts +6 -6
  293. package/src/goal/specKitImport.ts +12 -12
  294. package/src/goal/subgoalSync.ts +11 -8
  295. package/src/goal/worktreeManager.ts +139 -22
  296. package/src/httpServer.ts +113 -30
  297. package/src/logging.ts +10 -3
  298. package/src/policy/projectPolicy.ts +5 -2
  299. package/src/release/releaseGate.ts +74 -27
  300. package/src/runner/agentInvocation.ts +126 -4
  301. package/src/runner/changeCapture.ts +291 -57
  302. package/src/runner/postTaskCleanup.ts +41 -17
  303. package/src/runner/processSecurity.ts +433 -0
  304. package/src/runner/runTask.ts +197 -97
  305. package/src/runner/simpleProcess.ts +66 -31
  306. package/src/{taskProgress.ts → runner/taskProgress.ts} +3 -3
  307. package/src/{taskRuntime.ts → runner/taskRuntime.ts} +6 -3
  308. package/src/runner/taskStatusStore.ts +69 -0
  309. package/src/runner/watch.ts +348 -52
  310. package/src/security/contentRedaction.ts +2 -2
  311. package/src/security/discoveryTokenStore.ts +18 -4
  312. package/src/security/loopbackHost.ts +19 -0
  313. package/src/security/pathGuard.ts +35 -16
  314. package/src/security/planGuard.ts +2 -1
  315. package/src/security/runtimeGuard.ts +9 -6
  316. package/src/security/secretComparison.ts +13 -0
  317. package/src/security/sensitiveGuard.ts +27 -8
  318. package/src/security/toolInvocationGuard.ts +2 -2
  319. package/src/security/workspaceRootGuard.ts +53 -0
  320. package/src/smoke-test.ts +27 -26
  321. package/src/tools/catalog/index.ts +4 -0
  322. package/src/tools/{toolCatalog.ts → catalog/toolCatalog.ts} +3 -12
  323. package/src/tools/{toolRegistry.ts → catalog/toolRegistry.ts} +7 -16
  324. package/src/tools/definitions/toolDefs.ts +1264 -0
  325. package/src/tools/{auditSession.ts → diagnostics/auditSession.ts} +2 -2
  326. package/src/tools/{auditTask.ts → diagnostics/auditTask.ts} +136 -39
  327. package/src/tools/{healthCheck.ts → diagnostics/healthCheck.ts} +37 -9
  328. package/src/tools/diagnostics/index.ts +6 -0
  329. package/src/tools/{safeStatus.ts → diagnostics/safeStatus.ts} +7 -7
  330. package/src/tools/{safeViews.ts → diagnostics/safeViews.ts} +27 -17
  331. package/src/tools/{schemaDriftCheck.ts → diagnostics/schemaDriftCheck.ts} +3 -3
  332. package/src/tools/{createDirectSession.ts → direct/createDirectSession.ts} +6 -6
  333. package/src/tools/{finalizeDirectSession.ts → direct/finalizeDirectSession.ts} +7 -5
  334. package/src/tools/direct/index.ts +3 -0
  335. package/src/tools/{runDirectVerificationBundle.ts → direct/runDirectVerificationBundle.ts} +2 -2
  336. package/src/tools/{discoverTools.ts → discovery/discoverTools.ts} +6 -6
  337. package/src/tools/{explainTool.ts → discovery/explainTool.ts} +3 -3
  338. package/src/tools/discovery/index.ts +3 -0
  339. package/src/tools/{invokeDiscoveredTool.ts → discovery/invokeDiscoveredTool.ts} +7 -7
  340. package/src/tools/dispatch/coreDispatch.ts +36 -31
  341. package/src/tools/dispatch/diagnosticDispatch.ts +26 -21
  342. package/src/tools/dispatch/directDispatch.ts +11 -10
  343. package/src/tools/dispatch/goalDispatch.ts +5 -4
  344. package/src/tools/dispatch/releaseDispatch.ts +3 -2
  345. package/src/tools/dispatch/validation.ts +78 -0
  346. package/src/tools/{getPlan.ts → goals/getPlan.ts} +4 -4
  347. package/src/tools/{goalSubgoalTask.ts → goals/goalSubgoalTask.ts} +41 -26
  348. package/src/tools/goals/index.ts +3 -0
  349. package/src/tools/{savePlan.ts → goals/savePlan.ts} +38 -8
  350. package/src/tools/registry.ts +17 -1261
  351. package/src/tools/{checkReleaseGate.ts → release/checkReleaseGate.ts} +3 -3
  352. package/src/tools/release/index.ts +2 -0
  353. package/src/tools/{releaseMode.ts → release/releaseMode.ts} +42 -24
  354. package/src/tools/tasks/cancelTask.ts +110 -0
  355. package/src/tools/{createTask.ts → tasks/createTask.ts} +161 -33
  356. package/src/tools/{diagnoseTask.ts → tasks/diagnoseTask.ts} +12 -16
  357. package/src/tools/{evidencePack.ts → tasks/evidencePack.ts} +36 -22
  358. package/src/tools/{getTaskFile.ts → tasks/getTaskFile.ts} +4 -4
  359. package/src/tools/{getTaskStatus.ts → tasks/getTaskStatus.ts} +13 -6
  360. package/src/tools/{getTaskStdoutTail.ts → tasks/getTaskStdoutTail.ts} +13 -11
  361. package/src/tools/{getTaskSummary.ts → tasks/getTaskSummary.ts} +46 -44
  362. package/src/tools/tasks/index.ts +18 -0
  363. package/src/tools/{listTasks.ts → tasks/listTasks.ts} +6 -5
  364. package/src/tools/{reconcileTasks.ts → tasks/reconcileTasks.ts} +228 -77
  365. package/src/tools/tasks/retryTask.ts +69 -0
  366. package/src/tools/{runTaskLoop.ts → tasks/runTaskLoop.ts} +73 -46
  367. package/src/tools/{runVerification.ts → tasks/runVerification.ts} +6 -3
  368. package/src/tools/{taskLineage.ts → tasks/taskLineage.ts} +8 -7
  369. package/src/tools/{taskOutputs.ts → tasks/taskOutputs.ts} +27 -20
  370. package/src/tools/tasks/taskStates.ts +54 -0
  371. package/src/tools/{waitForTask.ts → tasks/waitForTask.ts} +3 -12
  372. package/src/tools/{androidDoctor.ts → workspace/androidDoctor.ts} +15 -10
  373. package/src/tools/{applyPatch.ts → workspace/applyPatch.ts} +38 -16
  374. package/src/tools/{discardWorktree.ts → workspace/discardWorktree.ts} +3 -3
  375. package/src/tools/workspace/index.ts +10 -0
  376. package/src/tools/workspace/listAgents.ts +75 -0
  377. package/src/tools/{listWorkspace.ts → workspace/listWorkspace.ts} +3 -3
  378. package/src/tools/{mergeWorktree.ts → workspace/mergeWorktree.ts} +3 -3
  379. package/src/tools/{readWorkspaceFile.ts → workspace/readWorkspaceFile.ts} +8 -8
  380. package/src/tools/{recommendAgentForTask.ts → workspace/recommendAgentForTask.ts} +3 -3
  381. package/src/tools/{searchWorkspace.ts → workspace/searchWorkspace.ts} +5 -5
  382. package/src/tools/workspace/syncFile.ts +292 -0
  383. package/src/utils/atomicFile.ts +74 -0
  384. package/src/utils/boundedFile.ts +116 -0
  385. package/src/utils/lockedJsonFile.ts +251 -0
  386. package/src/utils/platform.ts +31 -0
  387. package/src/utils/stableJson.ts +12 -0
  388. package/src/version.ts +3 -2
  389. package/src/watcherStatus.ts +19 -1
  390. package/ui/desktop-bootstrap.js +11 -0
  391. package/ui/desktop-bridge.js +36 -0
  392. package/ui/desktop.css +160 -0
  393. package/ui/getting-started.js +93 -0
  394. package/ui/i18n.js +484 -0
  395. package/ui/log-parser.js +30 -0
  396. package/ui/pages/audit.html +12 -0
  397. package/ui/pages/dashboard.html +94 -147
  398. package/ui/pages/direct-sessions.html +123 -26
  399. package/ui/pages/getting-started.html +43 -0
  400. package/ui/pages/logs.html +134 -22
  401. package/ui/pages/settings.html +101 -0
  402. package/ui/pages/task-detail.html +12 -0
  403. package/ui/pages/tasks.html +54 -8
  404. package/ui/pages/workspace.html +38 -1
  405. package/ui/settings.js +254 -0
  406. package/PatchWarden-Control.cmd +0 -6
  407. package/Restart-PatchWarden-Control.cmd +0 -6
  408. package/dist/test/unit/acceptance-engine.test.d.ts +0 -1
  409. package/dist/test/unit/acceptance-engine.test.js +0 -228
  410. package/dist/test/unit/agent-router.test.d.ts +0 -1
  411. package/dist/test/unit/agent-router.test.js +0 -287
  412. package/dist/test/unit/android-doctor.test.d.ts +0 -1
  413. package/dist/test/unit/android-doctor.test.js +0 -118
  414. package/dist/test/unit/apply-patch.test.d.ts +0 -1
  415. package/dist/test/unit/apply-patch.test.js +0 -225
  416. package/dist/test/unit/audit-checks.test.d.ts +0 -1
  417. package/dist/test/unit/audit-checks.test.js +0 -350
  418. package/dist/test/unit/chinese-path.test.d.ts +0 -1
  419. package/dist/test/unit/chinese-path.test.js +0 -91
  420. package/dist/test/unit/command-guard.test.d.ts +0 -1
  421. package/dist/test/unit/command-guard.test.js +0 -160
  422. package/dist/test/unit/create-task.test.d.ts +0 -1
  423. package/dist/test/unit/create-task.test.js +0 -197
  424. package/dist/test/unit/diagnose-task.test.d.ts +0 -1
  425. package/dist/test/unit/diagnose-task.test.js +0 -457
  426. package/dist/test/unit/direct-guards.test.d.ts +0 -1
  427. package/dist/test/unit/direct-guards.test.js +0 -328
  428. package/dist/test/unit/discovery-token-store.test.d.ts +0 -1
  429. package/dist/test/unit/discovery-token-store.test.js +0 -139
  430. package/dist/test/unit/evidence-pack.test.d.ts +0 -1
  431. package/dist/test/unit/evidence-pack.test.js +0 -224
  432. package/dist/test/unit/get-task-status.test.d.ts +0 -1
  433. package/dist/test/unit/get-task-status.test.js +0 -174
  434. package/dist/test/unit/get-task-summary.test.d.ts +0 -1
  435. package/dist/test/unit/get-task-summary.test.js +0 -146
  436. package/dist/test/unit/goal-graph.test.d.ts +0 -1
  437. package/dist/test/unit/goal-graph.test.js +0 -298
  438. package/dist/test/unit/goal-progress.test.d.ts +0 -1
  439. package/dist/test/unit/goal-progress.test.js +0 -381
  440. package/dist/test/unit/goal-report.test.d.ts +0 -1
  441. package/dist/test/unit/goal-report.test.js +0 -159
  442. package/dist/test/unit/goal-status.test.d.ts +0 -1
  443. package/dist/test/unit/goal-status.test.js +0 -215
  444. package/dist/test/unit/goal-store.test.d.ts +0 -1
  445. package/dist/test/unit/goal-store.test.js +0 -253
  446. package/dist/test/unit/goal-subgoal-task.test.d.ts +0 -1
  447. package/dist/test/unit/goal-subgoal-task.test.js +0 -55
  448. package/dist/test/unit/goal-tools-registry.test.d.ts +0 -1
  449. package/dist/test/unit/goal-tools-registry.test.js +0 -192
  450. package/dist/test/unit/handoff-export.test.d.ts +0 -1
  451. package/dist/test/unit/handoff-export.test.js +0 -263
  452. package/dist/test/unit/invoke-discovered-tool.test.d.ts +0 -1
  453. package/dist/test/unit/invoke-discovered-tool.test.js +0 -167
  454. package/dist/test/unit/logging.test.d.ts +0 -1
  455. package/dist/test/unit/logging.test.js +0 -397
  456. package/dist/test/unit/path-guard.test.d.ts +0 -1
  457. package/dist/test/unit/path-guard.test.js +0 -133
  458. package/dist/test/unit/post-task-cleanup.test.d.ts +0 -1
  459. package/dist/test/unit/post-task-cleanup.test.js +0 -48
  460. package/dist/test/unit/project-policy-release-mode.test.d.ts +0 -1
  461. package/dist/test/unit/project-policy-release-mode.test.js +0 -125
  462. package/dist/test/unit/reconcile-tasks.test.d.ts +0 -1
  463. package/dist/test/unit/reconcile-tasks.test.js +0 -456
  464. package/dist/test/unit/release-gate.test.d.ts +0 -1
  465. package/dist/test/unit/release-gate.test.js +0 -242
  466. package/dist/test/unit/run-task-loop.test.d.ts +0 -1
  467. package/dist/test/unit/run-task-loop.test.js +0 -380
  468. package/dist/test/unit/safe-status.test.d.ts +0 -1
  469. package/dist/test/unit/safe-status.test.js +0 -165
  470. package/dist/test/unit/safe-views.test.d.ts +0 -1
  471. package/dist/test/unit/safe-views.test.js +0 -171
  472. package/dist/test/unit/schema-drift-check.test.d.ts +0 -1
  473. package/dist/test/unit/schema-drift-check.test.js +0 -176
  474. package/dist/test/unit/sensitive-guard.test.d.ts +0 -1
  475. package/dist/test/unit/sensitive-guard.test.js +0 -104
  476. package/dist/test/unit/spec-kit-import.test.d.ts +0 -1
  477. package/dist/test/unit/spec-kit-import.test.js +0 -341
  478. package/dist/test/unit/subgoal-sync.test.d.ts +0 -1
  479. package/dist/test/unit/subgoal-sync.test.js +0 -183
  480. package/dist/test/unit/sync-file.test.d.ts +0 -1
  481. package/dist/test/unit/sync-file.test.js +0 -154
  482. package/dist/test/unit/tool-invocation-guard.test.d.ts +0 -1
  483. package/dist/test/unit/tool-invocation-guard.test.js +0 -432
  484. package/dist/test/unit/tool-usage-stats.test.d.ts +0 -1
  485. package/dist/test/unit/tool-usage-stats.test.js +0 -300
  486. package/dist/test/unit/toolSearch.test.d.ts +0 -1
  487. package/dist/test/unit/toolSearch.test.js +0 -571
  488. package/dist/test/unit/wait-for-task.test.d.ts +0 -1
  489. package/dist/test/unit/wait-for-task.test.js +0 -144
  490. package/dist/test/unit/watcher-status.test.d.ts +0 -1
  491. package/dist/test/unit/watcher-status.test.js +0 -169
  492. package/dist/test/unit/worktree-manager.test.d.ts +0 -1
  493. package/dist/test/unit/worktree-manager.test.js +0 -176
  494. package/dist/tools/applyPatch.js +0 -41
  495. package/dist/tools/cancelTask.d.ts +0 -30
  496. package/dist/tools/cancelTask.js +0 -64
  497. package/dist/tools/finalizeDirectSession.js +0 -84
  498. package/dist/tools/goalSubgoalTask.js +0 -110
  499. package/dist/tools/killTask.d.ts +0 -15
  500. package/dist/tools/listAgents.d.ts +0 -12
  501. package/dist/tools/listAgents.js +0 -42
  502. package/dist/tools/reconcileTasks.js +0 -352
  503. package/dist/tools/retryTask.js +0 -45
  504. package/dist/tools/runVerification.js +0 -36
  505. package/dist/tools/syncFile.js +0 -65
  506. package/docs/control-center/control-center-daily-driver.md +0 -211
  507. package/docs/control-center/control-center-mvp.md +0 -205
  508. package/docs/control-center/control-center-phase2.md +0 -159
  509. package/docs/execution-plan-2026-07-09.md +0 -315
  510. package/docs/release-v0.6.0.md +0 -71
  511. package/docs/release-v0.6.1.md +0 -75
  512. package/docs/release-v0.6.4.md +0 -45
  513. package/docs/roadmap-execution-and-acceptance.md +0 -365
  514. package/src/test/unit/acceptance-engine.test.ts +0 -261
  515. package/src/test/unit/agent-router.test.ts +0 -342
  516. package/src/test/unit/android-doctor.test.ts +0 -158
  517. package/src/test/unit/apply-patch.test.ts +0 -293
  518. package/src/test/unit/audit-checks.test.ts +0 -567
  519. package/src/test/unit/chinese-path.test.ts +0 -106
  520. package/src/test/unit/command-guard.test.ts +0 -221
  521. package/src/test/unit/create-task.test.ts +0 -255
  522. package/src/test/unit/diagnose-task.test.ts +0 -544
  523. package/src/test/unit/direct-guards.test.ts +0 -467
  524. package/src/test/unit/discovery-token-store.test.ts +0 -181
  525. package/src/test/unit/evidence-pack.test.ts +0 -251
  526. package/src/test/unit/get-task-status.test.ts +0 -203
  527. package/src/test/unit/get-task-summary.test.ts +0 -173
  528. package/src/test/unit/goal-graph.test.ts +0 -347
  529. package/src/test/unit/goal-progress.test.ts +0 -538
  530. package/src/test/unit/goal-report.test.ts +0 -189
  531. package/src/test/unit/goal-status.test.ts +0 -270
  532. package/src/test/unit/goal-store.test.ts +0 -318
  533. package/src/test/unit/goal-subgoal-task.test.ts +0 -72
  534. package/src/test/unit/goal-tools-registry.test.ts +0 -245
  535. package/src/test/unit/handoff-export.test.ts +0 -295
  536. package/src/test/unit/invoke-discovered-tool.test.ts +0 -216
  537. package/src/test/unit/logging.test.ts +0 -497
  538. package/src/test/unit/path-guard.test.ts +0 -180
  539. package/src/test/unit/post-task-cleanup.test.ts +0 -53
  540. package/src/test/unit/project-policy-release-mode.test.ts +0 -156
  541. package/src/test/unit/reconcile-tasks.test.ts +0 -551
  542. package/src/test/unit/release-gate.test.ts +0 -314
  543. package/src/test/unit/run-task-loop.test.ts +0 -425
  544. package/src/test/unit/safe-status.test.ts +0 -187
  545. package/src/test/unit/safe-views.test.ts +0 -184
  546. package/src/test/unit/schema-drift-check.test.ts +0 -260
  547. package/src/test/unit/sensitive-guard.test.ts +0 -124
  548. package/src/test/unit/spec-kit-import.test.ts +0 -429
  549. package/src/test/unit/subgoal-sync.test.ts +0 -236
  550. package/src/test/unit/sync-file.test.ts +0 -231
  551. package/src/test/unit/tool-invocation-guard.test.ts +0 -542
  552. package/src/test/unit/tool-usage-stats.test.ts +0 -384
  553. package/src/test/unit/toolSearch.test.ts +0 -756
  554. package/src/test/unit/wait-for-task.test.ts +0 -176
  555. package/src/test/unit/watcher-status.test.ts +0 -190
  556. package/src/test/unit/worktree-manager.test.ts +0 -247
  557. package/src/tools/cancelTask.ts +0 -70
  558. package/src/tools/listAgents.ts +0 -54
  559. package/src/tools/retryTask.ts +0 -53
  560. package/src/tools/syncFile.ts +0 -122
  561. /package/dist/tools/{toolCatalog.d.ts → catalog/toolCatalog.d.ts} +0 -0
  562. /package/dist/tools/{toolSearch.d.ts → catalog/toolSearch.d.ts} +0 -0
  563. /package/dist/tools/{toolSearch.js → catalog/toolSearch.js} +0 -0
  564. /package/dist/tools/{toolUsageStats.d.ts → catalog/toolUsageStats.d.ts} +0 -0
  565. /package/dist/tools/{toolUsageStats.js → catalog/toolUsageStats.js} +0 -0
  566. /package/dist/tools/{createDirectSession.d.ts → direct/createDirectSession.d.ts} +0 -0
  567. /package/dist/tools/{runDirectVerificationBundle.d.ts → direct/runDirectVerificationBundle.d.ts} +0 -0
  568. /package/dist/tools/{getPlan.d.ts → goals/getPlan.d.ts} +0 -0
  569. /package/dist/tools/{savePlan.d.ts → goals/savePlan.d.ts} +0 -0
  570. /package/dist/tools/{evidencePack.d.ts → tasks/evidencePack.d.ts} +0 -0
  571. /package/dist/tools/{getTaskFile.d.ts → tasks/getTaskFile.d.ts} +0 -0
  572. /package/dist/tools/{getTaskProgress.d.ts → tasks/getTaskProgress.d.ts} +0 -0
  573. /package/dist/tools/{getTaskProgress.js → tasks/getTaskProgress.js} +0 -0
  574. /package/dist/tools/{getTaskStdoutTail.d.ts → tasks/getTaskStdoutTail.d.ts} +0 -0
  575. /package/dist/tools/{getTaskSummary.d.ts → tasks/getTaskSummary.d.ts} +0 -0
  576. /package/dist/tools/{killTask.js → tasks/killTask.js} +0 -0
  577. /package/dist/tools/{retryTask.d.ts → tasks/retryTask.d.ts} +0 -0
  578. /package/dist/tools/{runVerification.d.ts → tasks/runVerification.d.ts} +0 -0
  579. /package/dist/tools/{taskLineage.d.ts → tasks/taskLineage.d.ts} +0 -0
  580. /package/dist/tools/{waitForTask.d.ts → tasks/waitForTask.d.ts} +0 -0
  581. /package/dist/tools/{androidDoctor.d.ts → workspace/androidDoctor.d.ts} +0 -0
  582. /package/dist/tools/{discardWorktree.d.ts → workspace/discardWorktree.d.ts} +0 -0
  583. /package/dist/tools/{listWorkspace.d.ts → workspace/listWorkspace.d.ts} +0 -0
  584. /package/dist/tools/{mergeWorktree.d.ts → workspace/mergeWorktree.d.ts} +0 -0
  585. /package/dist/tools/{readWorkspaceFile.d.ts → workspace/readWorkspaceFile.d.ts} +0 -0
  586. /package/dist/tools/{recommendAgentForTask.d.ts → workspace/recommendAgentForTask.d.ts} +0 -0
  587. /package/dist/tools/{searchWorkspace.d.ts → workspace/searchWorkspace.d.ts} +0 -0
  588. /package/src/tools/{toolSearch.ts → catalog/toolSearch.ts} +0 -0
  589. /package/src/tools/{toolUsageStats.ts → catalog/toolUsageStats.ts} +0 -0
  590. /package/src/tools/{getTaskProgress.ts → tasks/getTaskProgress.ts} +0 -0
  591. /package/src/tools/{killTask.ts → tasks/killTask.ts} +0 -0
@@ -124,7 +124,7 @@ html.dark {
124
124
  .pw-toast.pw-toast-info { border-left: 3px solid var(--pw-state-info); }
125
125
  .pw-toast .pw-toast-title { font-weight: 600; margin-bottom: 2px; }
126
126
  .pw-toast .pw-toast-msg { color: var(--pw-text-secondary); word-break: break-word; }
127
- .pw-toast .pw-toast-close { margin-left: auto; cursor: pointer; color: var(--pw-text-tertiary); font-size: 14px; line-height: 1; padding: 0 2px; }
127
+ .pw-toast .pw-toast-close { margin-left: auto; cursor: pointer; color: var(--pw-text-tertiary); background: transparent; border: 0; font-size: 14px; line-height: 1; padding: 0 2px; }
128
128
  .pw-toast .pw-toast-close:hover { color: var(--pw-text-primary); }
129
129
  @keyframes pw-toast-in {
130
130
  from { opacity: 0; transform: translateX(20px); }
@@ -172,6 +172,8 @@ html.dark {
172
172
  background-color: var(--pw-accent-muted);
173
173
  }
174
174
  </style>
175
+ <script src="/desktop-bootstrap.js"></script>
176
+ <link rel="stylesheet" href="/desktop.css">
175
177
  </head>
176
178
  <body class="flex h-screen overflow-hidden">
177
179
 
@@ -189,6 +191,10 @@ html.dark {
189
191
 
190
192
  <!-- Navigation -->
191
193
  <nav class="flex-1 flex flex-col gap-1 px-3 pt-4 overflow-y-auto">
194
+ <a href="/pages/getting-started.html" data-nav-key="getting-started" class="desktop-only-nav flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors truncate" style="color: var(--pw-text-secondary); font-family: var(--pw-font-sans);">
195
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="shrink-0"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.87 12.87 0 0 1 22 2c0 2.72-.78 7.5-6.05 11a22.35 22.35 0 0 1-3.95 2z"/></svg>
196
+ <span class="truncate" data-i18n="nav.gettingStarted">开始使用</span>
197
+ </a>
192
198
 
193
199
  <a href="/pages/dashboard.html" data-nav-key="dashboard" data-dom-id="nav-dashboard" class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors truncate" style="color: var(--pw-text-secondary); font-family: var(--pw-font-sans);">
194
200
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="shrink-0">
@@ -244,6 +250,10 @@ html.dark {
244
250
  <span class="truncate" data-zh="日志" data-en="Logs">日志</span>
245
251
  </a>
246
252
 
253
+ <a href="/pages/settings.html" data-nav-key="settings" class="desktop-only-nav flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors truncate" style="color: var(--pw-text-secondary); font-family: var(--pw-font-sans);">
254
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="shrink-0"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1-2.8 2.8-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.6v.2h-4V21a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1L4.2 17l.1-.1a1.7 1.7 0 0 0 .3-1.9A1.7 1.7 0 0 0 3 14H2.8v-4H3a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9L4.2 7 7 4.2l.1.1A1.7 1.7 0 0 0 9 4.6 1.7 1.7 0 0 0 10 3V2.8h4V3a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1L19.8 7l-.1.1a1.7 1.7 0 0 0-.3 1.9A1.7 1.7 0 0 0 21 10h.2v4H21a1.7 1.7 0 0 0-1.6 1z"/></svg>
255
+ <span class="truncate" data-i18n="nav.settings">设置</span>
256
+ </a>
247
257
  </nav>
248
258
 
249
259
  <!-- Bottom Section -->
@@ -268,6 +278,12 @@ html.dark {
268
278
  Direct 会话
269
279
  </h1>
270
280
  <div class="flex items-center gap-4 shrink-0">
281
+ <select id="session-state" class="px-2 py-1.5 rounded-md text-xs font-medium" style="background-color: var(--pw-bg-surface); color: var(--pw-text-secondary); border: 1px solid var(--pw-border-subtle); font-family: var(--pw-font-sans);">
282
+ <option value="active">进行中</option>
283
+ <option value="archive">历史记录</option>
284
+ <option value="audited">仅审计完成</option>
285
+ <option value="expired">仅已过期</option>
286
+ </select>
271
287
  <span id="lastUpdated" class="text-xs whitespace-nowrap hidden" style="color: var(--pw-text-tertiary); font-family: var(--pw-font-mono);"></span>
272
288
  <button id="refreshBtn" class="flex items-center gap-2 px-4 py-1.5 rounded-lg text-xs font-semibold whitespace-nowrap transition-colors" style="background-color: var(--pw-bg-surface); color: var(--pw-text-secondary); border: 1px solid var(--pw-border-subtle); font-family: var(--pw-font-sans);">
273
289
  <svg id="refreshIcon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -286,6 +302,18 @@ html.dark {
286
302
  <!-- Page Content Area -->
287
303
  <main class="flex-1 overflow-y-auto p-6" style="background-color: var(--pw-bg-elevated);">
288
304
 
305
+ <div class="mb-4 flex flex-wrap items-end gap-3 rounded-lg px-4 py-3" style="background-color: var(--pw-bg-surface); border: 1px solid var(--pw-border);">
306
+ <label class="grid gap-1 text-xs" style="color: var(--pw-text-tertiary);"><span data-zh="项目" data-en="Project">项目</span><select id="session-repo" aria-label="Direct 会话项目" class="px-2 py-1.5 rounded-md text-xs" style="min-width:180px;background-color:var(--pw-bg-elevated);color:var(--pw-text-primary);border:1px solid var(--pw-border-subtle);"><option value="">全部项目</option></select></label>
307
+ <label class="grid gap-1 text-xs" style="color: var(--pw-text-tertiary);"><span data-zh="开始日期" data-en="From date">开始日期</span><input id="session-date-from" type="date" aria-label="Direct 会话开始日期" class="px-2 py-1.5 rounded-md text-xs" style="background-color:var(--pw-bg-elevated);color:var(--pw-text-primary);border:1px solid var(--pw-border-subtle);"></label>
308
+ <label class="grid gap-1 text-xs" style="color: var(--pw-text-tertiary);"><span data-zh="结束日期" data-en="To date">结束日期</span><input id="session-date-to" type="date" aria-label="Direct 会话结束日期" class="px-2 py-1.5 rounded-md text-xs" style="background-color:var(--pw-bg-elevated);color:var(--pw-text-primary);border:1px solid var(--pw-border-subtle);"></label>
309
+ </div>
310
+
311
+ <section id="direct-disabled" class="hidden rounded-lg p-6 mb-4" style="background-color: var(--pw-bg-surface); border: 1px solid var(--pw-border);">
312
+ <h2 class="text-base font-semibold" style="color:var(--pw-text-primary);" data-zh="Direct 是可选高级能力" data-en="Direct is an optional advanced capability">Direct 是可选高级能力</h2>
313
+ <p class="mt-2 text-sm" style="color:var(--pw-text-secondary);" data-zh="未启用不会影响 Core、Tunnel 或普通任务。需要受控的直接编辑会话时,可在设置中启用。" data-en="Leaving Direct disabled does not affect Core, Tunnel, or regular tasks. Enable it in Settings when you need controlled direct editing sessions.">未启用不会影响 Core、Tunnel 或普通任务。需要受控的直接编辑会话时,可在设置中启用。</p>
314
+ <a href="/pages/settings.html" class="inline-flex mt-4 px-3 py-2 rounded-md text-sm font-semibold" style="background-color:var(--pw-accent);color:var(--pw-text-inverse);" data-zh="前往设置" data-en="Open Settings">前往设置</a>
315
+ </section>
316
+
289
317
  <!-- ===== Error Banner ===== -->
290
318
  <div id="error-banner" class="hidden mb-5 rounded-lg px-4 py-3 flex items-start gap-3" style="background-color: var(--pw-state-error-bg); border: 1px solid var(--pw-state-error);">
291
319
  <svg class="shrink-0 mt-0.5" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--pw-state-error)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -327,6 +355,7 @@ html.dark {
327
355
 
328
356
  <!-- ===== Sessions List ===== -->
329
357
  <div id="sessions-list" class="hidden flex flex-col gap-3"></div>
358
+ <div id="sessions-more-wrap" class="hidden mt-4 text-center"><button id="sessions-more" type="button" class="px-4 py-2 rounded-md text-sm font-medium" style="background-color:var(--pw-bg-surface);color:var(--pw-text-primary);border:1px solid var(--pw-border);" data-zh="加载更多" data-en="Load more">加载更多</button></div>
330
359
 
331
360
  <!-- ===== Session Detail ===== -->
332
361
  <div id="session-detail" class="hidden flex flex-col gap-6"></div>
@@ -339,7 +368,7 @@ html.dark {
339
368
  <div class="rounded-lg w-full max-w-2xl max-h-[80vh] flex flex-col" style="background-color: var(--pw-bg-surface); border: 1px solid var(--pw-border); box-shadow: var(--pw-shadow-modal);">
340
369
  <div class="flex items-center justify-between px-4 py-3" style="border-bottom: 1px solid var(--pw-border);">
341
370
  <h3 id="safe-modal-title" class="text-sm font-semibold truncate" style="color: var(--pw-text-primary);">—</h3>
342
- <button id="safe-modal-close" class="text-lg leading-none" style="color: var(--pw-text-tertiary);" type="button">×</button>
371
+ <button id="safe-modal-close" class="text-lg leading-none" style="color: var(--pw-text-tertiary);" type="button" title="关闭" aria-label="关闭结果面板">×</button>
343
372
  </div>
344
373
  <div id="safe-modal-body" class="flex-1 overflow-auto px-4 py-3 text-xs" style="color: var(--pw-text-primary); font-family: var(--pw-font-mono); white-space: pre-wrap; word-break: break-all;"></div>
345
374
  </div>
@@ -373,6 +402,8 @@ html.dark {
373
402
 
374
403
  var API_URL = '/api/direct-sessions';
375
404
  var controlToken = null;
405
+ var loadedSessions = [];
406
+ var nextCursor = null;
376
407
 
377
408
  function $(id) { return document.getElementById(id); }
378
409
  function hide(el) { if (el) el.classList.add('hidden'); }
@@ -432,6 +463,7 @@ html.dark {
432
463
 
433
464
  function showLoading() {
434
465
  show($('loading-state'));
466
+ hide($('direct-disabled'));
435
467
  hide($('empty-state'));
436
468
  hide($('sessions-list'));
437
469
  hide($('session-detail'));
@@ -441,6 +473,8 @@ html.dark {
441
473
  show($('empty-state'));
442
474
  hide($('sessions-list'));
443
475
  hide($('session-detail'));
476
+ hide($('direct-disabled'));
477
+ hide($('sessions-more-wrap'));
444
478
  var rEl = $('empty-reason');
445
479
  if (rEl) rEl.textContent = reason || '';
446
480
  }
@@ -449,12 +483,24 @@ html.dark {
449
483
  hide($('empty-state'));
450
484
  show($('sessions-list'));
451
485
  hide($('session-detail'));
486
+ hide($('direct-disabled'));
452
487
  }
453
488
  function showDetail() {
454
489
  hide($('loading-state'));
455
490
  hide($('empty-state'));
456
491
  hide($('sessions-list'));
457
492
  show($('session-detail'));
493
+ hide($('direct-disabled'));
494
+ hide($('sessions-more-wrap'));
495
+ }
496
+
497
+ function showDirectDisabled() {
498
+ hide($('loading-state'));
499
+ hide($('empty-state'));
500
+ hide($('sessions-list'));
501
+ hide($('session-detail'));
502
+ hide($('sessions-more-wrap'));
503
+ show($('direct-disabled'));
458
504
  }
459
505
 
460
506
  function verdictColor(v) {
@@ -489,7 +535,7 @@ html.dark {
489
535
  + '<div class="pw-toast-title">' + escapeHtml(title || '') + '</div>'
490
536
  + (msg ? '<div class="pw-toast-msg">' + escapeHtml(msg) + '</div>' : '')
491
537
  + '</div>'
492
- + '<span class="pw-toast-close" title="关闭">×</span>';
538
+ + '<button type="button" class="pw-toast-close" title="关闭" aria-label="关闭通知">×</button>';
493
539
  var closeBtn = el.querySelector('.pw-toast-close');
494
540
  if (closeBtn) closeBtn.addEventListener('click', function () { dismissToast(el); });
495
541
  container.appendChild(el);
@@ -650,7 +696,7 @@ html.dark {
650
696
  var c = COLOR_VARS[meta.color] || COLOR_VARS.muted;
651
697
  return '<div class="flex items-center gap-2 mt-2 mb-1 px-1">'
652
698
  + '<span class="w-2 h-2 rounded-full" style="background-color: ' + c.fg + ';"></span>'
653
- + '<h2 class="text-sm font-semibold" style="color: var(--pw-text-primary); font-family: var(--pw-font-sans);">' + escapeHtml(meta.zh) + '</h2>'
699
+ + '<h2 class="text-sm font-semibold" data-zh="' + escapeHtml(meta.zh) + '" data-en="' + escapeHtml(meta.en) + '" style="color: var(--pw-text-primary); font-family: var(--pw-font-sans);">' + escapeHtml(meta.zh) + '</h2>'
654
700
  + '<span class="text-xs" style="color: var(--pw-text-tertiary);">(' + count + ')</span>'
655
701
  + '</div>';
656
702
  }
@@ -662,7 +708,7 @@ html.dark {
662
708
  '<summary class="flex items-center gap-2 cursor-pointer px-3 py-2" style="color: var(--pw-text-primary); font-family: var(--pw-font-sans;">'
663
709
  + '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="shrink-0"><polyline points="6 9 12 15 18 9"/></svg>'
664
710
  + '<span class="w-2 h-2 rounded-full" style="background-color: ' + c.fg + ';"></span>'
665
- + '<span class="text-sm font-semibold">' + escapeHtml(meta.zh) + '</span>'
711
+ + '<span class="text-sm font-semibold" data-zh="' + escapeHtml(meta.zh) + '" data-en="' + escapeHtml(meta.en) + '">' + escapeHtml(meta.zh) + '</span>'
666
712
  + '<span class="text-xs" style="color: var(--pw-text-tertiary);">(' + sessions.length + ')</span>'
667
713
  + '<span class="ml-auto text-xs" style="color: var(--pw-text-tertiary);">点击展开 / 折叠</span>'
668
714
  + '</summary>';
@@ -690,11 +736,11 @@ html.dark {
690
736
  var decision = s.audit_decision || null;
691
737
  var decisionBadge = decision
692
738
  ? badgeHtml(decision, verdictColor(decision))
693
- : '<span class="text-xs px-2 py-0.5 rounded-md" style="color: var(--pw-text-tertiary); background-color: var(--pw-bg-hover);">not audited</span>';
739
+ : '<span class="text-xs px-2 py-0.5 rounded-md" style="color: var(--pw-text-tertiary); background-color: var(--pw-bg-hover);">未审计</span>';
694
740
  var stateBadge = finalized
695
- ? badgeHtml('finalized', 'success')
696
- : (isExpired ? badgeHtml('expired', 'warning') : badgeHtml('open', 'warning'));
697
- var auditedBadge = audited ? badgeHtml('audited', 'success') : '';
741
+ ? badgeHtml('已完成', 'success')
742
+ : (isExpired ? badgeHtml('已过期', 'warning') : badgeHtml('进行中', 'warning'));
743
+ var auditedBadge = audited ? badgeHtml('已审计', 'success') : '';
698
744
  var titleText = s.title || s.repo_path || sid;
699
745
 
700
746
  // Verification status summary
@@ -706,21 +752,21 @@ html.dark {
706
752
  // Quick action buttons
707
753
  var actions = '';
708
754
  // safe_direct_summary
709
- actions += quickBtnHtml('summary', 'safe_direct_summary', sid, '查看安全摘要', false, false);
755
+ actions += quickBtnHtml('summary', '查看摘要', 'View summary', sid, '查看脱敏后的安全摘要', 'View the redacted safe summary', false, false);
710
756
  // run_direct_verification_bundle — informational button (links to tasks page)
711
- actions += quickBtnHtml('verify-bundle', 'verify', sid, 'run_direct_verification_bundle:通过任务页创建验证任务(该操作需在任务页发起)', false, false);
757
+ actions += quickBtnHtml('verify-bundle', '创建验证任务', 'Create verification task', sid, '前往任务页创建受控验证任务', 'Open Tasks to create a controlled verification task', false, false);
712
758
  // safe_finalize_direct_session (disabled if already finalized)
713
- actions += quickBtnHtml('finalize', 'safe_finalize_direct_session', sid, 'Finalize 会话', finalized, true);
759
+ actions += quickBtnHtml('finalize', '完成会话', 'Finalize session', sid, '完成并生成会话摘要', 'Finalize and generate the session summary', finalized, true);
714
760
  // safe_audit_direct_session (disabled if already audited)
715
- actions += quickBtnHtml('audit', 'safe_audit_direct_session', sid, '审计会话', audited, true);
761
+ actions += quickBtnHtml('audit', '运行审计', 'Run audit', sid, '运行安全审计', 'Run the security audit', audited, true);
716
762
  // copy session_id
717
- actions += quickBtnHtml('copy', 'copy session_id', sid, '复制 session_id', false, false);
763
+ actions += quickBtnHtml('copy', '复制 ID', 'Copy ID', sid, '复制会话 ID', 'Copy session ID', false, false);
718
764
  // hide (expired only)
719
765
  if (isExpired) {
720
- actions += quickBtnHtml('hide', 'hide', sid, '从列表隐藏', false, false, true);
766
+ actions += quickBtnHtml('hide', '隐藏记录', 'Hide record', sid, '仅从列表隐藏,不删除证据', 'Hide from the list without deleting evidence', false, false, true);
721
767
  }
722
768
 
723
- return '<div class="rounded-lg p-4 transition-colors session-card" data-session-id="' + escapeHtml(sid) + '" '
769
+ return '<div class="rounded-lg p-4 transition-colors session-card" role="button" tabindex="0" aria-label="查看 Direct 会话 ' + escapeHtml(shortId(sid)) + '" data-session-id="' + escapeHtml(sid) + '" '
724
770
  + 'onmouseover="this.style.backgroundColor=\'var(--pw-bg-hover)\'" '
725
771
  + 'onmouseout="this.style.backgroundColor=\'var(--pw-bg-surface)\'" '
726
772
  + 'style="background-color: var(--pw-bg-surface); border: 1px solid var(--pw-border); cursor: pointer;">'
@@ -765,13 +811,13 @@ html.dark {
765
811
  + '</div>';
766
812
  }
767
813
 
768
- function quickBtnHtml(action, label, sid, title, disabled, accent, danger) {
814
+ function quickBtnHtml(action, labelZh, labelEn, sid, titleZh, titleEn, disabled, accent, danger) {
769
815
  var cls = 'pw-quick-btn';
770
816
  if (accent) cls += ' pw-quick-accent';
771
817
  if (danger) cls += ' pw-quick-danger';
772
818
  var disAttr = disabled ? ' disabled' : '';
773
- return '<button type="button" class="' + cls + '" data-action="' + escapeHtml(action) + '" data-session-id="' + escapeHtml(sid) + '" title="' + escapeHtml(title + ' (' + label + ')') + '"' + disAttr + '>'
774
- + escapeHtml(label)
819
+ return '<button type="button" class="' + cls + '" data-action="' + escapeHtml(action) + '" data-session-id="' + escapeHtml(sid) + '" title="' + escapeHtml(titleZh) + '" aria-label="' + escapeHtml(titleZh) + '" data-zh="' + escapeHtml(labelZh) + '" data-en="' + escapeHtml(labelEn) + '"' + disAttr + '>'
820
+ + escapeHtml(labelZh)
775
821
  + '</button>';
776
822
  }
777
823
 
@@ -803,6 +849,13 @@ html.dark {
803
849
  var sid2 = ev.currentTarget.getAttribute('data-session-id');
804
850
  if (sid2) loadSessionDetail(sid2);
805
851
  });
852
+ card.addEventListener('keydown', function (ev) {
853
+ if (ev.key !== 'Enter' && ev.key !== ' ') return;
854
+ if (ev.target.closest('.pw-quick-btn') || ev.target.closest('summary')) return;
855
+ ev.preventDefault();
856
+ var sid2 = ev.currentTarget.getAttribute('data-session-id');
857
+ if (sid2) loadSessionDetail(sid2);
858
+ });
806
859
  }
807
860
  }
808
861
 
@@ -1009,11 +1062,29 @@ html.dark {
1009
1062
  }
1010
1063
 
1011
1064
  // ---------- Network ----------
1012
- function loadSessions() {
1065
+ function updateRepoOptions(data) {
1066
+ var select = $('session-repo');
1067
+ if (!select) return;
1068
+ var selected = select.value;
1069
+ var repos = data && data.filters && data.filters.options && Array.isArray(data.filters.options.repos) ? data.filters.options.repos : [];
1070
+ select.innerHTML = '<option value="">全部项目</option>' + repos.map(function (repo) { return '<option value="' + escapeHtml(repo) + '">' + escapeHtml(repo) + '</option>'; }).join('');
1071
+ select.value = repos.indexOf(selected) >= 0 ? selected : '';
1072
+ }
1073
+
1074
+ function loadSessions(cursor, append) {
1013
1075
  clearError();
1014
- showLoading();
1076
+ if (!append) showLoading();
1015
1077
  setRefreshing(true);
1016
- fetch(API_URL, { method: 'GET', headers: { 'Accept': 'application/json' }, cache: 'no-store' })
1078
+ var state = $('session-state') ? $('session-state').value : 'active';
1079
+ var params = ['state=' + encodeURIComponent(state), 'limit=50'];
1080
+ var repo = $('session-repo') ? $('session-repo').value : '';
1081
+ var dateFrom = $('session-date-from') ? $('session-date-from').value : '';
1082
+ var dateTo = $('session-date-to') ? $('session-date-to').value : '';
1083
+ if (repo) params.push('repo_path=' + encodeURIComponent(repo));
1084
+ if (dateFrom) params.push('date_from=' + encodeURIComponent(dateFrom));
1085
+ if (dateTo) params.push('date_to=' + encodeURIComponent(dateTo));
1086
+ if (cursor) params.push('cursor=' + encodeURIComponent(cursor));
1087
+ fetch(API_URL + '?' + params.join('&'), { method: 'GET', headers: { 'Accept': 'application/json' }, cache: 'no-store' })
1017
1088
  .then(function (res) {
1018
1089
  if (!res.ok) {
1019
1090
  return res.text().then(function (body) {
@@ -1024,7 +1095,23 @@ html.dark {
1024
1095
  })
1025
1096
  .then(function (data) {
1026
1097
  data = data || {};
1027
- renderSessions(data.sessions || []);
1098
+ updateRepoOptions(data);
1099
+ if (data.direct_profile_enabled === false) {
1100
+ loadedSessions = append ? loadedSessions.concat(data.sessions || []) : (data.sessions || []);
1101
+ nextCursor = data.nextCursor || data.next_cursor || null;
1102
+ if (loadedSessions.length) {
1103
+ renderSessions(loadedSessions);
1104
+ show($('direct-disabled'));
1105
+ nextCursor ? show($('sessions-more-wrap')) : hide($('sessions-more-wrap'));
1106
+ } else {
1107
+ showDirectDisabled();
1108
+ }
1109
+ } else {
1110
+ loadedSessions = append ? loadedSessions.concat(data.sessions || []) : (data.sessions || []);
1111
+ nextCursor = data.nextCursor || data.next_cursor || null;
1112
+ renderSessions(loadedSessions);
1113
+ nextCursor ? show($('sessions-more-wrap')) : hide($('sessions-more-wrap'));
1114
+ }
1028
1115
  setLastUpdated();
1029
1116
  })
1030
1117
  .catch(function (err) {
@@ -1080,9 +1167,17 @@ html.dark {
1080
1167
 
1081
1168
  // ---------- Event wiring ----------
1082
1169
  var refreshBtn = $('refreshBtn');
1083
- if (refreshBtn) refreshBtn.addEventListener('click', loadSessions);
1170
+ if (refreshBtn) refreshBtn.addEventListener('click', function () { loadSessions(null, false); });
1084
1171
  var retryBtn = $('retry-btn');
1085
- if (retryBtn) retryBtn.addEventListener('click', loadSessions);
1172
+ if (retryBtn) retryBtn.addEventListener('click', function () { loadSessions(null, false); });
1173
+ var stateSelect = $('session-state');
1174
+ if (stateSelect) stateSelect.addEventListener('change', function () { loadSessions(null, false); });
1175
+ ['session-repo', 'session-date-from', 'session-date-to'].forEach(function (id) {
1176
+ var input = $(id);
1177
+ if (input) input.addEventListener('change', function () { loadSessions(null, false); });
1178
+ });
1179
+ var moreBtn = $('sessions-more');
1180
+ if (moreBtn) moreBtn.addEventListener('click', function () { if (nextCursor) loadSessions(nextCursor, true); });
1086
1181
 
1087
1182
  var modalClose = $('safe-modal-close');
1088
1183
  if (modalClose) modalClose.addEventListener('click', closeSafeModal);
@@ -1097,8 +1192,10 @@ html.dark {
1097
1192
  });
1098
1193
 
1099
1194
  // Initial load
1100
- loadSessions();
1195
+ loadSessions(null, false);
1101
1196
  })();
1102
1197
  </script>
1198
+ <script src="/i18n.js"></script>
1199
+ <script src="/desktop-bridge.js"></script>
1103
1200
  </body>
1104
1201
  </html>
@@ -0,0 +1,43 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>PatchWarden</title>
7
+ <link rel="stylesheet" href="/colors_and_type.css">
8
+ <script src="/desktop-bootstrap.js"></script>
9
+ <link rel="stylesheet" href="/desktop.css">
10
+ <script src="/vendor/lucide.js"></script>
11
+ </head>
12
+ <body class="pw-app-shell">
13
+ <aside class="pw-sidebar">
14
+ <div class="pw-brand"><i data-lucide="shield-check"></i><strong>PatchWarden</strong></div>
15
+ <nav>
16
+ <a href="/pages/getting-started.html" data-nav-key="getting-started" data-active="true"><i data-lucide="rocket"></i><span data-i18n="nav.gettingStarted"></span></a>
17
+ <a href="/pages/dashboard.html" data-nav-key="dashboard"><i data-lucide="layout-dashboard"></i><span data-i18n="nav.dashboard"></span></a>
18
+ <a href="/pages/tasks.html" data-nav-key="tasks"><i data-lucide="list-checks"></i><span data-i18n="nav.tasks"></span></a>
19
+ <a href="/pages/workspace.html" data-nav-key="workspace"><i data-lucide="folder"></i><span data-i18n="nav.workspace"></span></a>
20
+ <a href="/pages/audit.html" data-nav-key="audit"><i data-lucide="file-search"></i><span data-i18n="nav.audit"></span></a>
21
+ <a href="/pages/direct-sessions.html" data-nav-key="direct-sessions"><i data-lucide="route"></i><span data-i18n="nav.direct"></span></a>
22
+ <a href="/pages/logs.html" data-nav-key="logs"><i data-lucide="scroll-text"></i><span data-i18n="nav.logs"></span></a>
23
+ <a href="/pages/settings.html" data-nav-key="settings" class="desktop-only-nav"><i data-lucide="settings"></i><span data-i18n="nav.settings"></span></a>
24
+ </nav>
25
+ </aside>
26
+ <div class="pw-page">
27
+ <header class="pw-page-header"><div><h1 data-i18n="home.title"></h1><p data-i18n="home.subtitle"></p></div><select id="language" aria-label="Language"><option value="system" data-i18n="language.system"></option><option value="zh-CN" data-i18n="language.zh"></option><option value="en" data-i18n="language.en"></option></select></header>
28
+ <main class="getting-started-main">
29
+ <div class="readiness-list">
30
+ <section class="readiness-item" data-check="workspace"><span class="check-index">1</span><div><div class="check-heading"><h2 data-i18n="home.workspace"></h2><span class="check-status" data-status>…</span></div><p data-message data-i18n="home.checking"></p><p class="reason-detail" data-reason></p></div><a class="primary-command" href="/pages/settings.html" data-i18n="home.openSettings"></a></section>
31
+ <section class="readiness-item" data-check="core"><span class="check-index">2</span><div><div class="check-heading"><h2 data-i18n="home.core"></h2><span class="check-status" data-status>…</span></div><p data-message data-i18n="home.checking"></p><p class="reason-detail" data-reason></p></div><button class="primary-command" id="startCore" data-i18n="home.startCore"></button></section>
32
+ <section class="readiness-item" data-check="tunnel"><span class="check-index">3</span><div><div class="check-heading"><h2 data-i18n="home.platform"></h2><span class="check-status" data-status>…</span></div><p data-message data-i18n="home.checking"></p><p class="reason-detail" data-reason></p></div><a class="primary-command" href="https://platform.openai.com/settings/organization/tunnels" target="_blank" rel="noreferrer" data-i18n="home.openPlatform"></a></section>
33
+ <section class="readiness-item" data-check="chatgpt"><span class="check-index">4</span><div><div class="check-heading"><h2 data-i18n="home.chatgpt"></h2><span class="check-status manual" data-status data-i18n="home.manual"></span></div><p data-message data-i18n="home.chatgptManual"></p><p class="reason-detail" data-reason></p></div><button class="primary-command" id="copyPrompt" data-i18n="home.copyPrompt"></button></section>
34
+ </div>
35
+ <section class="guide-band"><h2 data-i18n="home.docs"></h2><div class="guide-links"><a href="https://developers.openai.com/api/docs/guides/secure-mcp-tunnels" target="_blank" rel="noreferrer" data-i18n="home.secureGuide"></a><a href="https://chatgpt.com/#settings/Plugins" target="_blank" rel="noreferrer" data-i18n="home.pluginsGuide"></a><a href="https://github.com/jiezeng2004-design/PatchWarden/blob/main/README.md" target="_blank" rel="noreferrer" data-i18n="home.readmeZh"></a><a href="https://github.com/jiezeng2004-design/PatchWarden/blob/main/README.en.md" target="_blank" rel="noreferrer" data-i18n="home.readmeEn"></a></div></section>
36
+ <div id="toast" class="pw-toast" role="status" aria-live="polite"></div>
37
+ </main>
38
+ </div>
39
+ <script src="/i18n.js"></script>
40
+ <script src="/desktop-bridge.js"></script>
41
+ <script src="/getting-started.js"></script>
42
+ </body>
43
+ </html>