patchwarden 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (597) hide show
  1. package/PatchWarden.cmd +32 -2
  2. package/README.en.md +194 -26
  3. package/README.md +160 -22
  4. package/dist/assessments/agentAssessor.d.ts +1 -1
  5. package/dist/assessments/agentAssessor.js +24 -15
  6. package/dist/assessments/assessmentStore.d.ts +1 -1
  7. package/dist/assessments/assessmentStore.js +44 -36
  8. package/dist/assessments/confirmCli.js +5 -4
  9. package/dist/config.d.ts +22 -0
  10. package/dist/config.js +98 -11
  11. package/dist/control/fileManager.d.ts +2 -0
  12. package/dist/control/fileManager.js +39 -0
  13. package/dist/control/middleware/auth.d.ts +16 -0
  14. package/dist/control/middleware/auth.js +17 -0
  15. package/dist/control/middleware/static.d.ts +3 -0
  16. package/dist/control/middleware/static.js +78 -0
  17. package/dist/control/routeTable.d.ts +24 -0
  18. package/dist/control/routeTable.js +263 -0
  19. package/dist/control/routes/audit.d.ts +15 -0
  20. package/dist/control/routes/audit.js +287 -0
  21. package/dist/control/routes/evidence.d.ts +4 -0
  22. package/dist/control/routes/evidence.js +96 -0
  23. package/dist/control/routes/lineage.d.ts +3 -0
  24. package/dist/control/routes/lineage.js +71 -0
  25. package/dist/control/routes/policy.d.ts +3 -0
  26. package/dist/control/routes/policy.js +81 -0
  27. package/dist/control/routes/process.d.ts +12 -0
  28. package/dist/control/routes/process.js +487 -0
  29. package/dist/control/routes/sessions.d.ts +30 -0
  30. package/dist/control/routes/sessions.js +287 -0
  31. package/dist/control/routes/status.d.ts +51 -0
  32. package/dist/control/routes/status.js +307 -0
  33. package/dist/control/routes/taskActions.d.ts +21 -0
  34. package/dist/control/routes/taskActions.js +197 -0
  35. package/dist/control/routes/tasks.d.ts +24 -0
  36. package/dist/control/routes/tasks.js +309 -0
  37. package/dist/control/routes/workspace.d.ts +15 -0
  38. package/dist/control/routes/workspace.js +220 -0
  39. package/dist/control/runtime.d.ts +92 -0
  40. package/dist/control/runtime.js +425 -0
  41. package/dist/control/server.d.ts +13 -0
  42. package/dist/control/server.js +150 -0
  43. package/dist/control/shared.d.ts +59 -0
  44. package/dist/control/shared.js +341 -0
  45. package/dist/controlCenter.d.ts +6 -0
  46. package/dist/controlCenter.js +7 -2197
  47. package/dist/direct/directAudit.js +234 -225
  48. package/dist/direct/directGuards.d.ts +2 -1
  49. package/dist/direct/directGuards.js +72 -37
  50. package/dist/direct/directPatch.d.ts +6 -1
  51. package/dist/direct/directPatch.js +55 -8
  52. package/dist/direct/directSessionStore.d.ts +16 -6
  53. package/dist/direct/directSessionStore.js +127 -35
  54. package/dist/direct/directVerification.js +8 -16
  55. package/dist/doctor.d.ts +18 -1
  56. package/dist/doctor.js +614 -373
  57. package/dist/goal/acceptanceEngine.d.ts +1 -1
  58. package/dist/goal/goalProgress.js +75 -69
  59. package/dist/goal/goalReport.d.ts +54 -0
  60. package/dist/goal/goalReport.js +197 -0
  61. package/dist/goal/goalStatus.d.ts +8 -0
  62. package/dist/goal/goalStatus.js +10 -3
  63. package/dist/goal/goalStore.d.ts +9 -2
  64. package/dist/goal/goalStore.js +152 -45
  65. package/dist/goal/handoffExport.js +6 -6
  66. package/dist/goal/specKitImport.d.ts +63 -0
  67. package/dist/goal/specKitImport.js +221 -0
  68. package/dist/goal/subgoalSync.js +13 -10
  69. package/dist/goal/worktreeManager.d.ts +2 -0
  70. package/dist/goal/worktreeManager.js +209 -136
  71. package/dist/httpServer.js +126 -44
  72. package/dist/index.js +7 -4
  73. package/dist/logging.d.ts +7 -1
  74. package/dist/logging.js +13 -3
  75. package/dist/policy/projectPolicy.js +5 -2
  76. package/dist/release/releaseGate.d.ts +1 -1
  77. package/dist/release/releaseGate.js +78 -25
  78. package/dist/runner/agentInvocation.d.ts +14 -0
  79. package/dist/runner/agentInvocation.js +96 -4
  80. package/dist/runner/changeCapture.d.ts +14 -6
  81. package/dist/runner/changeCapture.js +287 -81
  82. package/dist/runner/cli.js +7 -6
  83. package/dist/runner/postTaskCleanup.js +60 -7
  84. package/dist/runner/processSecurity.d.ts +56 -0
  85. package/dist/runner/processSecurity.js +373 -0
  86. package/dist/runner/runTask.d.ts +1 -1
  87. package/dist/runner/runTask.js +339 -287
  88. package/dist/runner/simpleProcess.d.ts +3 -0
  89. package/dist/runner/simpleProcess.js +52 -38
  90. package/dist/{taskProgress.d.ts → runner/taskProgress.d.ts} +1 -1
  91. package/dist/{taskProgress.js → runner/taskProgress.js} +2 -2
  92. package/dist/{taskRuntime.d.ts → runner/taskRuntime.d.ts} +1 -1
  93. package/dist/{taskRuntime.js → runner/taskRuntime.js} +3 -2
  94. package/dist/runner/taskStatusStore.d.ts +11 -0
  95. package/dist/runner/taskStatusStore.js +24 -0
  96. package/dist/runner/watch.d.ts +14 -1
  97. package/dist/runner/watch.js +265 -54
  98. package/dist/security/contentRedaction.d.ts +6 -0
  99. package/dist/security/contentRedaction.js +24 -2
  100. package/dist/security/discoveryTokenStore.d.ts +3 -2
  101. package/dist/security/discoveryTokenStore.js +17 -2
  102. package/dist/security/loopbackHost.d.ts +2 -0
  103. package/dist/security/loopbackHost.js +16 -0
  104. package/dist/security/pathGuard.js +32 -17
  105. package/dist/security/planGuard.js +2 -1
  106. package/dist/security/runtimeGuard.js +9 -6
  107. package/dist/security/secretComparison.d.ts +3 -0
  108. package/dist/security/secretComparison.js +11 -0
  109. package/dist/security/sensitiveGuard.d.ts +5 -0
  110. package/dist/security/sensitiveGuard.js +27 -8
  111. package/dist/security/toolInvocationGuard.d.ts +2 -2
  112. package/dist/security/toolInvocationGuard.js +1 -1
  113. package/dist/security/workspaceRootGuard.d.ts +8 -0
  114. package/dist/security/workspaceRootGuard.js +47 -0
  115. package/dist/smoke-test.js +280 -273
  116. package/dist/tools/catalog/index.d.ts +4 -0
  117. package/dist/tools/catalog/index.js +4 -0
  118. package/dist/tools/{toolCatalog.js → catalog/toolCatalog.js} +3 -12
  119. package/dist/tools/{toolRegistry.d.ts → catalog/toolRegistry.d.ts} +3 -3
  120. package/dist/tools/{toolRegistry.js → catalog/toolRegistry.js} +28 -15
  121. package/dist/tools/definitions/toolDefs.d.ts +18 -0
  122. package/dist/tools/definitions/toolDefs.js +1177 -0
  123. package/dist/tools/{auditSession.d.ts → diagnostics/auditSession.d.ts} +1 -1
  124. package/dist/tools/{auditSession.js → diagnostics/auditSession.js} +2 -2
  125. package/dist/tools/{auditTask.d.ts → diagnostics/auditTask.d.ts} +8 -63
  126. package/dist/tools/{auditTask.js → diagnostics/auditTask.js} +111 -37
  127. package/dist/tools/{healthCheck.d.ts → diagnostics/healthCheck.d.ts} +6 -6
  128. package/dist/tools/{healthCheck.js → diagnostics/healthCheck.js} +10 -10
  129. package/dist/tools/diagnostics/index.d.ts +6 -0
  130. package/dist/tools/diagnostics/index.js +6 -0
  131. package/dist/tools/{safeStatus.d.ts → diagnostics/safeStatus.d.ts} +3 -3
  132. package/dist/tools/{safeStatus.js → diagnostics/safeStatus.js} +6 -6
  133. package/dist/tools/{safeViews.d.ts → diagnostics/safeViews.d.ts} +14 -10
  134. package/dist/tools/{safeViews.js → diagnostics/safeViews.js} +25 -15
  135. package/dist/tools/{schemaDriftCheck.d.ts → diagnostics/schemaDriftCheck.d.ts} +1 -1
  136. package/dist/tools/{schemaDriftCheck.js → diagnostics/schemaDriftCheck.js} +2 -2
  137. package/dist/tools/{createDirectSession.d.ts → direct/createDirectSession.d.ts} +1 -1
  138. package/dist/tools/{createDirectSession.js → direct/createDirectSession.js} +8 -8
  139. package/dist/tools/{finalizeDirectSession.d.ts → direct/finalizeDirectSession.d.ts} +2 -2
  140. package/dist/tools/direct/finalizeDirectSession.js +86 -0
  141. package/dist/tools/direct/index.d.ts +3 -0
  142. package/dist/tools/direct/index.js +3 -0
  143. package/dist/tools/{runDirectVerificationBundle.js → direct/runDirectVerificationBundle.js} +2 -2
  144. package/dist/tools/{discoverTools.d.ts → discovery/discoverTools.d.ts} +2 -2
  145. package/dist/tools/{discoverTools.js → discovery/discoverTools.js} +5 -5
  146. package/dist/tools/{explainTool.d.ts → discovery/explainTool.d.ts} +2 -2
  147. package/dist/tools/{explainTool.js → discovery/explainTool.js} +2 -2
  148. package/dist/tools/discovery/index.d.ts +3 -0
  149. package/dist/tools/discovery/index.js +3 -0
  150. package/dist/tools/{invokeDiscoveredTool.d.ts → discovery/invokeDiscoveredTool.d.ts} +2 -2
  151. package/dist/tools/{invokeDiscoveredTool.js → discovery/invokeDiscoveredTool.js} +5 -5
  152. package/dist/tools/dispatch/coreDispatch.d.ts +9 -0
  153. package/dist/tools/dispatch/coreDispatch.js +283 -0
  154. package/dist/tools/dispatch/diagnosticDispatch.d.ts +12 -0
  155. package/dist/tools/dispatch/diagnosticDispatch.js +80 -0
  156. package/dist/tools/dispatch/directDispatch.d.ts +8 -0
  157. package/dist/tools/dispatch/directDispatch.js +116 -0
  158. package/dist/tools/dispatch/goalDispatch.d.ts +8 -0
  159. package/dist/tools/dispatch/goalDispatch.js +92 -0
  160. package/dist/tools/dispatch/releaseDispatch.d.ts +8 -0
  161. package/dist/tools/dispatch/releaseDispatch.js +46 -0
  162. package/dist/tools/dispatch/types.d.ts +23 -0
  163. package/dist/tools/dispatch/types.js +15 -0
  164. package/dist/tools/dispatch/validation.d.ts +7 -0
  165. package/dist/tools/dispatch/validation.js +71 -0
  166. package/dist/tools/{getPlan.js → goals/getPlan.js} +4 -4
  167. package/dist/tools/{goalSubgoalTask.d.ts → goals/goalSubgoalTask.d.ts} +2 -2
  168. package/dist/tools/goals/goalSubgoalTask.js +118 -0
  169. package/dist/tools/goals/index.d.ts +3 -0
  170. package/dist/tools/goals/index.js +3 -0
  171. package/dist/tools/{savePlan.js → goals/savePlan.js} +28 -8
  172. package/dist/tools/registry.d.ts +10 -14
  173. package/dist/tools/registry.js +47 -1651
  174. package/dist/tools/{checkReleaseGate.d.ts → release/checkReleaseGate.d.ts} +1 -1
  175. package/dist/tools/{checkReleaseGate.js → release/checkReleaseGate.js} +3 -3
  176. package/dist/tools/release/index.d.ts +2 -0
  177. package/dist/tools/release/index.js +2 -0
  178. package/dist/tools/{releaseMode.d.ts → release/releaseMode.d.ts} +2 -2
  179. package/dist/tools/{releaseMode.js → release/releaseMode.js} +46 -26
  180. package/dist/tools/tasks/cancelTask.d.ts +11 -0
  181. package/dist/tools/tasks/cancelTask.js +85 -0
  182. package/dist/tools/{createTask.d.ts → tasks/createTask.d.ts} +12 -4
  183. package/dist/tools/{createTask.js → tasks/createTask.js} +46 -31
  184. package/dist/tools/{diagnoseTask.d.ts → tasks/diagnoseTask.d.ts} +1 -1
  185. package/dist/tools/{diagnoseTask.js → tasks/diagnoseTask.js} +8 -8
  186. package/dist/tools/{evidencePack.d.ts → tasks/evidencePack.d.ts} +6 -0
  187. package/dist/tools/tasks/evidencePack.js +387 -0
  188. package/dist/tools/{getTaskFile.js → tasks/getTaskFile.js} +4 -4
  189. package/dist/tools/{getTaskStatus.d.ts → tasks/getTaskStatus.d.ts} +6 -1
  190. package/dist/tools/{getTaskStatus.js → tasks/getTaskStatus.js} +5 -5
  191. package/dist/tools/{getTaskStdoutTail.js → tasks/getTaskStdoutTail.js} +13 -11
  192. package/dist/tools/{getTaskSummary.js → tasks/getTaskSummary.js} +33 -26
  193. package/dist/tools/tasks/index.d.ts +18 -0
  194. package/dist/tools/tasks/index.js +18 -0
  195. package/dist/tools/tasks/killTask.d.ts +1 -0
  196. package/dist/tools/{listTasks.d.ts → tasks/listTasks.d.ts} +1 -1
  197. package/dist/tools/{listTasks.js → tasks/listTasks.js} +3 -3
  198. package/dist/tools/{reconcileTasks.d.ts → tasks/reconcileTasks.d.ts} +1 -1
  199. package/dist/tools/{reconcileTasks.js → tasks/reconcileTasks.js} +64 -66
  200. package/dist/tools/{retryTask.d.ts → tasks/retryTask.d.ts} +2 -2
  201. package/dist/tools/tasks/retryTask.js +60 -0
  202. package/dist/tools/{runTaskLoop.d.ts → tasks/runTaskLoop.d.ts} +6 -6
  203. package/dist/tools/{runTaskLoop.js → tasks/runTaskLoop.js} +59 -31
  204. package/dist/tools/tasks/runVerification.js +38 -0
  205. package/dist/tools/{taskLineage.js → tasks/taskLineage.js} +8 -7
  206. package/dist/tools/{taskOutputs.js → tasks/taskOutputs.js} +17 -16
  207. package/dist/tools/{androidDoctor.js → workspace/androidDoctor.js} +16 -10
  208. package/dist/tools/{applyPatch.d.ts → workspace/applyPatch.d.ts} +1 -1
  209. package/dist/tools/workspace/applyPatch.js +53 -0
  210. package/dist/tools/{discardWorktree.js → workspace/discardWorktree.js} +3 -3
  211. package/dist/tools/workspace/index.d.ts +10 -0
  212. package/dist/tools/workspace/index.js +10 -0
  213. package/dist/tools/{listAgents.d.ts → workspace/listAgents.d.ts} +5 -0
  214. package/dist/tools/{listAgents.js → workspace/listAgents.js} +8 -4
  215. package/dist/tools/{listWorkspace.js → workspace/listWorkspace.js} +3 -3
  216. package/dist/tools/{mergeWorktree.js → workspace/mergeWorktree.js} +3 -3
  217. package/dist/tools/{readWorkspaceFile.js → workspace/readWorkspaceFile.js} +8 -8
  218. package/dist/tools/{recommendAgentForTask.js → workspace/recommendAgentForTask.js} +3 -3
  219. package/dist/tools/{searchWorkspace.js → workspace/searchWorkspace.js} +5 -5
  220. package/dist/tools/{syncFile.d.ts → workspace/syncFile.d.ts} +1 -1
  221. package/dist/tools/workspace/syncFile.js +134 -0
  222. package/dist/utils/atomicFile.d.ts +7 -0
  223. package/dist/utils/atomicFile.js +48 -0
  224. package/dist/utils/boundedFile.d.ts +8 -0
  225. package/dist/utils/boundedFile.js +93 -0
  226. package/dist/utils/lockedJsonFile.d.ts +15 -0
  227. package/dist/utils/lockedJsonFile.js +224 -0
  228. package/dist/utils/platform.d.ts +11 -0
  229. package/dist/utils/platform.js +26 -0
  230. package/dist/utils/stableJson.d.ts +2 -0
  231. package/dist/utils/stableJson.js +12 -0
  232. package/dist/version.d.ts +3 -2
  233. package/dist/version.js +3 -2
  234. package/dist/watcherStatus.d.ts +2 -2
  235. package/dist/watcherStatus.js +18 -0
  236. package/docs/CODE_WIKI.md +1648 -0
  237. package/docs/agentseal-integration.md +150 -0
  238. package/docs/architecture.md +23 -0
  239. package/docs/assets/patchwarden-desktop-onboarding.png +0 -0
  240. package/docs/assets/patchwarden-oss-demo.gif +0 -0
  241. package/docs/control-center/README.md +4 -4
  242. package/docs/dashboard-overview.md +86 -0
  243. package/docs/demo.md +8 -0
  244. package/docs/desktop-app.md +175 -0
  245. package/docs/direct-session-workflow.md +98 -0
  246. package/docs/evidence-pack-schema.md +215 -0
  247. package/docs/lineage-evidence-pack-workflow.md +127 -0
  248. package/docs/mcp-inspector-testing.md +200 -0
  249. package/docs/open-source-application.md +168 -0
  250. package/docs/opencode-worker.md +151 -0
  251. package/docs/openhands-worker.md +181 -0
  252. package/docs/release-checklist.md +1 -1
  253. package/docs/release-evidence.md +82 -0
  254. package/docs/spec-kit-integration.md +131 -0
  255. package/docs/task-safe-review-workflow.md +98 -0
  256. package/docs/threat-model.md +97 -0
  257. package/docs/user-feedback.md +40 -0
  258. package/docs/why-patchwarden.md +110 -0
  259. package/examples/config.example.json +4 -2
  260. package/package.json +28 -11
  261. package/scripts/README.md +15 -6
  262. package/scripts/build.js +11 -0
  263. package/scripts/checks/brand-check.js +3 -0
  264. package/scripts/checks/build-output-check.js +37 -0
  265. package/scripts/checks/control-center-smoke.js +447 -6
  266. package/scripts/checks/control-smoke.js +19 -8
  267. package/scripts/checks/http-mcp-smoke.js +82 -4
  268. package/scripts/checks/lifecycle-smoke.js +39 -33
  269. package/scripts/checks/mcp-manifest-check.js +1 -1
  270. package/scripts/checks/mcp-smoke.js +30 -4
  271. package/scripts/checks/package-manifest-check.js +20 -7
  272. package/scripts/checks/unit-tests.js +3 -5
  273. package/scripts/checks/watcher-supervisor-smoke.js +9 -0
  274. package/scripts/control/get-patchwarden-health.ps1 +1 -1
  275. package/scripts/control/manage-patchwarden.ps1 +69 -4
  276. package/scripts/control/provision-patchwarden-tunnel.ps1 +127 -0
  277. package/scripts/control/run-background-supervisor.ps1 +41 -0
  278. package/scripts/control/start-patchwarden-tunnel.ps1 +126 -32
  279. package/scripts/generate-demo-gif.py +320 -0
  280. package/{PatchWarden-Control-Tray.cmd → scripts/launchers/PatchWarden-Control-Tray.cmd} +3 -3
  281. package/scripts/launchers/PatchWarden-Control.cmd +6 -0
  282. package/{PatchWarden-Desktop.cmd → scripts/launchers/PatchWarden-Desktop.cmd} +2 -2
  283. package/scripts/launchers/Restart-PatchWarden-Control.cmd +6 -0
  284. package/{Stop-PatchWarden.cmd → scripts/launchers/Stop-PatchWarden.cmd} +2 -2
  285. package/scripts/lib/clean-generated-output.js +11 -0
  286. package/scripts/lib/file-discovery.js +12 -0
  287. package/scripts/release/desktop-preflight.js +211 -0
  288. package/scripts/release/pack-clean.js +59 -14
  289. package/src/assessments/agentAssessor.ts +29 -15
  290. package/src/assessments/assessmentStore.ts +55 -43
  291. package/src/assessments/confirmCli.ts +5 -4
  292. package/src/config.ts +105 -11
  293. package/src/control/fileManager.ts +40 -0
  294. package/src/control/middleware/auth.ts +35 -0
  295. package/src/control/middleware/static.ts +84 -0
  296. package/src/control/routeTable.ts +301 -0
  297. package/src/control/routes/audit.ts +329 -0
  298. package/src/control/routes/evidence.ts +107 -0
  299. package/src/control/routes/lineage.ts +92 -0
  300. package/src/control/routes/policy.ts +81 -0
  301. package/src/control/routes/process.ts +505 -0
  302. package/src/control/routes/sessions.ts +314 -0
  303. package/src/control/routes/status.ts +405 -0
  304. package/src/control/routes/taskActions.ts +214 -0
  305. package/src/control/routes/tasks.ts +331 -0
  306. package/src/control/routes/workspace.ts +234 -0
  307. package/src/control/runtime.ts +508 -0
  308. package/src/control/server.ts +165 -0
  309. package/src/control/shared.ts +360 -0
  310. package/src/controlCenter.ts +7 -2347
  311. package/src/direct/directAudit.ts +17 -9
  312. package/src/direct/directGuards.ts +100 -51
  313. package/src/direct/directPatch.ts +95 -8
  314. package/src/direct/directSessionStore.ts +211 -55
  315. package/src/direct/directVerification.ts +9 -23
  316. package/src/doctor.ts +766 -492
  317. package/src/goal/acceptanceEngine.ts +1 -1
  318. package/src/goal/goalProgress.ts +17 -13
  319. package/src/goal/goalReport.ts +263 -0
  320. package/src/goal/goalStatus.ts +25 -3
  321. package/src/goal/goalStore.ts +241 -54
  322. package/src/goal/handoffExport.ts +6 -6
  323. package/src/goal/specKitImport.ts +355 -0
  324. package/src/goal/subgoalSync.ts +15 -10
  325. package/src/goal/worktreeManager.ts +139 -22
  326. package/src/httpServer.ts +130 -44
  327. package/src/index.ts +7 -4
  328. package/src/logging.ts +20 -4
  329. package/src/policy/projectPolicy.ts +5 -2
  330. package/src/release/releaseGate.ts +74 -27
  331. package/src/runner/agentInvocation.ts +126 -4
  332. package/src/runner/changeCapture.ts +342 -80
  333. package/src/runner/cli.ts +7 -6
  334. package/src/runner/postTaskCleanup.ts +55 -7
  335. package/src/runner/processSecurity.ts +433 -0
  336. package/src/runner/runTask.ts +441 -292
  337. package/src/runner/simpleProcess.ts +68 -33
  338. package/src/{taskProgress.ts → runner/taskProgress.ts} +3 -3
  339. package/src/{taskRuntime.ts → runner/taskRuntime.ts} +4 -3
  340. package/src/runner/taskStatusStore.ts +54 -0
  341. package/src/runner/watch.ts +290 -57
  342. package/src/security/contentRedaction.ts +31 -2
  343. package/src/security/discoveryTokenStore.ts +18 -4
  344. package/src/security/loopbackHost.ts +19 -0
  345. package/src/security/pathGuard.ts +35 -16
  346. package/src/security/planGuard.ts +2 -1
  347. package/src/security/runtimeGuard.ts +9 -6
  348. package/src/security/secretComparison.ts +13 -0
  349. package/src/security/sensitiveGuard.ts +27 -8
  350. package/src/security/toolInvocationGuard.ts +2 -2
  351. package/src/security/workspaceRootGuard.ts +53 -0
  352. package/src/smoke-test.ts +276 -273
  353. package/src/tools/catalog/index.ts +4 -0
  354. package/src/tools/{toolCatalog.ts → catalog/toolCatalog.ts} +3 -12
  355. package/src/tools/{toolRegistry.ts → catalog/toolRegistry.ts} +29 -16
  356. package/src/tools/definitions/toolDefs.ts +1264 -0
  357. package/src/tools/{auditSession.ts → diagnostics/auditSession.ts} +2 -2
  358. package/src/tools/{auditTask.ts → diagnostics/auditTask.ts} +196 -89
  359. package/src/tools/{healthCheck.ts → diagnostics/healthCheck.ts} +11 -11
  360. package/src/tools/diagnostics/index.ts +6 -0
  361. package/src/tools/{safeStatus.ts → diagnostics/safeStatus.ts} +7 -7
  362. package/src/tools/{safeViews.ts → diagnostics/safeViews.ts} +29 -19
  363. package/src/tools/{schemaDriftCheck.ts → diagnostics/schemaDriftCheck.ts} +3 -3
  364. package/src/tools/{createDirectSession.ts → direct/createDirectSession.ts} +9 -9
  365. package/src/tools/{finalizeDirectSession.ts → direct/finalizeDirectSession.ts} +11 -9
  366. package/src/tools/direct/index.ts +3 -0
  367. package/src/tools/{runDirectVerificationBundle.ts → direct/runDirectVerificationBundle.ts} +2 -2
  368. package/src/tools/{discoverTools.ts → discovery/discoverTools.ts} +6 -6
  369. package/src/tools/{explainTool.ts → discovery/explainTool.ts} +3 -3
  370. package/src/tools/discovery/index.ts +3 -0
  371. package/src/tools/{invokeDiscoveredTool.ts → discovery/invokeDiscoveredTool.ts} +7 -7
  372. package/src/tools/dispatch/coreDispatch.ts +379 -0
  373. package/src/tools/dispatch/diagnosticDispatch.ts +106 -0
  374. package/src/tools/dispatch/directDispatch.ts +168 -0
  375. package/src/tools/dispatch/goalDispatch.ts +128 -0
  376. package/src/tools/dispatch/releaseDispatch.ts +66 -0
  377. package/src/tools/dispatch/types.ts +24 -0
  378. package/src/tools/dispatch/validation.ts +78 -0
  379. package/src/tools/{getPlan.ts → goals/getPlan.ts} +4 -4
  380. package/src/tools/{goalSubgoalTask.ts → goals/goalSubgoalTask.ts} +43 -28
  381. package/src/tools/goals/index.ts +3 -0
  382. package/src/tools/{savePlan.ts → goals/savePlan.ts} +38 -8
  383. package/src/tools/registry.ts +54 -1858
  384. package/src/tools/{checkReleaseGate.ts → release/checkReleaseGate.ts} +3 -3
  385. package/src/tools/release/index.ts +2 -0
  386. package/src/tools/{releaseMode.ts → release/releaseMode.ts} +42 -24
  387. package/src/tools/tasks/cancelTask.ts +109 -0
  388. package/src/tools/{createTask.ts → tasks/createTask.ts} +56 -33
  389. package/src/tools/{diagnoseTask.ts → tasks/diagnoseTask.ts} +8 -8
  390. package/src/tools/tasks/evidencePack.ts +504 -0
  391. package/src/tools/{getTaskFile.ts → tasks/getTaskFile.ts} +4 -4
  392. package/src/tools/{getTaskStatus.ts → tasks/getTaskStatus.ts} +7 -5
  393. package/src/tools/{getTaskStdoutTail.ts → tasks/getTaskStdoutTail.ts} +13 -11
  394. package/src/tools/{getTaskSummary.ts → tasks/getTaskSummary.ts} +44 -33
  395. package/src/tools/tasks/index.ts +18 -0
  396. package/src/tools/{listTasks.ts → tasks/listTasks.ts} +4 -4
  397. package/src/tools/{reconcileTasks.ts → tasks/reconcileTasks.ts} +68 -66
  398. package/src/tools/tasks/retryTask.ts +69 -0
  399. package/src/tools/{runTaskLoop.ts → tasks/runTaskLoop.ts} +70 -35
  400. package/src/tools/{runVerification.ts → tasks/runVerification.ts} +6 -3
  401. package/src/tools/{taskLineage.ts → tasks/taskLineage.ts} +8 -7
  402. package/src/tools/{taskOutputs.ts → tasks/taskOutputs.ts} +27 -20
  403. package/src/tools/{androidDoctor.ts → workspace/androidDoctor.ts} +15 -10
  404. package/src/tools/{applyPatch.ts → workspace/applyPatch.ts} +38 -16
  405. package/src/tools/{discardWorktree.ts → workspace/discardWorktree.ts} +3 -3
  406. package/src/tools/workspace/index.ts +10 -0
  407. package/src/tools/{listAgents.ts → workspace/listAgents.ts} +11 -4
  408. package/src/tools/{listWorkspace.ts → workspace/listWorkspace.ts} +3 -3
  409. package/src/tools/{mergeWorktree.ts → workspace/mergeWorktree.ts} +3 -3
  410. package/src/tools/{readWorkspaceFile.ts → workspace/readWorkspaceFile.ts} +8 -8
  411. package/src/tools/{recommendAgentForTask.ts → workspace/recommendAgentForTask.ts} +3 -3
  412. package/src/tools/{searchWorkspace.ts → workspace/searchWorkspace.ts} +5 -5
  413. package/src/tools/workspace/syncFile.ts +292 -0
  414. package/src/utils/atomicFile.ts +58 -0
  415. package/src/utils/boundedFile.ts +116 -0
  416. package/src/utils/lockedJsonFile.ts +251 -0
  417. package/src/utils/platform.ts +31 -0
  418. package/src/utils/stableJson.ts +12 -0
  419. package/src/version.ts +3 -2
  420. package/src/watcherStatus.ts +19 -1
  421. package/ui/desktop-bootstrap.js +11 -0
  422. package/ui/desktop-bridge.js +36 -0
  423. package/ui/desktop.css +160 -0
  424. package/ui/getting-started.js +93 -0
  425. package/ui/i18n.js +484 -0
  426. package/ui/log-parser.js +30 -0
  427. package/ui/pages/audit.html +204 -3
  428. package/ui/pages/dashboard.html +937 -79
  429. package/ui/pages/direct-sessions.html +609 -60
  430. package/ui/pages/getting-started.html +43 -0
  431. package/ui/pages/logs.html +105 -22
  432. package/ui/pages/settings.html +101 -0
  433. package/ui/pages/task-detail.html +468 -438
  434. package/ui/pages/tasks.html +648 -65
  435. package/ui/pages/workspace.html +38 -1
  436. package/ui/settings.js +245 -0
  437. package/PatchWarden-Control.cmd +0 -6
  438. package/Restart-PatchWarden-Control.cmd +0 -6
  439. package/dist/test/unit/acceptance-engine.test.d.ts +0 -1
  440. package/dist/test/unit/acceptance-engine.test.js +0 -228
  441. package/dist/test/unit/agent-router.test.d.ts +0 -1
  442. package/dist/test/unit/agent-router.test.js +0 -287
  443. package/dist/test/unit/android-doctor.test.d.ts +0 -1
  444. package/dist/test/unit/android-doctor.test.js +0 -118
  445. package/dist/test/unit/audit-checks.test.d.ts +0 -1
  446. package/dist/test/unit/audit-checks.test.js +0 -350
  447. package/dist/test/unit/chinese-path.test.d.ts +0 -1
  448. package/dist/test/unit/chinese-path.test.js +0 -91
  449. package/dist/test/unit/command-guard.test.d.ts +0 -1
  450. package/dist/test/unit/command-guard.test.js +0 -160
  451. package/dist/test/unit/diagnose-task.test.d.ts +0 -1
  452. package/dist/test/unit/diagnose-task.test.js +0 -457
  453. package/dist/test/unit/direct-guards.test.d.ts +0 -1
  454. package/dist/test/unit/direct-guards.test.js +0 -213
  455. package/dist/test/unit/discovery-token-store.test.d.ts +0 -1
  456. package/dist/test/unit/discovery-token-store.test.js +0 -139
  457. package/dist/test/unit/evidence-pack.test.d.ts +0 -1
  458. package/dist/test/unit/evidence-pack.test.js +0 -130
  459. package/dist/test/unit/goal-graph.test.d.ts +0 -1
  460. package/dist/test/unit/goal-graph.test.js +0 -298
  461. package/dist/test/unit/goal-progress.test.d.ts +0 -1
  462. package/dist/test/unit/goal-progress.test.js +0 -381
  463. package/dist/test/unit/goal-status.test.d.ts +0 -1
  464. package/dist/test/unit/goal-status.test.js +0 -215
  465. package/dist/test/unit/goal-store.test.d.ts +0 -1
  466. package/dist/test/unit/goal-store.test.js +0 -253
  467. package/dist/test/unit/goal-subgoal-task.test.d.ts +0 -1
  468. package/dist/test/unit/goal-subgoal-task.test.js +0 -55
  469. package/dist/test/unit/goal-tools-registry.test.d.ts +0 -1
  470. package/dist/test/unit/goal-tools-registry.test.js +0 -190
  471. package/dist/test/unit/handoff-export.test.d.ts +0 -1
  472. package/dist/test/unit/handoff-export.test.js +0 -263
  473. package/dist/test/unit/invoke-discovered-tool.test.d.ts +0 -1
  474. package/dist/test/unit/invoke-discovered-tool.test.js +0 -167
  475. package/dist/test/unit/logging.test.d.ts +0 -1
  476. package/dist/test/unit/logging.test.js +0 -397
  477. package/dist/test/unit/path-guard.test.d.ts +0 -1
  478. package/dist/test/unit/path-guard.test.js +0 -109
  479. package/dist/test/unit/post-task-cleanup.test.d.ts +0 -1
  480. package/dist/test/unit/post-task-cleanup.test.js +0 -48
  481. package/dist/test/unit/project-policy-release-mode.test.d.ts +0 -1
  482. package/dist/test/unit/project-policy-release-mode.test.js +0 -125
  483. package/dist/test/unit/reconcile-tasks.test.d.ts +0 -1
  484. package/dist/test/unit/reconcile-tasks.test.js +0 -456
  485. package/dist/test/unit/release-gate.test.d.ts +0 -1
  486. package/dist/test/unit/release-gate.test.js +0 -242
  487. package/dist/test/unit/run-task-loop.test.d.ts +0 -1
  488. package/dist/test/unit/run-task-loop.test.js +0 -380
  489. package/dist/test/unit/safe-status.test.d.ts +0 -1
  490. package/dist/test/unit/safe-status.test.js +0 -165
  491. package/dist/test/unit/safe-views.test.d.ts +0 -1
  492. package/dist/test/unit/safe-views.test.js +0 -171
  493. package/dist/test/unit/schema-drift-check.test.d.ts +0 -1
  494. package/dist/test/unit/schema-drift-check.test.js +0 -176
  495. package/dist/test/unit/sensitive-guard.test.d.ts +0 -1
  496. package/dist/test/unit/sensitive-guard.test.js +0 -104
  497. package/dist/test/unit/subgoal-sync.test.d.ts +0 -1
  498. package/dist/test/unit/subgoal-sync.test.js +0 -183
  499. package/dist/test/unit/sync-file.test.d.ts +0 -1
  500. package/dist/test/unit/sync-file.test.js +0 -154
  501. package/dist/test/unit/tool-invocation-guard.test.d.ts +0 -1
  502. package/dist/test/unit/tool-invocation-guard.test.js +0 -432
  503. package/dist/test/unit/tool-usage-stats.test.d.ts +0 -1
  504. package/dist/test/unit/tool-usage-stats.test.js +0 -300
  505. package/dist/test/unit/toolSearch.test.d.ts +0 -1
  506. package/dist/test/unit/toolSearch.test.js +0 -571
  507. package/dist/test/unit/watcher-status.test.d.ts +0 -1
  508. package/dist/test/unit/watcher-status.test.js +0 -169
  509. package/dist/test/unit/worktree-manager.test.d.ts +0 -1
  510. package/dist/test/unit/worktree-manager.test.js +0 -176
  511. package/dist/tools/applyPatch.js +0 -41
  512. package/dist/tools/cancelTask.d.ts +0 -30
  513. package/dist/tools/cancelTask.js +0 -64
  514. package/dist/tools/evidencePack.js +0 -168
  515. package/dist/tools/finalizeDirectSession.js +0 -84
  516. package/dist/tools/goalSubgoalTask.js +0 -110
  517. package/dist/tools/killTask.d.ts +0 -15
  518. package/dist/tools/retryTask.js +0 -45
  519. package/dist/tools/runVerification.js +0 -36
  520. package/dist/tools/syncFile.js +0 -65
  521. package/docs/control-center/control-center-daily-driver.md +0 -211
  522. package/docs/control-center/control-center-mvp.md +0 -205
  523. package/docs/control-center/control-center-phase2.md +0 -159
  524. package/docs/release-v0.6.0.md +0 -71
  525. package/docs/release-v0.6.1.md +0 -75
  526. package/docs/release-v0.6.4.md +0 -45
  527. package/src/test/unit/acceptance-engine.test.ts +0 -261
  528. package/src/test/unit/agent-router.test.ts +0 -342
  529. package/src/test/unit/android-doctor.test.ts +0 -158
  530. package/src/test/unit/audit-checks.test.ts +0 -567
  531. package/src/test/unit/chinese-path.test.ts +0 -106
  532. package/src/test/unit/command-guard.test.ts +0 -221
  533. package/src/test/unit/diagnose-task.test.ts +0 -544
  534. package/src/test/unit/direct-guards.test.ts +0 -297
  535. package/src/test/unit/discovery-token-store.test.ts +0 -181
  536. package/src/test/unit/evidence-pack.test.ts +0 -142
  537. package/src/test/unit/goal-graph.test.ts +0 -347
  538. package/src/test/unit/goal-progress.test.ts +0 -538
  539. package/src/test/unit/goal-status.test.ts +0 -270
  540. package/src/test/unit/goal-store.test.ts +0 -318
  541. package/src/test/unit/goal-subgoal-task.test.ts +0 -72
  542. package/src/test/unit/goal-tools-registry.test.ts +0 -243
  543. package/src/test/unit/handoff-export.test.ts +0 -295
  544. package/src/test/unit/invoke-discovered-tool.test.ts +0 -216
  545. package/src/test/unit/logging.test.ts +0 -497
  546. package/src/test/unit/path-guard.test.ts +0 -150
  547. package/src/test/unit/post-task-cleanup.test.ts +0 -53
  548. package/src/test/unit/project-policy-release-mode.test.ts +0 -156
  549. package/src/test/unit/reconcile-tasks.test.ts +0 -551
  550. package/src/test/unit/release-gate.test.ts +0 -314
  551. package/src/test/unit/run-task-loop.test.ts +0 -425
  552. package/src/test/unit/safe-status.test.ts +0 -187
  553. package/src/test/unit/safe-views.test.ts +0 -184
  554. package/src/test/unit/schema-drift-check.test.ts +0 -260
  555. package/src/test/unit/sensitive-guard.test.ts +0 -124
  556. package/src/test/unit/subgoal-sync.test.ts +0 -236
  557. package/src/test/unit/sync-file.test.ts +0 -231
  558. package/src/test/unit/tool-invocation-guard.test.ts +0 -542
  559. package/src/test/unit/tool-usage-stats.test.ts +0 -384
  560. package/src/test/unit/toolSearch.test.ts +0 -756
  561. package/src/test/unit/watcher-status.test.ts +0 -190
  562. package/src/test/unit/worktree-manager.test.ts +0 -247
  563. package/src/tools/cancelTask.ts +0 -70
  564. package/src/tools/evidencePack.ts +0 -205
  565. package/src/tools/retryTask.ts +0 -53
  566. package/src/tools/syncFile.ts +0 -122
  567. /package/dist/tools/{toolCatalog.d.ts → catalog/toolCatalog.d.ts} +0 -0
  568. /package/dist/tools/{toolSearch.d.ts → catalog/toolSearch.d.ts} +0 -0
  569. /package/dist/tools/{toolSearch.js → catalog/toolSearch.js} +0 -0
  570. /package/dist/tools/{toolUsageStats.d.ts → catalog/toolUsageStats.d.ts} +0 -0
  571. /package/dist/tools/{toolUsageStats.js → catalog/toolUsageStats.js} +0 -0
  572. /package/dist/tools/{runDirectVerificationBundle.d.ts → direct/runDirectVerificationBundle.d.ts} +0 -0
  573. /package/dist/tools/{getPlan.d.ts → goals/getPlan.d.ts} +0 -0
  574. /package/dist/tools/{savePlan.d.ts → goals/savePlan.d.ts} +0 -0
  575. /package/dist/tools/{getTaskFile.d.ts → tasks/getTaskFile.d.ts} +0 -0
  576. /package/dist/tools/{getTaskProgress.d.ts → tasks/getTaskProgress.d.ts} +0 -0
  577. /package/dist/tools/{getTaskProgress.js → tasks/getTaskProgress.js} +0 -0
  578. /package/dist/tools/{getTaskStdoutTail.d.ts → tasks/getTaskStdoutTail.d.ts} +0 -0
  579. /package/dist/tools/{getTaskSummary.d.ts → tasks/getTaskSummary.d.ts} +0 -0
  580. /package/dist/tools/{killTask.js → tasks/killTask.js} +0 -0
  581. /package/dist/tools/{runVerification.d.ts → tasks/runVerification.d.ts} +0 -0
  582. /package/dist/tools/{taskLineage.d.ts → tasks/taskLineage.d.ts} +0 -0
  583. /package/dist/tools/{taskOutputs.d.ts → tasks/taskOutputs.d.ts} +0 -0
  584. /package/dist/tools/{waitForTask.d.ts → tasks/waitForTask.d.ts} +0 -0
  585. /package/dist/tools/{waitForTask.js → tasks/waitForTask.js} +0 -0
  586. /package/dist/tools/{androidDoctor.d.ts → workspace/androidDoctor.d.ts} +0 -0
  587. /package/dist/tools/{discardWorktree.d.ts → workspace/discardWorktree.d.ts} +0 -0
  588. /package/dist/tools/{listWorkspace.d.ts → workspace/listWorkspace.d.ts} +0 -0
  589. /package/dist/tools/{mergeWorktree.d.ts → workspace/mergeWorktree.d.ts} +0 -0
  590. /package/dist/tools/{readWorkspaceFile.d.ts → workspace/readWorkspaceFile.d.ts} +0 -0
  591. /package/dist/tools/{recommendAgentForTask.d.ts → workspace/recommendAgentForTask.d.ts} +0 -0
  592. /package/dist/tools/{searchWorkspace.d.ts → workspace/searchWorkspace.d.ts} +0 -0
  593. /package/src/tools/{toolSearch.ts → catalog/toolSearch.ts} +0 -0
  594. /package/src/tools/{toolUsageStats.ts → catalog/toolUsageStats.ts} +0 -0
  595. /package/src/tools/{getTaskProgress.ts → tasks/getTaskProgress.ts} +0 -0
  596. /package/src/tools/{killTask.ts → tasks/killTask.ts} +0 -0
  597. /package/src/tools/{waitForTask.ts → tasks/waitForTask.ts} +0 -0
