collabmd 0.1.47 → 0.1.49

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 (305) hide show
  1. package/README.md +70 -11
  2. package/bin/collabmd.js +3 -0
  3. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-C-nmgL5g.js +1 -0
  4. package/dist/client/assets/JetBrainsMono-Regular-BQaDgvhP.woff2 +0 -0
  5. package/dist/client/assets/abnfDiagram-VCTEODGH-CdVZqicp.js +1 -0
  6. package/dist/client/assets/{architectureDiagram-5GKGNRK7-I39sYjHI.js → architectureDiagram-5GKGNRK7-wUo0bXif.js} +3 -3
  7. package/dist/client/assets/babel-CY5KOv-I.js +16 -0
  8. package/dist/client/assets/{blockDiagram-NRAW4CY4-C6DtJy5Y.js → blockDiagram-I7D4REHJ-BRSK3m49.js} +4 -4
  9. package/dist/client/assets/browser-utils-DbXSMI-6.js +1 -0
  10. package/dist/client/assets/{c4Diagram-UCG6FXSJ-CtWtxS9_.js → c4Diagram-7LVT6UL2-yD2poxqw.js} +1 -1
  11. package/dist/client/assets/channel-Fa4GS_-F.js +1 -0
  12. package/dist/client/assets/chunk-2E4U76K2-BPnTT-J3.js +2 -0
  13. package/dist/client/assets/{chunk-TEH6E4GO-DVayPj-q.js → chunk-4HAMMTFA-DStbIfJ1.js} +20 -20
  14. package/dist/client/assets/{chunk-75Z2AOVW-CdFSaPjz.js → chunk-75Z2AOVW-C5pGd3W9.js} +1 -1
  15. package/dist/client/assets/{chunk-CLGD4ZFX-DQLgbQrv.js → chunk-CLGD4ZFX-BMeArk03.js} +1 -1
  16. package/dist/client/assets/chunk-DU6HZSFF-Zkp69c6c.js +127 -0
  17. package/dist/client/assets/{chunk-F27PBJKO-CNHIFhjo.js → chunk-F27PBJKO-D4xNct1r.js} +1 -1
  18. package/dist/client/assets/{chunk-GMAD6QVW-CbcBqPM5.js → chunk-GMAD6QVW-NZ6WpDb8.js} +1 -1
  19. package/dist/client/assets/{chunk-OBVCFTLP-BJR7u1jh.js → chunk-GVQU2GXP-D8SDprfX.js} +1 -1
  20. package/dist/client/assets/{chunk-G27WJ6UU-D9-eg537.js → chunk-IMKFNOWR-D8jEuU3Q.js} +2 -2
  21. package/dist/client/assets/{chunk-JQ64N6SF-DSFNH4bh.js → chunk-L3NEJ4N5-aijKP-eh.js} +1 -1
  22. package/dist/client/assets/chunk-OSK3NFVY-CCbLQAMa.js +10 -0
  23. package/dist/client/assets/{chunk-P2QGCYS3-BRpqY32H.js → chunk-P2QGCYS3-Oag_FdCq.js} +1 -1
  24. package/dist/client/assets/{chunk-POPQ4Y6H-Cb4SlVZF.js → chunk-POPQ4Y6H-CYnpIgXT.js} +1 -1
  25. package/dist/client/assets/{chunk-PWAF6VOD-Cz8IwBB5.js → chunk-PWAF6VOD-JSNrcBmP.js} +1 -1
  26. package/dist/client/assets/{chunk-RM4UPSZO-CWRwxNWJ.js → chunk-RM4UPSZO-DOWllDY8.js} +4 -4
  27. package/dist/client/assets/{chunk-RHFEMEQ7-CWY8cf4H.js → chunk-SHT3W25Y-BiQGljao.js} +5 -5
  28. package/dist/client/assets/{chunk-SVP7TREG-CyHOmcac.js → chunk-SVP7TREG-DB485R5x.js} +1 -1
  29. package/dist/client/assets/{chunk-LCL6LL3I-DmDkVukh.js → chunk-TICWLB2K-8rAVvoS3.js} +4 -4
  30. package/dist/client/assets/{chunk-CKBBP62Z-DG26UiBv.js → chunk-TLUHSLCS-DTY5v0aj.js} +2 -2
  31. package/dist/client/assets/classDiagram-ZZMXUADV-BsQWoR3Q.js +1 -0
  32. package/dist/client/assets/classDiagram-v2-VYDZK3BY-BsQWoR3Q.js +1 -0
  33. package/dist/client/assets/{comment-thread-store-CdcwrObc.js → comment-thread-store-CX98zR6q.js} +1 -1
  34. package/dist/client/assets/comment-threads-BnRwo5B9.js +4 -0
  35. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CdTPi2yO.js → cynefinDiagram-5FMLGOSQ-rTz9RhFH.js} +1 -1
  36. package/dist/client/assets/{dagre-3AP2YEHR-5gtJtd0O.js → dagre-GXQ25YYZ-Cr67wLpQ.js} +2 -2
  37. package/dist/client/assets/{diagram-S7CK7UJ4-BudWz9WU.js → diagram-S7CK7UJ4-DywERe__.js} +2 -2
  38. package/dist/client/assets/{diagram-UQ7AKVKN-3v4rbH-s.js → diagram-UQ7AKVKN-CNYlXtu4.js} +1 -1
  39. package/dist/client/assets/diagram-VSXAHHWV-0H1a61Bn.js +3 -0
  40. package/dist/client/assets/{diagram-VX7I27RA-C_-rj0sw.js → diagram-VX7I27RA-CsJbsx5F.js} +1 -1
  41. package/dist/client/assets/{diagram-Z3DM3KII-B4yxavgj.js → diagram-Z3DM3KII-D0mLxEgI.js} +1 -1
  42. package/dist/client/assets/dist--hk9I5HQ.js +1 -0
  43. package/dist/client/assets/{dist-DutPuFmC.js → dist-B1XEa-Zs.js} +1 -1
  44. package/dist/client/assets/dist-Bd1JucQF.js +1 -0
  45. package/dist/client/assets/{dist-DZAAWTG-.js → dist-C0G3AaXG.js} +1 -1
  46. package/dist/client/assets/dist-ChRoo3IB.js +9 -0
  47. package/dist/client/assets/dist-Dm4w5UId.js +1 -0
  48. package/dist/client/assets/{dist-B_yQaEv_.js → dist-DpYDHR9p.js} +1 -1
  49. package/dist/client/assets/{dist-CietwTVS.js → dist-DzNmC81X.js} +1 -1
  50. package/dist/client/assets/{dist-DDUn5zTz.js → dist-GvvCNBe4.js} +1 -1
  51. package/dist/client/assets/dist-JaU3aRlD.js +19 -0
  52. package/dist/client/assets/{dist-Bw3VIE_v.js → dist-TW8iFRyW.js} +1 -1
  53. package/dist/client/assets/{dist-Dir5dDKZ.js → dist-jVU5Be5P.js} +1 -1
  54. package/dist/client/assets/document-formatter-rDDjRfZ2.js +2 -0
  55. package/dist/client/assets/drawioEditor-JubEEha7.js +9 -0
  56. package/dist/client/assets/ebnfDiagram-PWID7BFC-HeTxHpCU.js +1 -0
  57. package/dist/client/assets/editor-session-Bk6oIvSr.js +54 -0
  58. package/dist/client/assets/embedded-editor-base-BlCgz6mw.css +1 -0
  59. package/dist/client/assets/{erDiagram-SSCWMZ5O-C-iy6VkX.js → erDiagram-RLTQ6QDP-CbrDdd5P.js} +2 -2
  60. package/dist/client/assets/{es-CAsWR6hG.js → es-Bfdp096f.js} +13 -13
  61. package/dist/client/assets/estree-CuT_pB8K.js +44 -0
  62. package/dist/client/assets/excalidraw-element-link-YLIaTnVF.js +7 -0
  63. package/dist/client/assets/{excalidraw-scene-BOben2gr.js → excalidraw-scene-6uROebca.js} +1 -1
  64. package/dist/client/assets/{excalidraw-editor-BlcN6umJ.css → excalidrawEditor-BbSbI80a.css} +1 -1
  65. package/dist/client/assets/excalidrawEditor-dBMbRX_S.js +9 -0
  66. package/dist/client/assets/export-page-CRRQ2NEl.js +57 -0
  67. package/dist/client/assets/exportDocument-BlQRd9_m.js +2 -0
  68. package/dist/client/assets/exportDocument-CNSbjZwu.css +1 -0
  69. package/dist/client/assets/{file-icon-svg-CQAjlWjK.js → file-icon-svg-Y_kpF957.js} +1 -1
  70. package/dist/client/assets/file-kind-BwMIcZbi.js +1 -0
  71. package/dist/client/assets/file-search-DDLyyLDU.js +1 -0
  72. package/dist/client/assets/flowDiagram-HODETNUW-D5Gy0wmg.js +1 -0
  73. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DtKHAbez.js → ganttDiagram-EL5Y4UJY-BHgOYiZz.js} +1 -1
  74. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-oue8fQ5o.js → gitGraphDiagram-WWUBYQGX-Dl__X3Sk.js} +1 -1
  75. package/dist/client/assets/html-Cdnr2qzU.js +25 -0
  76. package/dist/client/assets/image-ZVKINSPA-DgzW5zAy.js +1 -0
  77. package/dist/client/assets/index-D3RER1SZ.js +1023 -0
  78. package/dist/client/assets/index-DREVKl_K.css +1 -0
  79. package/dist/client/assets/{infoDiagram-RXCK75RN-BMzo6KIn.js → infoDiagram-27XIBGKW-DBpoANC9.js} +1 -1
  80. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BIM3h287.js → ishikawaDiagram-5VMMS53U-BMPC6hfp.js} +1 -1
  81. package/dist/client/assets/{journeyDiagram-EYS64GPL-mF6Lh8O-.js → journeyDiagram-3NMN7TZE-B1sApUmM.js} +2 -2
  82. package/dist/client/assets/{kanban-definition-3QL26DDD-DLN2NyoR.js → kanban-definition-UXKFOSKX-C9yP4td1.js} +4 -4
  83. package/dist/client/assets/{line-BfTWJmgf.js → line-BFl3ujec.js} +1 -1
  84. package/dist/client/assets/markdown-CByV-4CU.js +70 -0
  85. package/dist/client/assets/{mermaid.core-CLZBlpIW.js → mermaid.core-BrY09czX.js} +5 -5
  86. package/dist/client/assets/mermaid.core-DfcNfOTv.js +1 -0
  87. package/dist/client/assets/{mindmap-definition-FBJOCRG2-CRyHaHTk.js → mindmap-definition-YA3MSWOX-BUQHcYbK.js} +8 -8
  88. package/dist/client/assets/pegDiagram-XKGWAZYB-Bi2Iml7Z.js +1 -0
  89. package/dist/client/assets/{pieDiagram-E7YTZNPT-B5OZPb88.js → pieDiagram-E7YTZNPT-_gYXnMoi.js} +1 -1
  90. package/dist/client/assets/preview-render-compiler-CfxJYldJ.js +41 -0
  91. package/dist/client/assets/preview-render-compiler-Cu8_i9iS.js +1 -0
  92. package/dist/client/assets/{preview-render-worker-BmN79bVc.js → preview-render-worker-c4Yi93qW.js} +41 -35
  93. package/dist/client/assets/prod-BiJL30sl.js +1 -0
  94. package/dist/client/assets/prod-qAk7rHa4.js +177 -0
  95. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Drrw14YH.js → quadrantDiagram-AXDQQJYC-DwexhEhd.js} +1 -1
  96. package/dist/client/assets/quick-switcher-controller-BoIK_wuG.js +1 -0
  97. package/dist/client/assets/railroadDiagram-O6MQD6OU-BVA5UbMu.js +1 -0
  98. package/dist/client/assets/{requirementDiagram-EFPCY7ZU-CRZG6mRB.js → requirementDiagram-BXWQKSXE-C4cKwiIw.js} +2 -2
  99. package/dist/client/assets/runtime-config-DcmnGcXU.js +1 -0
  100. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-DvarEJpo.js → sankeyDiagram-P5KCCOFB-B5HHkRT2.js} +1 -1
  101. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-B4oWlb-w.js → sequenceDiagram-WJ2MYXX4-BX6jqJFD.js} +6 -6
  102. package/dist/client/assets/standalone-6z5x8CWe.js +29 -0
  103. package/dist/client/assets/{stateDiagram-HBIQ2CUA-qbHIIqRZ.js → stateDiagram-D77RDMKH-CmqxyRGx.js} +1 -1
  104. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-zoLLQVyh.js +1 -0
  105. package/dist/client/assets/{swimlanes-XN3QIQJK-xB6CtUGj.js → swimlanes-42K2YHIH-Bmgb9Zld.js} +1 -1
  106. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DS-KQN37.js +8 -0
  107. package/dist/client/assets/{timeline-definition-24CTP7MA-Lj_yTNlY.js → timeline-definition-24CTP7MA-BA-lVH6P.js} +1 -1
  108. package/dist/client/assets/vault-api-client-iZLhMJKe.js +6 -0
  109. package/dist/client/assets/{vennDiagram-4TSXK5OY-BekRp5Y0.js → vennDiagram-4TSXK5OY-DNdUC_Xj.js} +1 -1
  110. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-kdnV_Hdm.js → wardleyDiagram-VM6X3IG4-C2oY-YbF.js} +1 -1
  111. package/dist/client/assets/wiki-link-resolver-DFIwErjc.js +1 -0
  112. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DufGwNSB.js → xychartDiagram-S5SC5T6Z-CoIR8CBX.js} +1 -1
  113. package/dist/client/assets/yaml-9ltHPDNO.js +154 -0
  114. package/dist/client/assets/{yjs-provider-reset-guard-DE0vINDP.js → yjs-provider-reset-guard-9ul1qF6k.js} +1 -1
  115. package/dist/client/drawio-editor.html +11 -3
  116. package/dist/client/excalidraw-editor.html +45 -2
  117. package/dist/client/export-document.html +3 -3
  118. package/dist/client/index.html +106 -52
  119. package/integrations/pi/index.ts +94 -0
  120. package/package.json +41 -29
  121. package/src/client/app/drawio-editor.html +2 -2
  122. package/src/client/app/excalidraw-editor.html +2 -2
  123. package/src/client/app/export-document.html +1 -1
  124. package/src/client/app/index.html +88 -50
  125. package/src/client/app/main-entry.js +15 -1
  126. package/src/client/application/app-shell/chat-feature.js +7 -22
  127. package/src/client/application/app-shell/export-feature.js +17 -1
  128. package/src/client/application/app-shell/git-feature.js +51 -14
  129. package/src/client/application/app-shell/presence-feature.js +8 -25
  130. package/src/client/application/app-shell/ui-feature-identity.js +13 -0
  131. package/src/client/application/app-shell/ui-feature-shell.js +199 -99
  132. package/src/client/application/app-shell/ui-feature-sidebar.js +43 -7
  133. package/src/client/application/app-shell/ui-feature-tab-activity.js +19 -6
  134. package/src/client/application/app-shell/ui-feature-toolbar.js +16 -129
  135. package/src/client/application/app-shell-elements.js +8 -0
  136. package/src/client/application/preview-render-compiler.js +1 -87
  137. package/src/client/application/preview-render-scheduler.js +8 -24
  138. package/src/client/application/preview-renderer.js +2 -2
  139. package/src/client/application/webmcp-diagram-renderer.js +47 -0
  140. package/src/client/application/workspace-coordinator.js +23 -4
  141. package/src/client/application/workspace-preview-controller.js +120 -2
  142. package/src/client/application/workspace-route-controller.js +11 -1
  143. package/src/client/assets/vendor/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
  144. package/src/client/assets/vendor/jetbrains-mono/OFL.txt +93 -0
  145. package/src/client/bootstrap/collabmd-app-shell.js +99 -6
  146. package/src/client/domain/document-formatter.js +193 -0
  147. package/src/client/domain/excalidraw-element-link.js +73 -0
  148. package/src/client/domain/excalidraw-scene.js +21 -0
  149. package/src/client/domain/file-search.js +73 -0
  150. package/src/client/domain/git-labels.js +5 -0
  151. package/src/client/domain/hash-routes.js +8 -0
  152. package/src/client/domain/room.js +1 -5
  153. package/src/client/domain/runtime-paths.js +5 -0
  154. package/src/client/domain/vault-paths.js +6 -4
  155. package/src/client/domain/wiki-link-completions.js +20 -20
  156. package/src/client/drawio-editor.js +8 -3
  157. package/src/client/excalidraw-editor.js +287 -16
  158. package/src/client/export/export-host.js +59 -36
  159. package/src/client/export/export-page.js +14 -4
  160. package/src/client/export/export-pipeline.js +270 -42
  161. package/src/client/infrastructure/agent-connection-api-client.js +23 -0
  162. package/src/client/infrastructure/auth-client.js +3 -13
  163. package/src/client/infrastructure/editor-session.js +15 -0
  164. package/src/client/infrastructure/editor-view-adapter.js +73 -14
  165. package/src/client/infrastructure/excalidraw-room-client.js +80 -1
  166. package/src/client/infrastructure/git-api-client.js +39 -33
  167. package/src/client/infrastructure/lobby-presence.js +2 -5
  168. package/src/client/infrastructure/runtime-config.js +11 -1
  169. package/src/client/infrastructure/tab-activity-lock.js +2 -5
  170. package/src/client/infrastructure/vault-api-client.js +33 -26
  171. package/src/client/infrastructure/webmcp-tool-registry.js +283 -0
  172. package/src/client/infrastructure/workspace-sync-client.js +6 -4
  173. package/src/client/presentation/agent-connection-controller.js +255 -0
  174. package/src/client/presentation/backlinks-panel.js +3 -0
  175. package/src/client/presentation/bases-preview-controller.js +59 -26
  176. package/src/client/presentation/comment-ui/comment-ui-card.js +4 -2
  177. package/src/client/presentation/create-menu-presenter.js +19 -16
  178. package/src/client/presentation/excalidraw-embed-controller.js +164 -4
  179. package/src/client/presentation/file-action-controller.js +15 -2
  180. package/src/client/presentation/file-explorer-controller.js +3 -0
  181. package/src/client/presentation/file-explorer-view.js +71 -12
  182. package/src/client/presentation/file-history-view-controller.js +19 -12
  183. package/src/client/presentation/file-tree-state.js +1 -11
  184. package/src/client/presentation/git-diff-view-controller.js +70 -53
  185. package/src/client/presentation/git-panel-controller.js +86 -32
  186. package/src/client/presentation/image-lightbox-controller.js +20 -16
  187. package/src/client/presentation/layout-controller.js +3 -1
  188. package/src/client/presentation/quick-switcher-controller.js +74 -232
  189. package/src/client/presentation/quick-switcher-text-search.js +10 -14
  190. package/src/client/styles/components/navigation.css +1 -2
  191. package/src/client/styles/components/scrollbars.css +10 -0
  192. package/src/client/styles/export-document.css +44 -29
  193. package/src/client/styles/features/agent-connection.css +202 -0
  194. package/src/client/styles/features/collaboration-chat.css +8 -1
  195. package/src/client/styles/features/collaboration-dialogs.css +16 -1
  196. package/src/client/styles/features/collaboration-presence.css +30 -5
  197. package/src/client/styles/features/diff-toolbar.css +1 -1
  198. package/src/client/styles/features/media-lightbox.css +12 -3
  199. package/src/client/styles/features/preview-markdown.css +54 -0
  200. package/src/client/styles/features/quick-switcher.css +20 -11
  201. package/src/client/styles/foundation/themes.css +2 -0
  202. package/src/client/styles/foundation/tokens.css +8 -0
  203. package/src/client/styles/layout/editor-page.css +25 -11
  204. package/src/client/styles/layout/responsive.css +2 -20
  205. package/src/client/styles/layout/shell.css +77 -24
  206. package/src/client/styles/layout/sidebar.css +7 -4
  207. package/src/client/styles/layout/view-modes.css +2 -0
  208. package/src/client/styles/overrides/codemirror.css +31 -19
  209. package/src/client/styles/primitives/controls.css +21 -54
  210. package/src/client/styles/style.css +1 -0
  211. package/src/client/styles/surfaces/excalidraw-editor.css +42 -0
  212. package/src/domain/agent-tool-definitions.js +796 -0
  213. package/src/domain/collabmd-content-capabilities.js +149 -0
  214. package/src/domain/collaboration-protocol.js +2 -0
  215. package/src/domain/comment-threads.js +3 -5
  216. package/src/domain/diagram-source.js +50 -0
  217. package/src/domain/editable-content-revision.js +10 -0
  218. package/src/domain/editable-text.js +3 -0
  219. package/src/domain/exact-text-edits.js +69 -0
  220. package/src/domain/excalidraw-agent-scene.js +522 -0
  221. package/src/domain/excalidraw-agent-verification.js +460 -0
  222. package/src/domain/excalidraw-room-codec.js +1 -5
  223. package/src/domain/file-kind.js +12 -1
  224. package/src/domain/video-embed.js +76 -0
  225. package/src/server/application/agent-connection-service.js +178 -0
  226. package/src/server/application/agent-content-service.js +773 -0
  227. package/src/server/application/workspace-reconciliation.js +5 -7
  228. package/src/server/config/env.js +51 -1
  229. package/src/server/create-app-server.js +36 -0
  230. package/src/server/domain/bases/base-query-service.js +1 -5
  231. package/src/server/domain/collaboration/collaboration-room.js +121 -25
  232. package/src/server/domain/collaboration/protocol.js +4 -0
  233. package/src/server/domain/hosted-workspace.js +21 -0
  234. package/src/server/domain/markdown-reference-extractor.js +15 -1
  235. package/src/server/domain/ripgrep-search-service.js +110 -37
  236. package/src/server/infrastructure/git/git-service.js +19 -1
  237. package/src/server/infrastructure/git/history-service.js +1 -1
  238. package/src/server/infrastructure/git/local-exclude.js +25 -0
  239. package/src/server/infrastructure/git/parsers.js +19 -17
  240. package/src/server/infrastructure/git/path-utils.js +0 -16
  241. package/src/server/infrastructure/git/status-service.js +1 -1
  242. package/src/server/infrastructure/git/untracked-files.js +12 -21
  243. package/src/server/infrastructure/http/create-agent-api-handler.js +171 -0
  244. package/src/server/infrastructure/http/create-git-api-command-handler.js +32 -0
  245. package/src/server/infrastructure/http/create-request-handler.js +28 -0
  246. package/src/server/infrastructure/http/create-static-handler.js +6 -0
  247. package/src/server/infrastructure/mcp/create-agent-mcp-handler.js +199 -0
  248. package/src/server/infrastructure/persistence/agent-connection-store.js +120 -0
  249. package/src/server/infrastructure/persistence/path-utils.js +10 -4
  250. package/src/server/infrastructure/persistence/pull-backup-store.js +2 -27
  251. package/src/server/infrastructure/persistence/vault-file-store.js +11 -2
  252. package/src/server/shared/agent-tool-image.js +22 -0
  253. package/src/server/shared/agent-tool-rate-limiter.js +20 -0
  254. package/src/server/startup/git-remote-bootstrap.js +5 -33
  255. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js +0 -1
  256. package/dist/client/assets/abnfDiagram-VCTEODGH-BNDLzJ7L.js +0 -1
  257. package/dist/client/assets/browser-utils--H_DkyEF.js +0 -1
  258. package/dist/client/assets/channel-CaoKA_We.js +0 -1
  259. package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +0 -2
  260. package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +0 -127
  261. package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +0 -10
  262. package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +0 -1
  263. package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +0 -1
  264. package/dist/client/assets/comment-threads-9J6Em-_y.js +0 -4
  265. package/dist/client/assets/comment-ui-shared-DWkk9Vh3.js +0 -7
  266. package/dist/client/assets/diagram-VSXAHHWV-CQRVEZR7.js +0 -3
  267. package/dist/client/assets/dist-73RPdcyU.js +0 -1
  268. package/dist/client/assets/dist-CH-sQu3r.js +0 -1
  269. package/dist/client/assets/drawio-editor-BjrxTe3l.js +0 -9
  270. package/dist/client/assets/drawioEditor-DUVZjSSr.js +0 -2
  271. package/dist/client/assets/ebnfDiagram-PWID7BFC-OXa8VEp1.js +0 -1
  272. package/dist/client/assets/editor-session-DfZuRgB_.js +0 -54
  273. package/dist/client/assets/embedded-editor-base-DvMynhKu.css +0 -1
  274. package/dist/client/assets/excalidraw-editor-D7pnUCLH.js +0 -9
  275. package/dist/client/assets/excalidraw-mermaid-stub-BNckbX2n.js +0 -1
  276. package/dist/client/assets/excalidraw-mermaid-stub-DE5FTiZB.js +0 -1
  277. package/dist/client/assets/excalidrawEditor-B0jOK3lv.js +0 -2
  278. package/dist/client/assets/export-page-Bs3xE1fg.js +0 -57
  279. package/dist/client/assets/exportDocument-Dg9MjkIk.js +0 -2
  280. package/dist/client/assets/exportDocument-PnYU3v1s.css +0 -1
  281. package/dist/client/assets/file-kind-BbqgGzpc.js +0 -1
  282. package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +0 -1
  283. package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +0 -1
  284. package/dist/client/assets/index-BIpgxyGZ.css +0 -1
  285. package/dist/client/assets/index-Z5sI0Bj-.js +0 -2
  286. package/dist/client/assets/main-Dwnj9Gaq.js +0 -903
  287. package/dist/client/assets/pegDiagram-XKGWAZYB-B31fKPR2.js +0 -1
  288. package/dist/client/assets/preview-render-compiler-BApvlLLo.js +0 -35
  289. package/dist/client/assets/preview-render-compiler-BQ_3h9vD.js +0 -1
  290. package/dist/client/assets/preview-render-profile-CE-5rVTC.js +0 -1
  291. package/dist/client/assets/prod-BiYPMR1i.js +0 -177
  292. package/dist/client/assets/prod-VxdGZ5Ly.js +0 -1
  293. package/dist/client/assets/quick-switcher-controller-ButWPmCI.js +0 -12
  294. package/dist/client/assets/railroadDiagram-O6MQD6OU-BPifP0MB.js +0 -1
  295. package/dist/client/assets/runtime-config-BLrEKVO1.js +0 -1
  296. package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +0 -1
  297. package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +0 -8
  298. package/dist/client/assets/vault-api-client-_LpV1aIn.js +0 -6
  299. package/dist/client/assets/vault-utils-wdQ0RNR9.js +0 -1
  300. package/src/client/app/drawio-editor-entry.js +0 -1
  301. package/src/client/app/excalidraw-editor-entry.js +0 -1
  302. package/src/client/excalidraw-mermaid-stub.js +0 -7
  303. package/src/client/main.js +0 -16
  304. /package/dist/client/assets/{drawio-editor-UQQ8XHou.css → drawioEditor-UQQ8XHou.css} +0 -0
  305. /package/dist/client/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