@@ -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>
@@ -95,13 +95,16 @@ html.dark {
95
95
  }
96
96
  </style>
97
97
  <script src="/vendor/tailwindcss-browser.js"></script>
98
- <script src="/vendor/lucide.js"></script>
98
+ <script src="/vendor/lucide.js"></script>
99
+ <script src="/log-parser.js"></script>
99
100
  <style>
100
101
  .no-scrollbar::-webkit-scrollbar { display: none; }
101
102
  .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
102
103
  .pw-spin { animation: pw-spin 1s linear infinite; }
103
104
  @keyframes pw-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
104
105
  </style>
106
+ <script src="/desktop-bootstrap.js"></script>
107
+ <link rel="stylesheet" href="/desktop.css">
105
108
  </head>
106
109
  <body class="flex h-screen overflow-hidden">
107
110
 
@@ -119,6 +122,10 @@ html.dark {
119
122
 
120
123
  <!-- Navigation -->
121
124
  <nav class="flex-1 flex flex-col gap-1 px-3 pt-4 overflow-y-auto">
125
+ <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);">
126
+ <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>
127
+ <span class="truncate" data-i18n="nav.gettingStarted">开始使用</span>
128
+ </a>
122
129
 
123
130
  <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);">
124
131
  <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">
@@ -174,6 +181,10 @@ html.dark {
174
181
  <span class="truncate" data-zh="日志" data-en="Logs">日志</span>
175
182
  </a>
176
183
 
184
+ <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);">
185
+ <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>
186
+ <span class="truncate" data-i18n="nav.settings">设置</span>
187
+ </a>
177
188
  </nav>
178
189
 
179
190
  <!-- Bottom Section -->
@@ -211,6 +222,11 @@ html.dark {
211
222
  <option value="300">tail 300</option>
212
223
  <option value="1000">tail 1000</option>
213
224
  </select>
225
+ <button id="clearView" class="px-2.5 py-1 rounded-md text-xs font-medium" type="button" title="仅清空当前显示,不删除日志文件" 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);">清空视图</button>
226
+ <select id="levelFilter" aria-label="日志级别" class="px-2 py-1 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);">
227
+ <option value="">全部级别</option><option value="error">Error</option><option value="warn">Warning</option><option value="info">Info</option>
228
+ </select>
229
+ <input id="logSearch" type="search" aria-label="搜索日志" placeholder="搜索日志" class="px-2 py-1 rounded-md text-xs outline-none" style="width: 140px; background-color: var(--pw-bg-surface); color: var(--pw-text-primary); border: 1px solid var(--pw-border-subtle);">
214
230
  <!-- Auto-refresh toggle -->
215
231
  <label class="flex items-center gap-1.5 text-xs cursor-pointer select-none" style="color: var(--pw-text-secondary); font-family: var(--pw-font-sans);">
216
232
  <input id="autoRefresh" type="checkbox" style="accent-color: var(--pw-accent);" />