@@ -1,4 +1,6 @@
1
+ import { createExcalidrawExportOptions } from '../domain/excalidraw-scene.js';
1
2
  import { escapeHtml } from '../domain/vault-utils.js';
3
+ import { commitButtonLabel } from '../domain/git-labels.js';
2
4
  import { getVaultPathLeaf, getVaultPathParent } from '../domain/vault-paths.js';
3
5
  import { resolveApiUrl } from '../domain/runtime-paths.js';
4
6
  import { renderDrawioViewer } from './drawio-viewer.js';
@@ -199,29 +201,25 @@ function getDrawioSourcePair(detail = {}) {
199
201
  };
200
202
  }
201
203
 
202
- function decodeXmlAttribute(value) {
203
- return String(value ?? '')
204
- .replace(/"/gu, '"')
205
- .replace(/'/gu, "'")
206
- .replace(/&/gu, '&')
207
- .replace(/&lt;/gu, '<')
208
- .replace(/&gt;/gu, '>');
209
- }
210
-
211
204
  function getDrawioCellMap(source) {
212
205
  const cells = new Map();
213
- const cellPattern = /<mxCell\b([^>]*?)(?:\/|>([\s\S]*?)<\/mxCell\s*)>/giu;
214
- let match;
206
+ if (typeof DOMParser === 'undefined' || typeof XMLSerializer === 'undefined') {
207
+ return cells;
208
+ }
209
+
210
+ const documentNode = new DOMParser().parseFromString(String(source ?? ''), 'application/xml');
211
+ if (documentNode.querySelector('parsererror')) {
212
+ return cells;
213
+ }
215
214
 
216
- while ((match = cellPattern.exec(String(source ?? ''))) !== null) {
217
- const idMatch = match[1].match(/\bid\s*=\s*(['"])(.*?)\1/iu);
218
- const id = decodeXmlAttribute(idMatch?.[2] || '');
215
+ const serializer = new XMLSerializer();
216
+ for (const cell of documentNode.getElementsByTagName('mxCell')) {
217
+ const id = cell.getAttribute('id');
219
218
  if (!id || id === '0' || id === '1') {
220
219
  continue;
221
220
  }
222
221
 
223
- const signature = `${match[1]}${match[2] || ''}`.replace(/\s+/gu, ' ').trim();
224
- cells.set(id, signature);
222
+ cells.set(id, serializer.serializeToString(cell).replace(/\s+/gu, ' ').trim());
225
223
  }
226
224
 
227
225
  return cells;
@@ -456,6 +454,7 @@ export class GitDiffViewController {
456
454
  this.data = null;
457
455
  this.currentIndex = 0;
458
456
  this.activeFilePath = null;
457
+ this.workspaceFilePath = null;
459
458
  this.fileCache = new Map();
460
459
  this.fileErrors = new Map();
461
460
  this.loadingFiles = new Set();
@@ -507,12 +506,12 @@ export class GitDiffViewController {
507
506
  return;
508
507
  }
509
508
 
510
- const currentFile = this.getCurrentFile();
511
- if (!currentFile?.path) {
509
+ const filePath = this.getCurrentFile()?.path ?? this.workspaceFilePath;
510
+ if (!filePath) {
512
511
  return;
513
512
  }
514
513
 
515
- this.onOpenFile?.(currentFile.path);
514
+ this.onOpenFile?.(filePath);
516
515
  });
517
516
  this.primaryActionButton?.addEventListener('click', () => {
518
517
  if (!this.isActive) {
@@ -611,6 +610,7 @@ export class GitDiffViewController {
611
610
  this.layoutMode = 'focused';
612
611
  this.currentIndex = 0;
613
612
  this.activeFilePath = null;
613
+ this.workspaceFilePath = null;
614
614
  this.fileCache.clear();
615
615
  this.fileErrors.clear();
616
616
  this.loadingFiles.clear();
@@ -624,7 +624,6 @@ export class GitDiffViewController {
624
624
  this.commitMeta = null;
625
625
  this.historyFilePath = null;
626
626
  this.pendingAction = null;
627
- this.repoStatus = null;
628
627
  }
629
628
 
630
629
  async openWorkspaceDiff({ filePath = null, scope = 'all' } = {}) {
@@ -636,6 +635,7 @@ export class GitDiffViewController {
636
635
  this.commitMeta = null;
637
636
  this.historyFilePath = null;
638
637
  this.activeFilePath = filePath;
638
+ this.workspaceFilePath = filePath;
639
639
  this.fileCache.clear();
640
640
  this.fileErrors.clear();
641
641
  this.loadingFiles.clear();
@@ -644,7 +644,7 @@ export class GitDiffViewController {
644
644
  this.excalidrawPreviewPayloads.clear();
645
645
  this.drawioPreviewPayloads.clear();
646
646
  this.requestScope = scope;
647
- this.renderLoading('Loading diff summary...');
647
+ this.renderLoading('Loading diff summary');
648
648
 
649
649
  try {
650
650
  const data = await this.gitApiClient.readDiff({
@@ -674,7 +674,7 @@ export class GitDiffViewController {
674
674
  source: 'workspace',
675
675
  summary: { additions: 0, deletions: 0, filesChanged: 0 },
676
676
  };
677
- this.renderEmpty('Failed to load git diff');
677
+ this.renderEmpty('Failed to load git diff', { alert: true });
678
678
  return this.data;
679
679
  }
680
680
  }
@@ -688,6 +688,7 @@ export class GitDiffViewController {
688
688
  this.commitMeta = null;
689
689
  this.historyFilePath = String(historyFilePath ?? '').trim() || null;
690
690
  this.activeFilePath = path || null;
691
+ this.workspaceFilePath = null;
691
692
  this.fileCache.clear();
692
693
  this.fileErrors.clear();
693
694
  this.loadingFiles.clear();
@@ -696,7 +697,7 @@ export class GitDiffViewController {
696
697
  this.excalidrawPreviewPayloads.clear();
697
698
  this.drawioPreviewPayloads.clear();
698
699
  this.requestScope = 'all';
699
- this.renderLoading('Loading commit summary...');
700
+ this.renderLoading('Loading commit summary');
700
701
 
701
702
  try {
702
703
  const data = await this.gitApiClient.readCommit({
@@ -737,7 +738,7 @@ export class GitDiffViewController {
737
738
  summary: { additions: 0, deletions: 0, filesChanged: 0 },
738
739
  };
739
740
  this.commitMeta = null;
740
- this.renderEmpty('Failed to load git commit');
741
+ this.renderEmpty('Failed to load git commit', { alert: true });
741
742
  return this.data;
742
743
  }
743
744
  }
@@ -786,25 +787,27 @@ export class GitDiffViewController {
786
787
  void this.loadCurrentFile();
787
788
  }
788
789
 
789
- renderLoading(message = 'Loading git diff...') {
790
+ renderLoading(message = 'Loading git diff') {
790
791
  if (!this.isActive) {
791
792
  return;
792
793
  }
793
794
  this.page?.classList.remove('hidden');
794
795
  if (this.content) {
795
- this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
796
+ // pi-lens-ignore: ast-grep:no-inner-html-js
797
+ this.content.innerHTML = `<div class="diff-empty-state" role="status" aria-live="polite">${escapeHtml(message)}</div>`;
796
798
  }
797
799
  this.data = null;
798
800
  this.syncToolbar();
799
801
  }
800
802
 
801
- renderEmpty(message) {
803
+ renderEmpty(message, { alert = false } = {}) {
802
804
  if (!this.isActive) {
803
805
  return;
804
806
  }
805
807
  this.page?.classList.remove('hidden');
806
808
  if (this.content) {
807
- this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
809
+ // pi-lens-ignore: ast-grep:no-inner-html-js
810
+ this.content.innerHTML = `<div class="diff-empty-state"${alert ? ' role="alert"' : ''}>${escapeHtml(message)}</div>`;
808
811
  }
809
812
  this.syncToolbar();
810
813
  }
@@ -1188,16 +1191,7 @@ export class GitDiffViewController {
1188
1191
  }
1189
1192
 
1190
1193
  try {
1191
- const svg = await exportToSvg({
1192
- appState: {
1193
- exportBackground: true,
1194
- exportWithDarkMode: false,
1195
- viewBackgroundColor: scene.appState?.viewBackgroundColor || '#ffffff',
1196
- },
1197
- elements: getVisibleSceneElements(scene),
1198
- exportPadding: 24,
1199
- files: scene.files || null,
1200
- });
1194
+ const svg = await exportToSvg(createExcalidrawExportOptions(scene));
1201
1195
  preview.replaceChildren(svg);
1202
1196
  preview.classList.add('is-ready');
1203
1197
  } catch (error) {
@@ -1240,10 +1234,14 @@ export class GitDiffViewController {
1240
1234
  const headerStats = fileKind === 'image'
1241
1235
  ? `<span class="diff-file-header-kind">${escapeHtml(getImageFormat(file.path))} image</span>`
1242
1236
  : `<span class="diff-file-header-stats"><span class="ui-stat-token ui-stat-token--add diff-stats-add">+${file.stats?.additions ?? 0}</span><span class="ui-stat-token ui-stat-token--del diff-stats-del">-${file.stats?.deletions ?? 0}</span></span>`;
1237
+ const inclusionStatus = file.hasStagedChanges
1238
+ ? '<span class="ui-pill-badge ui-pill-badge--muted" aria-label="Included in next commit">✓ Included</span>'
1239
+ : '';
1243
1240
  return `
1244
1241
  <div class="diff-file-header">
1245
1242
  <span class="diff-file-path">${escapeHtml(file.path)}</span>
1246
1243
  <span class="ui-status-badge ${badgeClass(file.status)}">${escapeHtml(file.status)}</span>
1244
+ ${inclusionStatus}
1247
1245
  ${headerStats}
1248
1246
  </div>
1249
1247
  `;
@@ -1335,7 +1333,7 @@ export class GitDiffViewController {
1335
1333
  return `
1336
1334
  <section class="diff-file-block">
1337
1335
  ${this.renderFileHeader(currentFile)}
1338
- <div class="diff-empty-state">Loading file diff...</div>
1336
+ <div class="diff-empty-state" role="status" aria-live="polite">Loading file diff…</div>
1339
1337
  </section>
1340
1338
  `;
1341
1339
  }
@@ -1345,7 +1343,7 @@ export class GitDiffViewController {
1345
1343
  return `
1346
1344
  <section class="diff-file-block">
1347
1345
  ${this.renderFileHeader(currentFile)}
1348
- <div class="diff-empty-state">${escapeHtml(errorMessage)}</div>
1346
+ <div class="diff-empty-state" role="alert">${escapeHtml(errorMessage)}</div>
1349
1347
  </section>
1350
1348
  `;
1351
1349
  }
@@ -1425,9 +1423,9 @@ export class GitDiffViewController {
1425
1423
  const bodyMarkup = isCollapsed
1426
1424
  ? ''
1427
1425
  : isLoading
1428
- ? '<div class="diff-empty-state">Loading file diff...</div>'
1426
+ ? '<div class="diff-empty-state" role="status" aria-live="polite">Loading file diff…</div>'
1429
1427
  : errorMessage
1430
- ? `<div class="diff-empty-state">${escapeHtml(errorMessage)}</div>`
1428
+ ? `<div class="diff-empty-state" role="alert">${escapeHtml(errorMessage)}</div>`
1431
1429
  : this.renderDiffDetail(detail, index, { includeHeader: false });
1432
1430
 
1433
1431
  return `
@@ -1837,8 +1835,8 @@ export class GitDiffViewController {
1837
1835
  this.fileIndicator.textContent = `${totalFiles} file${totalFiles === 1 ? '' : 's'}`;
1838
1836
  } else {
1839
1837
  this.fileIndicator.textContent = totalFiles > 0
1840
- ? `${visibleIndex} / ${totalFiles} files`
1841
- : '0 / 0 files';
1838
+ ? `${visibleIndex} of ${totalFiles}`
1839
+ : '0 files';
1842
1840
  }
1843
1841
  }
1844
1842
 
@@ -1859,6 +1857,7 @@ export class GitDiffViewController {
1859
1857
  const deletions = allFilesAreImages
1860
1858
  ? 0
1861
1859
  : Math.max(0, rawDeletions - imageLineStats.deletions);
1860
+ // pi-lens-ignore: ast-grep:no-inner-html-js
1862
1861
  this.stats.innerHTML = `
1863
1862
  <span class="ui-stat-token ui-stat-token--add diff-stats-add">+${additions}</span>
1864
1863
  <span class="ui-stat-token ui-stat-token--del diff-stats-del">-${deletions}</span>
@@ -1866,16 +1865,22 @@ export class GitDiffViewController {
1866
1865
  }
1867
1866
 
1868
1867
  this.modeButtons.forEach((button) => {
1868
+ const active = button.getAttribute('data-diff-mode') === this.mode;
1869
1869
  button.classList.remove('hidden');
1870
- button.classList.toggle('active', button.getAttribute('data-diff-mode') === this.mode);
1870
+ button.classList.toggle('active', active);
1871
+ button.setAttribute?.('aria-pressed', String(active));
1871
1872
  });
1872
1873
  this.layoutButtons.forEach((button) => {
1873
- button.classList.toggle('active', button.getAttribute('data-diff-layout') === this.layoutMode);
1874
+ const active = button.getAttribute('data-diff-layout') === this.layoutMode;
1875
+ button.classList.toggle('active', active);
1876
+ button.setAttribute?.('aria-pressed', String(active));
1874
1877
  });
1875
1878
 
1876
1879
  const hasCurrentFile = Boolean(this.getCurrentFile()?.path);
1880
+ const hasEditorFile = hasCurrentFile || Boolean(this.workspaceFilePath);
1877
1881
  const actionState = this.getCurrentActionState();
1878
1882
  const primaryAction = this.getPrimaryAction();
1883
+ const includedFileCount = Number(this.repoStatus?.summary?.staged || 0);
1879
1884
 
1880
1885
  this.backToHistoryButton?.classList.toggle('hidden', !isCommitSource);
1881
1886
  this.gitActionsGroup?.classList.toggle('hidden', isCommitSource);
@@ -1885,23 +1890,33 @@ export class GitDiffViewController {
1885
1890
  this.stats?.classList.remove('hidden');
1886
1891
 
1887
1892
  if (this.openEditorButton) {
1888
- this.openEditorButton.textContent = 'Open in Editor';
1893
+ this.openEditorButton.textContent = 'Open in editor';
1889
1894
  }
1890
- this.openEditorButton?.toggleAttribute('disabled', !hasCurrentFile || isCommitSource);
1895
+ this.openEditorButton?.toggleAttribute('disabled', !hasEditorFile || isCommitSource);
1891
1896
  if (this.primaryActionButton) {
1892
- this.primaryActionButton.textContent = this.pendingAction === primaryAction
1893
- ? 'Working...'
1897
+ const emphasizeInclude = primaryAction === 'stage' && !actionState.canUnstage;
1898
+ this.primaryActionButton.classList.toggle('ui-button--primary', emphasizeInclude);
1899
+ this.primaryActionButton.classList.toggle('ui-button--secondary', !emphasizeInclude);
1900
+ this.primaryActionButton.classList.toggle('ui-button--surface', !emphasizeInclude);
1901
+ this.primaryActionButton.textContent = this.pendingAction && this.pendingAction === primaryAction
1902
+ ? 'Working…'
1894
1903
  : primaryAction === 'unstage'
1895
- ? 'Unstage'
1896
- : 'Stage';
1904
+ ? 'Remove'
1905
+ : 'Include in commit';
1897
1906
  this.primaryActionButton.toggleAttribute(
1898
1907
  'disabled',
1899
1908
  isCommitSource || !hasCurrentFile || !primaryAction || Boolean(this.pendingAction),
1900
1909
  );
1901
1910
  }
1902
1911
  if (this.commitButton) {
1903
- this.commitButton.textContent = this.pendingAction === 'commit' ? 'Working...' : 'Commit Staged';
1912
+ this.commitButton.textContent = this.pendingAction === 'commit'
1913
+ ? 'Working…'
1914
+ : commitButtonLabel(includedFileCount);
1904
1915
  }
1916
+ this.commitButton?.classList.toggle(
1917
+ 'hidden',
1918
+ isCommitSource || !hasCurrentFile || !actionState.canUnstage,
1919
+ );
1905
1920
  this.commitButton?.toggleAttribute(
1906
1921
  'disabled',
1907
1922
  isCommitSource || !actionState.canCommit || Boolean(this.pendingAction),
@@ -1934,8 +1949,10 @@ export class GitDiffViewController {
1934
1949
  this.drawioPreviewPayloads.clear();
1935
1950
 
1936
1951
  if (this.source === 'commit') {
1952
+ // pi-lens-ignore: ast-grep:no-inner-html-js
1937
1953
  this.content.innerHTML = `${this.renderCommitHeader()}${this.renderCommitBody()}`;
1938
1954
  } else {
1955
+ // pi-lens-ignore: ast-grep:no-inner-html-js
1939
1956
  this.content.innerHTML = this.renderFocusedFileBody();
1940
1957
  }
1941
1958
  this.syncToolbar();
@@ -1,4 +1,5 @@
1
1
  import { escapeHtml } from '../domain/vault-utils.js';
2
+ import { commitButtonLabel } from '../domain/git-labels.js';
2
3
  import { getVaultPathLeaf, getVaultPathParent } from '../domain/vault-paths.js';
3
4
  import { buttonClassNames } from './components/ui/button.js';
4
5
  import { segmentedButtonClassNames, segmentedControlClassNames } from './components/ui/segmented-control.js';
@@ -93,7 +94,9 @@ export class GitPanelController {
93
94
  onResetFile = () => {},
94
95
  onSelectCommit = () => {},
95
96
  onSelectDiff = () => {},
97
+ onStageAll = () => {},
96
98
  onStageFile = () => {},
99
+ onUnstageAll = () => {},
97
100
  onUnstageFile = () => {},
98
101
  onViewAllDiff = () => {},
99
102
  searchInput = null,
@@ -109,7 +112,9 @@ export class GitPanelController {
109
112
  this.onResetFile = onResetFile;
110
113
  this.onSelectCommit = onSelectCommit;
111
114
  this.onSelectDiff = onSelectDiff;
115
+ this.onStageAll = onStageAll;
112
116
  this.onStageFile = onStageFile;
117
+ this.onUnstageAll = onUnstageAll;
113
118
  this.onUnstageFile = onUnstageFile;
114
119
  this.onViewAllDiff = onViewAllDiff;
115
120
  this.searchInput = searchInput;
@@ -117,6 +122,7 @@ export class GitPanelController {
117
122
  this.panel = document.getElementById('gitPanel');
118
123
  this.pullBackups = [];
119
124
  this.status = null;
125
+ this.statusError = '';
120
126
  this.active = false;
121
127
  this.refreshTimer = null;
122
128
  this.searchQuery = '';
@@ -235,6 +241,17 @@ export class GitPanelController {
235
241
 
236
242
  if (this._handleFileActionClick(event)) return;
237
243
 
244
+ const bulkActionButton = event.target instanceof Element
245
+ ? event.target.closest('[data-git-bulk-action]')
246
+ : null;
247
+ if (bulkActionButton) {
248
+ const action = bulkActionButton.getAttribute('data-git-bulk-action');
249
+ if (action === 'stage-all' || action === 'unstage-all') {
250
+ void this.handleBulkAction(action);
251
+ }
252
+ return;
253
+ }
254
+
238
255
  if (event.target instanceof Element && event.target.closest('[data-git-view-all]')) {
239
256
  this.onViewAllDiff();
240
257
  return;
@@ -376,7 +393,7 @@ export class GitPanelController {
376
393
 
377
394
  async refresh({ force = false, includeHistory = this.panelMode === 'history' } = {}) {
378
395
  const status = await this.refreshStatus({ force });
379
- if (includeHistory && status.isGitRepo) {
396
+ if (includeHistory && status?.isGitRepo) {
380
397
  await this.refreshHistory({ force });
381
398
  }
382
399
  return status;
@@ -384,6 +401,7 @@ export class GitPanelController {
384
401
 
385
402
  async refreshStatus({ force = false } = {}) {
386
403
  if (!this.enabled) {
404
+ this.statusError = '';
387
405
  this.status = {
388
406
  isGitRepo: false,
389
407
  sections: [],
@@ -408,6 +426,7 @@ export class GitPanelController {
408
426
  try {
409
427
  const data = await this.gitApiClient.readStatus({ force });
410
428
  this.status = data;
429
+ this.statusError = '';
411
430
  this.pullBackups = [];
412
431
  if (data.isGitRepo) {
413
432
  try {
@@ -434,25 +453,9 @@ export class GitPanelController {
434
453
  } catch (error) {
435
454
  console.error('[git-panel] Failed to load git status:', error);
436
455
  this.toastController?.show('Failed to load git status');
437
- this.status = {
438
- isGitRepo: false,
439
- sections: [],
440
- summary: { changedFiles: 0 },
441
- };
442
- this.pullBackups = [];
443
- this.history = {
444
- ...this.history,
445
- commits: [],
446
- error: '',
447
- hasMore: false,
448
- loaded: false,
449
- loading: false,
450
- loadingMore: false,
451
- offset: 0,
452
- };
453
- this.onRepoChange(false, this.status);
456
+ this.statusError = 'Failed to load Git status. Try again.';
454
457
  this.render();
455
- return this.status;
458
+ return null;
456
459
  }
457
460
  }
458
461
 
@@ -614,6 +617,22 @@ export class GitPanelController {
614
617
  }
615
618
  }
616
619
 
620
+ async handleBulkAction(action) {
621
+ if (this.pendingActionKey) {
622
+ return;
623
+ }
624
+
625
+ this.pendingActionKey = action;
626
+ this.render();
627
+
628
+ try {
629
+ await (action === 'stage-all' ? this.onStageAll() : this.onUnstageAll());
630
+ } finally {
631
+ this.pendingActionKey = null;
632
+ this.render();
633
+ }
634
+ }
635
+
617
636
  async handleCommitStaged() {
618
637
  const actionKey = 'commit-staged';
619
638
  if (this.pendingActionKey === actionKey) {
@@ -659,12 +678,13 @@ export class GitPanelController {
659
678
  }
660
679
 
661
680
  const isCollapsed = this.collapsedSections.has(section.key);
681
+ const label = section.key === 'staged' ? 'Included in Next Commit' : section.label;
662
682
 
663
683
  return `
664
684
  <section class="git-section">
665
685
  <button class="git-section-header" type="button" data-git-section-toggle="${escapeHtml(section.key)}">
666
686
  ${chevronSvg(isCollapsed)}
667
- ${escapeHtml(section.label)}
687
+ ${escapeHtml(label)}
668
688
  <span class="ui-pill-badge ui-pill-badge--count ui-pill-badge--muted git-section-count">${files.length}</span>
669
689
  </button>
670
690
  <div class="git-file-list${isCollapsed ? ' hidden' : ''}">
@@ -724,8 +744,8 @@ export class GitPanelController {
724
744
  const fullPath = String(file.path || '');
725
745
  const statusClass = badgeClass(file.status);
726
746
  const stageAction = file.scope === 'staged'
727
- ? { label: 'Unstage', value: 'unstage' }
728
- : { label: 'Stage', value: 'stage' };
747
+ ? { label: 'Remove from commit', value: 'unstage' }
748
+ : { label: 'Include in commit', value: 'stage' };
729
749
  const actionKey = `${stageAction.value}:${file.scope}:${file.path}`;
730
750
  const isPending = this.pendingActionKey === actionKey;
731
751
  const resetActionKey = `reset:${file.scope}:${file.path}`;
@@ -833,11 +853,11 @@ export class GitPanelController {
833
853
  const commits = this.filterCommits(this.history.commits);
834
854
 
835
855
  if (this.history.loading && !this.history.loaded) {
836
- return '<div class="git-panel-empty">Loading git history...</div>';
856
+ return '<div class="git-panel-empty" role="status" aria-live="polite">Loading git history…</div>';
837
857
  }
838
858
 
839
859
  if (this.history.error && !this.history.loaded) {
840
- return `<div class="git-panel-empty">${escapeHtml(this.history.error)}</div>`;
860
+ return `<div class="git-panel-empty" role="alert">${escapeHtml(this.history.error)}</div>`;
841
861
  }
842
862
 
843
863
  if (this.history.loaded && commits.length === 0 && this.history.commits.length === 0) {
@@ -860,7 +880,7 @@ export class GitPanelController {
860
880
  data-git-history-load-more
861
881
  ${this.history.loadingMore ? 'disabled' : ''}
862
882
  >
863
- ${this.history.loadingMore ? 'Loading...' : 'Load More'}
883
+ ${this.history.loadingMore ? 'Loading' : 'Load more'}
864
884
  </button>
865
885
  </div>
866
886
  ` : ''}
@@ -874,7 +894,9 @@ export class GitPanelController {
874
894
  .filter(Boolean)
875
895
  .join('');
876
896
  const hasChanges = Boolean(this.status.summary?.changedFiles);
877
- const hasStagedChanges = Number(this.status.summary?.staged || 0) > 0;
897
+ const includedFileCount = Number(this.status.summary?.staged || 0);
898
+ const excludedFileCount = Number(this.status.summary?.workingTree || 0)
899
+ + Number(this.status.summary?.untracked || 0);
878
900
  const isCommitPending = this.pendingActionKey === 'commit-staged';
879
901
 
880
902
  return `
@@ -883,17 +905,37 @@ export class GitPanelController {
883
905
  ${hasChanges ? `
884
906
  <div class="git-panel-footer">
885
907
  <div class="git-panel-footer-actions">
908
+ ${excludedFileCount > 0 ? `
909
+ <button
910
+ class="${buttonClassNames({ variant: 'secondary', size: 'compact', action: true, surface: true })}"
911
+ type="button"
912
+ data-git-bulk-action="stage-all"
913
+ ${this.pendingActionKey ? 'disabled' : ''}
914
+ >
915
+ ${this.pendingActionKey === 'stage-all' ? 'Working...' : 'Include all changes'}
916
+ </button>
917
+ ` : ''}
918
+ ${includedFileCount > 0 ? `
919
+ <button
920
+ class="${buttonClassNames({ variant: 'secondary', size: 'compact', action: true, surface: true })}"
921
+ type="button"
922
+ data-git-bulk-action="unstage-all"
923
+ ${this.pendingActionKey ? 'disabled' : ''}
924
+ >
925
+ ${this.pendingActionKey === 'unstage-all' ? 'Working...' : 'Remove all from commit'}
926
+ </button>
927
+ ` : ''}
886
928
  <button class="${buttonClassNames({ variant: 'secondary', size: 'compact', action: true, surface: true })}" type="button" data-git-view-all>
887
929
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M2 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
888
- View Full Diff
930
+ View full diff
889
931
  </button>
890
932
  <button
891
933
  class="${buttonClassNames({ variant: 'primary', action: true, wide: true, extra: 'git-footer-commit-btn' })}"
892
934
  type="button"
893
935
  data-git-commit-staged
894
- ${!hasStagedChanges || isCommitPending ? 'disabled' : ''}
936
+ ${includedFileCount === 0 || isCommitPending ? 'disabled' : ''}
895
937
  >
896
- ${isCommitPending ? 'Working...' : 'Commit Staged'}
938
+ ${isCommitPending ? 'Working' : commitButtonLabel(includedFileCount)}
897
939
  </button>
898
940
  </div>
899
941
  </div>
@@ -901,13 +943,19 @@ export class GitPanelController {
901
943
  `;
902
944
  }
903
945
 
904
- renderEmpty(message) {
946
+ renderEmpty(message, { alert = false, status = false } = {}) {
905
947
  if (!this.panel) {
906
948
  return;
907
949
  }
908
950
 
951
+ const semantics = alert
952
+ ? ' role="alert"'
953
+ : status
954
+ ? ' role="status" aria-live="polite"'
955
+ : '';
956
+ // pi-lens-ignore: ast-grep:no-inner-html-js
909
957
  this.panel.innerHTML = `
910
- <div class="git-panel-empty ui-empty-state ui-empty-state--compact">
958
+ <div class="git-panel-empty ui-empty-state ui-empty-state--compact"${semantics}>
911
959
  <p class="ui-empty-state-copy">${escapeHtml(message)}</p>
912
960
  </div>
913
961
  `;
@@ -918,8 +966,13 @@ export class GitPanelController {
918
966
  return;
919
967
  }
920
968
 
969
+ if (this.statusError) {
970
+ this.renderEmpty(this.statusError, { alert: true });
971
+ return;
972
+ }
973
+
921
974
  if (!this.status) {
922
- this.renderEmpty('Loading git status...');
975
+ this.renderEmpty('Loading git status', { status: true });
923
976
  return;
924
977
  }
925
978
 
@@ -933,6 +986,7 @@ export class GitPanelController {
933
986
  const isPullPending = this.pendingActionKey === 'sync:pull';
934
987
  const isPushPending = this.pendingActionKey === 'sync:push';
935
988
 
989
+ // pi-lens-ignore: ast-grep:no-inner-html-js
936
990
  this.panel.innerHTML = `
937
991
  <div class="git-branch-bar">
938
992
  <div class="git-branch-meta">