@@ -260,20 +276,20 @@ html.dark {
260
276
  <span id="stdoutMeta" class="text-xs whitespace-nowrap" style="color: var(--pw-text-tertiary); font-family: var(--pw-font-mono);">—</span>
261
277
  </div>
262
278
  <div id="stdoutEmpty" class="px-4 py-8 text-center text-sm" style="color: var(--pw-text-tertiary); font-family: var(--pw-font-sans);" data-zh="暂无 stdout 日志" data-en="No stdout log">暂无 stdout 日志</div>
263
- <pre id="stdoutContent" class="hidden px-4 py-3 text-xs leading-relaxed overflow-x-auto whitespace-pre-wrap break-all" style="background-color: #0d1117; color: var(--pw-text-secondary); font-family: var(--pw-font-mono); max-height: 480px; overflow-y: auto;"></pre>
279
+ <div id="stdoutContent" class="hidden log-list"></div>
264
280
  </section>
265
281
 
266
282
  <!-- stderr -->
267
283
  <section class="rounded-lg overflow-hidden" style="background-color: var(--pw-bg-surface); border: 1px solid var(--pw-border);">
268
284
  <div class="flex items-center justify-between px-4 py-3" style="border-bottom: 1px solid var(--pw-border);">
269
285
  <div class="flex items-center gap-2">
270
- <svg 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"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
286
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--pw-text-secondary)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
271
287
  <h2 class="text-sm font-semibold" style="color: var(--pw-text-primary); font-family: var(--pw-font-sans);">stderr</h2>
272
288
  </div>
273
289
  <span id="stderrMeta" class="text-xs whitespace-nowrap" style="color: var(--pw-text-tertiary); font-family: var(--pw-font-mono);">—</span>
274
290
  </div>
275
291
  <div id="stderrEmpty" class="px-4 py-8 text-center text-sm" style="color: var(--pw-text-tertiary); font-family: var(--pw-font-sans);" data-zh="暂无 stderr 日志" data-en="No stderr log">暂无 stderr 日志</div>
276
- <pre id="stderrContent" class="hidden px-4 py-3 text-xs leading-relaxed overflow-x-auto whitespace-pre-wrap break-all" style="background-color: #0d1117; color: var(--pw-state-error); font-family: var(--pw-font-mono); max-height: 480px; overflow-y: auto;"></pre>
292
+ <div id="stderrContent" class="hidden log-list"></div>
277
293
  </section>
278
294
 
279
295
  </div>
@@ -309,6 +325,19 @@ html.dark {
309
325
  background-color: var(--pw-accent-muted);
310
326
  color: var(--pw-accent);
311
327
  }
328
+ .log-list { max-height: 480px; overflow-y: auto; background: #0d1117; }
329
+ .log-row { border-bottom: 1px solid var(--pw-border-subtle); color: var(--pw-text-secondary); font-family: var(--pw-font-mono); }
330
+ .log-row:last-child { border-bottom: 0; }
331
+ .log-row > summary { display: grid; grid-template-columns: minmax(132px,auto) 64px minmax(90px,140px) minmax(180px,1fr) auto; gap: 10px; align-items: center; padding: 9px 12px; cursor: pointer; list-style: none; }
332
+ .log-row > summary::-webkit-details-marker { display: none; }
333
+ .log-time,.log-component,.log-summary { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
334
+ .log-level { font-weight: 700; text-transform: uppercase; }
335
+ .log-row[data-level="error"] .log-level { color: var(--pw-state-error); }
336
+ .log-row[data-level="warn"] .log-level { color: var(--pw-state-warning); }
337
+ .log-row[data-level="info"] .log-level { color: var(--pw-state-info); }
338
+ .log-detail { margin: 0; padding: 10px 12px; color: var(--pw-text-tertiary); background: var(--pw-code-bg); white-space: pre-wrap; word-break: break-all; }
339
+ .copy-log-line { padding: 3px 7px; border: 1px solid var(--pw-border-subtle); border-radius: 4px; color: var(--pw-text-secondary); background: var(--pw-bg-hover); font: 11px var(--pw-font-sans); }
340
+ @media (max-width: 900px) { .log-row > summary { grid-template-columns: 92px 52px minmax(0,1fr) auto; }.log-component { display:none; } }
312
341
  </style>
313
342
 
314
343
  <script>lucide.createIcons();</script>
@@ -381,37 +410,57 @@ html.dark {
381
410
  }
382
411
  }
383
412
 
413
+ var lastLogData = null;
414
+ var visibleLogLines = {};
415
+ function parseLogEntries(value, stream) {
416
+ var query = $('logSearch') ? $('logSearch').value.trim().toLowerCase() : '';
417
+ var level = $('levelFilter') ? $('levelFilter').value : '';
418
+ return String(value || '').split(/\r?\n/).filter(Boolean).map(function (line) {
419
+ var parsed = window.PatchWardenLogParser.parseLine(line, stream);
420
+ if (level && parsed.level !== level) return null;
421
+ var searchable = [parsed.time, parsed.level, parsed.component, parsed.summary, line].join(' ').toLowerCase();
422
+ if (query && searchable.indexOf(query) < 0) return null;
423
+ return parsed;
424
+ }).filter(Boolean);
425
+ }
426
+
427
+ function renderLogRows(container, emptyState, value, stream) {
428
+ var entries = parseLogEntries(value, stream);
429
+ if (!entries.length) { hide(container); show(emptyState); return 0; }
430
+ container.innerHTML = entries.map(function (entry, index) {
431
+ var copyId = stream + '-' + index;
432
+ visibleLogLines[copyId] = entry.raw;
433
+ return '<details class="log-row" data-level="' + escapeHtml(entry.level || 'unknown') + '">'
434
+ + '<summary><span class="log-time" title="' + escapeHtml(entry.time || '无时间字段') + '">' + escapeHtml(entry.time || '—') + '</span>'
435
+ + '<span class="log-level">' + escapeHtml(entry.level || 'raw') + '</span>'
436
+ + '<span class="log-component" title="' + escapeHtml(entry.component) + '">' + escapeHtml(entry.component) + '</span>'
437
+ + '<span class="log-summary" title="' + escapeHtml(entry.summary) + '">' + escapeHtml(entry.summary) + '</span>'
438
+ + '<button type="button" class="copy-log-line" data-copy-id="' + copyId + '" title="复制脱敏日志行" aria-label="复制脱敏日志行" data-zh="复制" data-en="Copy">复制</button></summary>'
439
+ + '<pre class="log-detail">' + escapeHtml(entry.detail) + '</pre></details>';
440
+ }).join('');
441
+ show(container); hide(emptyState);
442
+ return entries.length;
443
+ }
444
+
384
445
  function renderLogs(data) {
446
+ lastLogData = data || {};
385
447
  var stdout = (data && data.stdout) || '';
386
448
  var stderr = (data && data.stderr) || '';
449
+ visibleLogLines = {};
387
450
  var reason = (data && data.reason) || null;
388
451
  var tail = (data && data.tail) || currentTail;
389
452
 
390
453
  // stdout
391
454
  var stdoutEl = $('stdoutContent');
392
455
  var stdoutEmpty = $('stdoutEmpty');
393
- if (stdout) {
394
- text(stdoutEl, stdout);
395
- show(stdoutEl);
396
- hide(stdoutEmpty);
397
- } else {
398
- hide(stdoutEl);
399
- show(stdoutEmpty);
400
- }
401
- text($('stdoutMeta'), 'tail=' + tail + (reason ? ' · ' + reason : ''));
456
+ var stdoutCount = renderLogRows(stdoutEl, stdoutEmpty, stdout, 'stdout');
457
+ text($('stdoutMeta'), (data && data.historical_snapshot ? '历史日志 · ' : '') + stdoutCount + ' 行 · tail=' + tail + (reason ? ' · ' + reason : ''));
402
458
 
403
459
  // stderr
404
460
  var stderrEl = $('stderrContent');
405
461
  var stderrEmpty = $('stderrEmpty');
406
- if (stderr) {
407
- text(stderrEl, stderr);
408
- show(stderrEl);
409
- hide(stderrEmpty);
410
- } else {
411
- hide(stderrEl);
412
- show(stderrEmpty);
413
- }
414
- text($('stderrMeta'), 'tail=' + tail + (reason ? ' · ' + reason : ''));
462
+ var stderrCount = renderLogRows(stderrEl, stderrEmpty, stderr, 'stderr');
463
+ text($('stderrMeta'), (data && data.historical_snapshot ? '历史日志 · ' : '') + stderrCount + ' 行 · tail=' + tail + (reason ? ' · ' + reason : ''));
415
464
  }
416
465
 
417
466
  function loadLogs() {
@@ -443,6 +492,15 @@ html.dark {
443
492
  });
444
493
  }
445
494
 
495
+ function clearLogView() {
496
+ clearError();
497
+ text($('stdoutMeta'), '已清空当前视图');
498
+ text($('stderrMeta'), '日志文件未删除');
499
+ $('stdoutContent').innerHTML = ''; $('stderrContent').innerHTML = '';
500
+ show($('stdoutEmpty')); show($('stderrEmpty'));
501
+ hide($('stdoutContent')); hide($('stderrContent'));
502
+ }
503
+
446
504
  // ---------- Auto-refresh ----------
447
505
  function startAutoRefresh() {
448
506
  stopAutoRefresh();
@@ -492,11 +550,36 @@ html.dark {
492
550
 
493
551
  var refreshBtn = $('refreshBtn');
494
552
  if (refreshBtn) refreshBtn.addEventListener('click', loadLogs);
553
+ var clearView = $('clearView');
554
+ if (clearView) clearView.addEventListener('click', clearLogView);
555
+ var levelFilter = $('levelFilter');
556
+ if (levelFilter) levelFilter.addEventListener('change', function () { if (lastLogData) renderLogs(lastLogData); });
557
+ var logSearch = $('logSearch');
558
+ if (logSearch) logSearch.addEventListener('input', function () { if (lastLogData) renderLogs(lastLogData); });
559
+ ['stdoutContent', 'stderrContent'].forEach(function (id) {
560
+ var container = $(id);
561
+ if (!container) return;
562
+ container.addEventListener('click', function (event) {
563
+ var button = event.target.closest && event.target.closest('.copy-log-line');
564
+ if (!button) return;
565
+ event.preventDefault();
566
+ event.stopPropagation();
567
+ var line = visibleLogLines[button.getAttribute('data-copy-id')] || '';
568
+ if (navigator.clipboard && navigator.clipboard.writeText) {
569
+ navigator.clipboard.writeText(line).then(function () {
570
+ button.textContent = '已复制';
571
+ setTimeout(function () { button.textContent = '复制'; }, 1200);
572
+ });
573
+ }
574
+ });
575
+ });
495
576
 
496
577
  // ---------- Initial load ----------
497
578
  setCategory(DEFAULT_CATEGORY);
498
579
  loadLogs();
499
580
  })();
500
581
  </script>
582
+ <script src="/i18n.js"></script>
583
+ <script src="/desktop-bridge.js"></script>
501
584
  </body>
502
585
  </html>
@@ -0,0 +1,101 @@
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 data-i18n="settings.pageTitle"></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/tailwindcss-browser.js"></script>
11
+ <script src="/vendor/lucide.js"></script>
12
+ </head>
13
+ <body class="flex h-screen overflow-hidden">
14
+ <aside class="flex flex-col w-60 shrink-0 h-screen" style="background:var(--pw-bg);border-right:1px solid var(--pw-border)">
15
+ <div class="flex items-center gap-3 px-5 py-5" style="border-bottom:1px solid var(--pw-border-subtle)">
16
+ <i data-lucide="shield-check" style="color:var(--pw-accent)"></i><span class="text-lg font-semibold">PatchWarden</span>
17
+ </div>
18
+ <nav class="flex-1 flex flex-col gap-1 px-3 pt-4 overflow-y-auto">
19
+ <a href="/pages/getting-started.html" data-nav-key="getting-started" class="flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="rocket" class="w-4 h-4"></i><span data-i18n="nav.gettingStarted"></span></a>
20
+ <a href="/pages/dashboard.html" data-nav-key="dashboard" class="flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="layout-dashboard" class="w-4 h-4"></i><span data-i18n="nav.dashboard"></span></a>
21
+ <a href="/pages/tasks.html" data-nav-key="tasks" class="flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="list-checks" class="w-4 h-4"></i><span data-i18n="nav.tasks"></span></a>
22
+ <a href="/pages/workspace.html" data-nav-key="workspace" class="flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="folder" class="w-4 h-4"></i><span data-i18n="nav.workspace"></span></a>
23
+ <a href="/pages/audit.html" data-nav-key="audit" class="flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="file-search" class="w-4 h-4"></i><span data-i18n="nav.audit"></span></a>
24
+ <a href="/pages/direct-sessions.html" data-nav-key="direct-sessions" class="flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="route" class="w-4 h-4"></i><span data-i18n="nav.direct"></span></a>
25
+ <a href="/pages/logs.html" data-nav-key="logs" class="flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="scroll-text" class="w-4 h-4"></i><span data-i18n="nav.logs"></span></a>
26
+ <a href="/pages/settings.html" data-nav-key="settings" data-active="true" class="desktop-only-nav flex items-center gap-3 px-3 py-2.5 text-sm"><i data-lucide="settings" class="w-4 h-4"></i><span data-i18n="nav.settings"></span></a>
27
+ </nav>
28
+ </aside>
29
+ <div class="flex flex-col flex-1 min-w-0 h-screen overflow-hidden">
30
+ <header class="flex items-center px-6 py-3" style="border-bottom:1px solid var(--pw-border);background:var(--pw-bg)"><h1 class="text-lg font-semibold" data-i18n="settings.title"></h1></header>
31
+ <main class="flex-1 overflow-y-auto p-6" style="background:var(--pw-bg-elevated)">
32
+ <div class="settings-layout">
33
+ <section>
34
+ <h2 data-i18n="settings.appearance"></h2>
35
+ <div class="setting-row"><div><strong data-i18n="settings.theme"></strong><p data-i18n="settings.themeHelp"></p></div><select id="theme"><option value="system" data-i18n="settings.themeSystem"></option><option value="light" data-i18n="settings.themeLight"></option><option value="dark" data-i18n="settings.themeDark"></option></select></div>
36
+ <div class="setting-row"><div><strong data-i18n="language.label"></strong><p data-i18n="settings.languageHelp"></p></div><select id="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></div>
37
+ <div class="setting-row"><div><strong data-i18n="settings.closeWindow"></strong><p data-i18n="settings.closeWindowHelp"></p></div><select id="closeBehavior"><option value="tray" data-i18n="settings.closeToTray"></option><option value="quit" data-i18n="settings.closeQuit"></option></select></div>
38
+ </section>
39
+ <section>
40
+ <h2 data-i18n="settings.localAgents"></h2>
41
+ <div class="agent-section-toolbar"><p data-i18n="settings.localAgentsHelp"></p><button id="detectAgents"><i data-lucide="scan-search"></i><span data-i18n="settings.detectAgents"></span></button></div>
42
+ <div id="agentSettingsList" class="agent-settings-list"><p class="agent-empty" data-i18n="settings.loadingAgents"></p></div>
43
+ <div class="setting-actions"><button id="saveAgents" class="primary-action"><i data-lucide="save"></i><span data-i18n="settings.saveAgents"></span></button><span id="agentSettingsStatus" class="status-text" aria-live="polite"></span></div>
44
+ </section>
45
+ <section>
46
+ <h2 data-i18n="settings.mcpTunnel"></h2>
47
+ <div class="setting-row">
48
+ <div class="min-w-0"><strong>tunnel-client.exe</strong><p id="tunnelClientPath" class="mono break-path" data-i18n="settings.tunnelUndetected"></p></div>
49
+ <div class="inline-actions"><button id="detectTunnel"><i data-lucide="scan-search"></i><span data-i18n="settings.detect"></span></button><button id="chooseTunnel"><i data-lucide="file-search"></i><span data-i18n="settings.choose"></span></button></div>
50
+ </div>
51
+ <div class="setting-row">
52
+ <div><strong>Direct profile</strong><p data-i18n="settings.directHelp"></p></div>
53
+ <label class="switch-label"><input id="enableDirectProfile" type="checkbox"><span data-i18n="settings.enable"></span></label>
54
+ </div>
55
+ <div class="setting-row">
56
+ <div><strong data-i18n="settings.proxy"></strong><p data-i18n="settings.proxyHelp"></p></div>
57
+ <select id="proxyScope"><option value="shared" data-i18n="settings.proxyShared"></option><option value="separate" data-i18n="settings.proxySeparate"></option></select>
58
+ </div>
59
+ <div class="proxy-grid">
60
+ <div class="proxy-endpoint">
61
+ <strong>Core</strong>
62
+ <select id="coreProxyMode"><option value="environment" data-i18n="settings.proxyEnvironment"></option><option value="none" data-i18n="settings.proxyNone"></option><option value="manual" data-i18n="settings.proxyManual"></option></select>
63
+ <input id="coreProxyUrl" type="url" placeholder="http://127.0.0.1:7890" autocomplete="off">
64
+ </div>
65
+ <div id="directProxyEndpoint" class="proxy-endpoint hidden">
66
+ <strong>Direct</strong>
67
+ <select id="directProxyMode"><option value="environment" data-i18n="settings.proxyEnvironment"></option><option value="none" data-i18n="settings.proxyNone"></option><option value="manual" data-i18n="settings.proxyManual"></option></select>
68
+ <input id="directProxyUrl" type="url" placeholder="socks5://127.0.0.1:1080" autocomplete="off">
69
+ </div>
70
+ </div>
71
+ <div class="setting-actions"><button id="saveRuntime" class="primary-action"><i data-lucide="save"></i><span data-i18n="settings.saveRuntime"></span></button><span id="runtimeStatus" class="status-text" aria-live="polite"></span></div>
72
+ <div class="credential-panel">
73
+ <div class="credential-heading"><div><strong data-i18n="settings.tunnelCredentials"></strong><p data-i18n="settings.runtimeKeyHelp"></p></div><span id="credentialState" class="credential-state"></span></div>
74
+ <div class="credential-grid">
75
+ <label>Profile<select id="tunnelMode"><option value="core">Core</option><option value="direct">Direct</option></select></label>
76
+ <label><span data-i18n="settings.tunnelId"></span><input id="tunnelId" type="text" autocomplete="off" spellcheck="false" placeholder="tun_..."></label>
77
+ <label><span data-i18n="settings.runtimeKey"></span><input id="runtimeKey" type="password" autocomplete="new-password" spellcheck="false"></label>
78
+ </div>
79
+ <div class="setting-actions credential-actions"><button id="provisionTunnel" class="primary-action"><i data-lucide="shield-check"></i><span data-i18n="settings.configureCore"></span></button><button id="revalidateCredential"><i data-lucide="activity"></i><span data-i18n="settings.revalidate"></span></button><button id="forgetCredential"><i data-lucide="key-round"></i><span data-i18n="settings.forgetCredential"></span></button><span id="provisionStatus" class="status-text" aria-live="polite"></span></div>
80
+ </div>
81
+ <details class="install-guide"><summary data-i18n="settings.installSummary"></summary><ol><li data-i18n="settings.installStep1"></li><li data-i18n="settings.installStep2"></li><li data-i18n="settings.installStep3"></li><li data-i18n="settings.installStep4"></li></ol></details>
82
+ </section>
83
+ <section>
84
+ <h2 data-i18n="settings.workspaceDiagnostics"></h2>
85
+ <div class="setting-row"><div class="min-w-0"><strong data-i18n="settings.currentConfig"></strong><p id="configPath" class="mono truncate" data-i18n="settings.loading"></p></div><button id="openConfig" data-i18n-title="settings.openConfig"><i data-lucide="external-link"></i></button></div>
86
+ <div class="setting-row"><div><strong data-i18n="settings.workspace"></strong><p id="workspacePath" class="mono" data-i18n="settings.workspaceHelp"></p></div><button id="changeWorkspace" data-i18n="settings.change"></button></div>
87
+ <div class="setting-actions"><button id="openLogs"><i data-lucide="folder-open"></i><span data-i18n="settings.openLogs"></span></button><button id="runDoctor"><i data-lucide="stethoscope"></i><span data-i18n="settings.runDoctor"></span></button></div>
88
+ <pre id="doctorOutput" class="hidden"></pre>
89
+ </section>
90
+ </div>
91
+ </main>
92
+ </div>
93
+ <style>
94
+ [data-nav-key]{color:var(--pw-text-secondary);border-radius:6px}[data-nav-key]:hover{background:var(--pw-bg-hover);color:var(--pw-text-primary)}[data-nav-key][data-active="true"]{background:var(--pw-accent-subtle);color:var(--pw-accent);border-left:2px solid var(--pw-accent)}
95
+ .settings-layout{display:grid;gap:18px;max-width:920px}.settings-layout section{background:var(--pw-bg-surface);border:1px solid var(--pw-border);border-radius:7px}.settings-layout h2{margin:0;padding:16px 18px;font-size:14px;border-bottom:1px solid var(--pw-border)}.setting-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:20px;align-items:center;padding:16px 18px;border-bottom:1px solid var(--pw-border-subtle)}.setting-row p,.credential-panel p,.agent-section-toolbar p{margin:4px 0 0;color:var(--pw-text-secondary);font-size:12px}.setting-row select,.setting-row button,.setting-actions button,.proxy-endpoint select,.proxy-endpoint input,.credential-grid select,.credential-grid input,.agent-section-toolbar button,.agent-controls select,.agent-controls input,.agent-controls button{min-height:36px;padding:0 12px;color:var(--pw-text-primary);background:var(--pw-bg-elevated);border:1px solid var(--pw-border);border-radius:6px}.setting-row button,.agent-section-toolbar button,.agent-controls button{display:flex;align-items:center;gap:6px}.setting-row svg,.agent-section-toolbar svg,.agent-controls svg{width:16px}.setting-actions{display:flex;align-items:center;gap:10px;padding:16px 18px;flex-wrap:wrap}.setting-actions button{display:flex;align-items:center;gap:8px}.setting-actions svg{width:16px}.inline-actions{display:flex;gap:8px}.switch-label{display:flex;align-items:center;gap:8px}.switch-label input{width:18px;height:18px;accent-color:var(--pw-accent)}.agent-section-toolbar{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 18px;border-bottom:1px solid var(--pw-border-subtle)}.agent-settings-list{display:grid}.agent-setting-row{display:grid;grid-template-columns:minmax(180px,1fr) minmax(280px,1.4fr);align-items:center;gap:18px;padding:14px 18px;border-bottom:1px solid var(--pw-border-subtle)}.agent-identity{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:center}.agent-identity input{width:18px;height:18px;accent-color:var(--pw-accent)}.agent-identity strong,.agent-identity small{display:block}.agent-identity small{margin-top:3px;color:var(--pw-text-secondary);font-size:11px}.agent-controls{display:grid;grid-template-columns:minmax(150px,1fr) minmax(150px,1fr) 38px;gap:8px}.agent-controls button{justify-content:center;padding:0}.agent-empty{padding:18px;color:var(--pw-text-secondary);font-size:12px}.proxy-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;padding:16px 18px;border-bottom:1px solid var(--pw-border-subtle)}.proxy-endpoint{display:grid;grid-template-columns:auto minmax(150px,auto) minmax(180px,1fr);align-items:center;gap:10px}.proxy-endpoint input:disabled{opacity:.55}.primary-action{background:var(--pw-accent)!important;color:var(--pw-text-inverse)!important}.status-text{font-size:12px;color:var(--pw-text-secondary)}.credential-panel{border-top:1px solid var(--pw-border)}.credential-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:16px 18px}.credential-state{padding:3px 7px;background:var(--pw-bg-hover);border-radius:4px;font-size:11px;white-space:nowrap}.credential-grid{display:grid;grid-template-columns:150px minmax(180px,1fr) minmax(220px,1.4fr);gap:12px;padding:0 18px 16px}.credential-grid label{display:grid;gap:6px;color:var(--pw-text-secondary);font-size:11px}.credential-actions{padding-top:0}.install-guide{margin:0 18px 18px;padding:12px 14px;border:1px solid var(--pw-border-subtle);border-radius:6px;color:var(--pw-text-secondary);font-size:12px}.install-guide summary{cursor:pointer;color:var(--pw-text-primary);font-weight:600}.install-guide ol{margin:10px 0 0 20px;line-height:1.7}.break-path{overflow-wrap:anywhere}.mono{font-family:var(--pw-font-mono)}#doctorOutput{max-height:320px;margin:0 18px 18px;padding:14px;overflow:auto;color:var(--pw-code-text,#dbe8e3);background:var(--pw-code-bg);border-radius:6px;font:11px/1.5 var(--pw-font-mono);white-space:pre-wrap}.hidden{display:none}@media(max-width:760px){.setting-row,.agent-setting-row{grid-template-columns:1fr}.agent-controls{grid-template-columns:1fr}.proxy-grid,.credential-grid{grid-template-columns:1fr}.proxy-endpoint{grid-template-columns:1fr}.inline-actions{justify-content:flex-start}}
96
+ </style>
97
+ <script src="/i18n.js"></script>
98
+ <script src="/desktop-bridge.js"></script>
99
+ <script src="/settings.js"></script>
100
+ </body>
101
+ </html>