@piecemaker-legal/piecemaker 1.0.0

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 (1424) hide show
  1. package/LICENSE +718 -0
  2. package/README.md +80 -0
  3. package/dist/Mistral-Icon-Gradient-RGB.svg +12 -0
  4. package/dist/api-docs.html +901 -0
  5. package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  6. package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  7. package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  8. package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  9. package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  10. package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  11. package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  12. package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  13. package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  14. package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  15. package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  16. package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  17. package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  18. package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  19. package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  20. package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  21. package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  22. package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  23. package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  24. package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  25. package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  26. package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  27. package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  28. package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  29. package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  30. package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  31. package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  32. package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  33. package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  34. package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  35. package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  36. package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  37. package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  38. package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  39. package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  40. package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  41. package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  42. package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  43. package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  44. package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  45. package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  46. package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  47. package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  48. package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  49. package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  50. package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  51. package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  52. package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  53. package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  54. package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  55. package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  56. package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  57. package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  58. package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  59. package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  60. package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  61. package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  62. package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  63. package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  64. package/dist/assets/abnfDiagram-N423BO3Z-DjEx6DRO.js +1 -0
  65. package/dist/assets/arc-DYt0oU_6.js +1 -0
  66. package/dist/assets/architectureDiagram-T3A2C74G-Dn6DhYDe.js +36 -0
  67. package/dist/assets/blockDiagram-VBNYF7ZC-CsvhTLZi.js +132 -0
  68. package/dist/assets/c4Diagram-5PPSVZJV-BuPnjHm6.js +10 -0
  69. package/dist/assets/channel-Czt0N91A.js +1 -0
  70. package/dist/assets/chunk-2GRJ4B5K-BZJJc1-J.js +1 -0
  71. package/dist/assets/chunk-2Q5K7J3B-6stdrDbe.js +1 -0
  72. package/dist/assets/chunk-5RXB4S5H-D5UwN5cg.js +231 -0
  73. package/dist/assets/chunk-5VM5RSS4-BDB8AQ_I.js +15 -0
  74. package/dist/assets/chunk-6Q2QTUOP-RhjQ-NDz.js +88 -0
  75. package/dist/assets/chunk-GF5L2VYU-CJuiA7R4.js +206 -0
  76. package/dist/assets/chunk-JWPE2WC7-DjFkIZqh.js +1 -0
  77. package/dist/assets/chunk-KBJHAD2P-BeSQsoqv.js +1 -0
  78. package/dist/assets/chunk-RYQCIY6F-CPgwsb0o.js +1 -0
  79. package/dist/assets/chunk-XXDRQBXY-CMMVEsX3.js +1 -0
  80. package/dist/assets/classDiagram-JCYQIIEL-BrnQyrwR.js +1 -0
  81. package/dist/assets/classDiagram-v2-OCEON4UE-BrnQyrwR.js +1 -0
  82. package/dist/assets/cose-bilkent-JH36ORCC-XAdYMfi5.js +1 -0
  83. package/dist/assets/cynefin-VYW2F7L2-d2GpDBn-.js +178 -0
  84. package/dist/assets/cynefinDiagram-MW4NZA55-CGtqUrU1.js +62 -0
  85. package/dist/assets/cytoscape.esm-C10L9Icf.js +331 -0
  86. package/dist/assets/dagre-VZM6K2ZE-BxujKIsf.js +4 -0
  87. package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  88. package/dist/assets/diagram-7IWD3JNH-CJn9hobL.js +30 -0
  89. package/dist/assets/diagram-B4RE2ZJO-DF0Cnjzz.js +3 -0
  90. package/dist/assets/diagram-LBJQPF4R-Bq4d3NfR.js +24 -0
  91. package/dist/assets/diagram-Q27KOJAE-DDdfoXt-.js +24 -0
  92. package/dist/assets/diagram-UB23O5K3-TSFk7FuJ.js +41 -0
  93. package/dist/assets/ebnfDiagram-BXEA7PRR-DRvm2Wy9.js +1 -0
  94. package/dist/assets/erDiagram-JOGREHBK-BmdN66-A.js +85 -0
  95. package/dist/assets/flowDiagram-UKHOOZJN-Dsp5LwJz.js +156 -0
  96. package/dist/assets/ganttDiagram-PKOTCBZU-CYfCQ4Yi.js +292 -0
  97. package/dist/assets/gitGraphDiagram-DS77QQ5N-DEzmuv8v.js +106 -0
  98. package/dist/assets/graph-Cx-EqisW.js +1 -0
  99. package/dist/assets/index-CqFxV_pT.css +32 -0
  100. package/dist/assets/index-dWwHeqcq.js +4989 -0
  101. package/dist/assets/infoDiagram-6WML65LV-B1EfV5Bm.js +2 -0
  102. package/dist/assets/init-Gi6I4Gst.js +1 -0
  103. package/dist/assets/ishikawaDiagram-WSZJBQD7-OuQJfUii.js +70 -0
  104. package/dist/assets/journeyDiagram-NVQOT4AX-DHIilb_4.js +139 -0
  105. package/dist/assets/kanban-definition-27J2QSJJ-D4CvKWBP.js +89 -0
  106. package/dist/assets/layout-D6BstSzF.js +1 -0
  107. package/dist/assets/linear-i_Nzyzap.js +1 -0
  108. package/dist/assets/map-CV9uif0g.js +1 -0
  109. package/dist/assets/mermaid.core-DbSHejzG.js +312 -0
  110. package/dist/assets/mindmap-definition-FAOFIHXS-DqhC-BPZ.js +96 -0
  111. package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  112. package/dist/assets/pegDiagram-VL7TDLO6-pBqvOEvm.js +1 -0
  113. package/dist/assets/pieDiagram-7S7Q4E2Y-BH53iuaz.js +39 -0
  114. package/dist/assets/quadrantDiagram-CIZ2JOQS-CvW9ldJo.js +7 -0
  115. package/dist/assets/railroadDiagram-AXF67PYL-CERi66oR.js +1 -0
  116. package/dist/assets/requirementDiagram-LRYGKXZP-DbcP4MGI.js +84 -0
  117. package/dist/assets/sankeyDiagram-W5VNT64P-DO9bPHWO.js +40 -0
  118. package/dist/assets/sequenceDiagram-SI44F4Z6-D3zd2eJS.js +162 -0
  119. package/dist/assets/server.browser-CtX3Hdl5.js +27 -0
  120. package/dist/assets/sizeCapture-X5ZJPWSS-mcEXJiem.js +1 -0
  121. package/dist/assets/stateDiagram-OKZ733FA-DMqQgpiD.js +1 -0
  122. package/dist/assets/stateDiagram-v2-UEYNNEHI-DprF_P9y.js +1 -0
  123. package/dist/assets/swimlanes-SLNWSIFB-Cb8rIhB1.js +2 -0
  124. package/dist/assets/swimlanesDiagram-ULZ7WXOC-C6NVYMho.js +8 -0
  125. package/dist/assets/timeline-definition-Z64GVDOM-BQ4r_QsK.js +120 -0
  126. package/dist/assets/vendor-codemirror-CYrSt7-U.js +41 -0
  127. package/dist/assets/vendor-react-BGZc9oRE.js +59 -0
  128. package/dist/assets/vendor-xterm-CS4rQ5Mr.js +66 -0
  129. package/dist/assets/vennDiagram-T6HMQDX7-BEkKGTum.js +34 -0
  130. package/dist/assets/wardleyDiagram-T6FBY63Y-kJwmgH-h.js +78 -0
  131. package/dist/assets/xychartDiagram-ELKLHX3M-CSJRTKCr.js +7 -0
  132. package/dist/clear-cache.html +85 -0
  133. package/dist/convert-icons.md +53 -0
  134. package/dist/favicon.png +0 -0
  135. package/dist/favicon.svg +9 -0
  136. package/dist/generate-icons.js +49 -0
  137. package/dist/icons/claude-ai-icon.svg +1 -0
  138. package/dist/icons/codex-white.svg +3 -0
  139. package/dist/icons/codex.svg +3 -0
  140. package/dist/icons/cursor-white.svg +12 -0
  141. package/dist/icons/cursor.svg +1 -0
  142. package/dist/icons/icon-128x128.png +0 -0
  143. package/dist/icons/icon-128x128.svg +12 -0
  144. package/dist/icons/icon-144x144.png +0 -0
  145. package/dist/icons/icon-144x144.svg +12 -0
  146. package/dist/icons/icon-152x152.png +0 -0
  147. package/dist/icons/icon-152x152.svg +12 -0
  148. package/dist/icons/icon-192x192.png +0 -0
  149. package/dist/icons/icon-192x192.svg +12 -0
  150. package/dist/icons/icon-384x384.png +0 -0
  151. package/dist/icons/icon-384x384.svg +12 -0
  152. package/dist/icons/icon-512x512.png +0 -0
  153. package/dist/icons/icon-512x512.svg +12 -0
  154. package/dist/icons/icon-72x72.png +0 -0
  155. package/dist/icons/icon-72x72.svg +12 -0
  156. package/dist/icons/icon-96x96.png +0 -0
  157. package/dist/icons/icon-96x96.svg +12 -0
  158. package/dist/icons/icon-template.svg +12 -0
  159. package/dist/index.html +60 -0
  160. package/dist/logo-128.png +0 -0
  161. package/dist/logo-256.png +0 -0
  162. package/dist/logo-32.png +0 -0
  163. package/dist/logo-512.png +0 -0
  164. package/dist/logo-64.png +0 -0
  165. package/dist/logo.svg +17 -0
  166. package/dist/manifest.json +61 -0
  167. package/dist/screenshots/cli-selection.png +0 -0
  168. package/dist/screenshots/desktop-main.png +0 -0
  169. package/dist/screenshots/mobile-chat.png +0 -0
  170. package/dist/screenshots/tools-modal.png +0 -0
  171. package/dist/sw.js +125 -0
  172. package/dist-server/server/index.js +345 -0
  173. package/dist-server/server/index.js.map +1 -0
  174. package/dist-server/server/load-env.js +46 -0
  175. package/dist-server/server/load-env.js.map +1 -0
  176. package/dist-server/server/modules/agent/agent.module.js +38 -0
  177. package/dist-server/server/modules/agent/agent.module.js.map +1 -0
  178. package/dist-server/server/modules/agent/agent.routes.js +1161 -0
  179. package/dist-server/server/modules/agent/agent.routes.js.map +1 -0
  180. package/dist-server/server/modules/agent/index.js +3 -0
  181. package/dist-server/server/modules/agent/index.js.map +1 -0
  182. package/dist-server/server/modules/agent/tests/agent.routes.test.js +176 -0
  183. package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -0
  184. package/dist-server/server/modules/assets/assets.routes.js +130 -0
  185. package/dist-server/server/modules/assets/assets.routes.js.map +1 -0
  186. package/dist-server/server/modules/assets/index.js +4 -0
  187. package/dist-server/server/modules/assets/index.js.map +1 -0
  188. package/dist-server/server/modules/assets/services/image-assets.service.js +95 -0
  189. package/dist-server/server/modules/assets/services/image-assets.service.js.map +1 -0
  190. package/dist-server/server/modules/assets/tests/image-assets.service.test.js +56 -0
  191. package/dist-server/server/modules/assets/tests/image-assets.service.test.js.map +1 -0
  192. package/dist-server/server/modules/auth/auth.middleware.js +133 -0
  193. package/dist-server/server/modules/auth/auth.middleware.js.map +1 -0
  194. package/dist-server/server/modules/auth/auth.module.js +29 -0
  195. package/dist-server/server/modules/auth/auth.module.js.map +1 -0
  196. package/dist-server/server/modules/auth/auth.routes.js +45 -0
  197. package/dist-server/server/modules/auth/auth.routes.js.map +1 -0
  198. package/dist-server/server/modules/auth/auth.service.js +113 -0
  199. package/dist-server/server/modules/auth/auth.service.js.map +1 -0
  200. package/dist-server/server/modules/auth/index.js +9 -0
  201. package/dist-server/server/modules/auth/index.js.map +1 -0
  202. package/dist-server/server/modules/auth/tests/auth.service.test.js +80 -0
  203. package/dist-server/server/modules/auth/tests/auth.service.test.js.map +1 -0
  204. package/dist-server/server/modules/browser-use/browser-use-mcp.js +352 -0
  205. package/dist-server/server/modules/browser-use/browser-use-mcp.js.map +1 -0
  206. package/dist-server/server/modules/browser-use/browser-use-mcp.routes.js +107 -0
  207. package/dist-server/server/modules/browser-use/browser-use-mcp.routes.js.map +1 -0
  208. package/dist-server/server/modules/browser-use/browser-use-runtime.js +10 -0
  209. package/dist-server/server/modules/browser-use/browser-use-runtime.js.map +1 -0
  210. package/dist-server/server/modules/browser-use/browser-use.routes.js +93 -0
  211. package/dist-server/server/modules/browser-use/browser-use.routes.js.map +1 -0
  212. package/dist-server/server/modules/browser-use/browser-use.service.js +686 -0
  213. package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -0
  214. package/dist-server/server/modules/browser-use/index.js +11 -0
  215. package/dist-server/server/modules/browser-use/index.js.map +1 -0
  216. package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js +8 -0
  217. package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js.map +1 -0
  218. package/dist-server/server/modules/cli/cli.js +17 -0
  219. package/dist-server/server/modules/cli/cli.js.map +1 -0
  220. package/dist-server/server/modules/cli/cli.module.js +93 -0
  221. package/dist-server/server/modules/cli/cli.module.js.map +1 -0
  222. package/dist-server/server/modules/cli/cli.service.js +230 -0
  223. package/dist-server/server/modules/cli/cli.service.js.map +1 -0
  224. package/dist-server/server/modules/cli/index.js +3 -0
  225. package/dist-server/server/modules/cli/index.js.map +1 -0
  226. package/dist-server/server/modules/cli/pwa-launcher.js +116 -0
  227. package/dist-server/server/modules/cli/pwa-launcher.js.map +1 -0
  228. package/dist-server/server/modules/cli/sandbox.service.js +332 -0
  229. package/dist-server/server/modules/cli/sandbox.service.js.map +1 -0
  230. package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +154 -0
  231. package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js.map +1 -0
  232. package/dist-server/server/modules/cli/tests/cli.service.test.js +91 -0
  233. package/dist-server/server/modules/cli/tests/cli.service.test.js.map +1 -0
  234. package/dist-server/server/modules/cli/tests/sandbox.service.test.js +55 -0
  235. package/dist-server/server/modules/cli/tests/sandbox.service.test.js.map +1 -0
  236. package/dist-server/server/modules/commands/commands.module.js +20 -0
  237. package/dist-server/server/modules/commands/commands.module.js.map +1 -0
  238. package/dist-server/server/modules/commands/commands.routes.js +498 -0
  239. package/dist-server/server/modules/commands/commands.routes.js.map +1 -0
  240. package/dist-server/server/modules/commands/index.js +3 -0
  241. package/dist-server/server/modules/commands/index.js.map +1 -0
  242. package/dist-server/server/modules/commands/tests/commands.test.js +91 -0
  243. package/dist-server/server/modules/commands/tests/commands.test.js.map +1 -0
  244. package/dist-server/server/modules/database/connection.js +125 -0
  245. package/dist-server/server/modules/database/connection.js.map +1 -0
  246. package/dist-server/server/modules/database/index.js +23 -0
  247. package/dist-server/server/modules/database/index.js.map +1 -0
  248. package/dist-server/server/modules/database/init-db.js +18 -0
  249. package/dist-server/server/modules/database/init-db.js.map +1 -0
  250. package/dist-server/server/modules/database/migrations.js +465 -0
  251. package/dist-server/server/modules/database/migrations.js.map +1 -0
  252. package/dist-server/server/modules/database/repositories/api-keys.js +72 -0
  253. package/dist-server/server/modules/database/repositories/api-keys.js.map +1 -0
  254. package/dist-server/server/modules/database/repositories/app-config.js +47 -0
  255. package/dist-server/server/modules/database/repositories/app-config.js.map +1 -0
  256. package/dist-server/server/modules/database/repositories/credentials.js +68 -0
  257. package/dist-server/server/modules/database/repositories/credentials.js.map +1 -0
  258. package/dist-server/server/modules/database/repositories/github-tokens.js +54 -0
  259. package/dist-server/server/modules/database/repositories/github-tokens.js.map +1 -0
  260. package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js +100 -0
  261. package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js.map +1 -0
  262. package/dist-server/server/modules/database/repositories/notification-preferences.js +82 -0
  263. package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -0
  264. package/dist-server/server/modules/database/repositories/projects.db.js +172 -0
  265. package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -0
  266. package/dist-server/server/modules/database/repositories/provider-models.js +112 -0
  267. package/dist-server/server/modules/database/repositories/provider-models.js.map +1 -0
  268. package/dist-server/server/modules/database/repositories/push-subscriptions.js +49 -0
  269. package/dist-server/server/modules/database/repositories/push-subscriptions.js.map +1 -0
  270. package/dist-server/server/modules/database/repositories/scan-state.db.js +31 -0
  271. package/dist-server/server/modules/database/repositories/scan-state.db.js.map +1 -0
  272. package/dist-server/server/modules/database/repositories/scheduled-messages.db.js +71 -0
  273. package/dist-server/server/modules/database/repositories/scheduled-messages.db.js.map +1 -0
  274. package/dist-server/server/modules/database/repositories/session-drafts.db.js +105 -0
  275. package/dist-server/server/modules/database/repositories/session-drafts.db.js.map +1 -0
  276. package/dist-server/server/modules/database/repositories/sessions.db.js +507 -0
  277. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -0
  278. package/dist-server/server/modules/database/repositories/user-preferences.db.js +65 -0
  279. package/dist-server/server/modules/database/repositories/user-preferences.db.js.map +1 -0
  280. package/dist-server/server/modules/database/repositories/users.js +88 -0
  281. package/dist-server/server/modules/database/repositories/users.js.map +1 -0
  282. package/dist-server/server/modules/database/repositories/vapid-keys.js +38 -0
  283. package/dist-server/server/modules/database/repositories/vapid-keys.js.map +1 -0
  284. package/dist-server/server/modules/database/schema.js +291 -0
  285. package/dist-server/server/modules/database/schema.js.map +1 -0
  286. package/dist-server/server/modules/database/tests/projects.db.integration.test.js +64 -0
  287. package/dist-server/server/modules/database/tests/projects.db.integration.test.js.map +1 -0
  288. package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +102 -0
  289. package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js.map +1 -0
  290. package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js +79 -0
  291. package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js.map +1 -0
  292. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js +93 -0
  293. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -0
  294. package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js +105 -0
  295. package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js.map +1 -0
  296. package/dist-server/server/modules/file-tree/file-tree.module.js +95 -0
  297. package/dist-server/server/modules/file-tree/file-tree.module.js.map +1 -0
  298. package/dist-server/server/modules/file-tree/file-tree.routes.js +208 -0
  299. package/dist-server/server/modules/file-tree/file-tree.routes.js.map +1 -0
  300. package/dist-server/server/modules/file-tree/file-tree.service.js +584 -0
  301. package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -0
  302. package/dist-server/server/modules/file-tree/index.js +3 -0
  303. package/dist-server/server/modules/file-tree/index.js.map +1 -0
  304. package/dist-server/server/modules/file-tree/tests/file-tree.routes.test.js +123 -0
  305. package/dist-server/server/modules/file-tree/tests/file-tree.routes.test.js.map +1 -0
  306. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +311 -0
  307. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -0
  308. package/dist-server/server/modules/git/git-branch.service.js +15 -0
  309. package/dist-server/server/modules/git/git-branch.service.js.map +1 -0
  310. package/dist-server/server/modules/git/git-parsing.service.js +61 -0
  311. package/dist-server/server/modules/git/git-parsing.service.js.map +1 -0
  312. package/dist-server/server/modules/git/git.module.js +14 -0
  313. package/dist-server/server/modules/git/git.module.js.map +1 -0
  314. package/dist-server/server/modules/git/git.routes.js +1347 -0
  315. package/dist-server/server/modules/git/git.routes.js.map +1 -0
  316. package/dist-server/server/modules/git/index.js +3 -0
  317. package/dist-server/server/modules/git/index.js.map +1 -0
  318. package/dist-server/server/modules/git/tests/git-branch.service.test.js +52 -0
  319. package/dist-server/server/modules/git/tests/git-branch.service.test.js.map +1 -0
  320. package/dist-server/server/modules/git/tests/git-init.routes.test.js +132 -0
  321. package/dist-server/server/modules/git/tests/git-init.routes.test.js.map +1 -0
  322. package/dist-server/server/modules/git/tests/git.test.js +80 -0
  323. package/dist-server/server/modules/git/tests/git.test.js.map +1 -0
  324. package/dist-server/server/modules/notifications/index.js +20 -0
  325. package/dist-server/server/modules/notifications/index.js.map +1 -0
  326. package/dist-server/server/modules/notifications/notifications.routes.js +115 -0
  327. package/dist-server/server/modules/notifications/notifications.routes.js.map +1 -0
  328. package/dist-server/server/modules/notifications/services/desktop-notification-clients.service.js +97 -0
  329. package/dist-server/server/modules/notifications/services/desktop-notification-clients.service.js.map +1 -0
  330. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +249 -0
  331. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js.map +1 -0
  332. package/dist-server/server/modules/notifications/tests/notification-orchestrator.integration.test.js +44 -0
  333. package/dist-server/server/modules/notifications/tests/notification-orchestrator.integration.test.js.map +1 -0
  334. package/dist-server/server/modules/notifications/vapid-keys.service.js +28 -0
  335. package/dist-server/server/modules/notifications/vapid-keys.service.js.map +1 -0
  336. package/dist-server/server/modules/notifications/websocket/desktop-notifications-websocket.service.js +79 -0
  337. package/dist-server/server/modules/notifications/websocket/desktop-notifications-websocket.service.js.map +1 -0
  338. package/dist-server/server/modules/plugins/index.js +9 -0
  339. package/dist-server/server/modules/plugins/index.js.map +1 -0
  340. package/dist-server/server/modules/plugins/plugin-process.service.js +191 -0
  341. package/dist-server/server/modules/plugins/plugin-process.service.js.map +1 -0
  342. package/dist-server/server/modules/plugins/plugin-registry.service.js +415 -0
  343. package/dist-server/server/modules/plugins/plugin-registry.service.js.map +1 -0
  344. package/dist-server/server/modules/plugins/plugins.module.js +30 -0
  345. package/dist-server/server/modules/plugins/plugins.module.js.map +1 -0
  346. package/dist-server/server/modules/plugins/plugins.routes.js +70 -0
  347. package/dist-server/server/modules/plugins/plugins.routes.js.map +1 -0
  348. package/dist-server/server/modules/plugins/plugins.service.js +123 -0
  349. package/dist-server/server/modules/plugins/plugins.service.js.map +1 -0
  350. package/dist-server/server/modules/plugins/tests/plugins.service.test.js +28 -0
  351. package/dist-server/server/modules/plugins/tests/plugins.service.test.js.map +1 -0
  352. package/dist-server/server/modules/projects/index.js +9 -0
  353. package/dist-server/server/modules/projects/index.js.map +1 -0
  354. package/dist-server/server/modules/projects/projects.routes.js +205 -0
  355. package/dist-server/server/modules/projects/projects.routes.js.map +1 -0
  356. package/dist-server/server/modules/projects/services/project-clone.service.js +220 -0
  357. package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -0
  358. package/dist-server/server/modules/projects/services/project-delete.service.js +89 -0
  359. package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -0
  360. package/dist-server/server/modules/projects/services/project-management.service.js +90 -0
  361. package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -0
  362. package/dist-server/server/modules/projects/services/project-star.service.js +60 -0
  363. package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -0
  364. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js +167 -0
  365. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js.map +1 -0
  366. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +188 -0
  367. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -0
  368. package/dist-server/server/modules/projects/tests/project-clone.service.test.js +126 -0
  369. package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -0
  370. package/dist-server/server/modules/projects/tests/project-management.service.test.js +85 -0
  371. package/dist-server/server/modules/projects/tests/project-management.service.test.js.map +1 -0
  372. package/dist-server/server/modules/projects/tests/project-star.service.test.js +95 -0
  373. package/dist-server/server/modules/projects/tests/project-star.service.test.js.map +1 -0
  374. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js +87 -0
  375. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js.map +1 -0
  376. package/dist-server/server/modules/providers/index.js +12 -0
  377. package/dist-server/server/modules/providers/index.js.map +1 -0
  378. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +151 -0
  379. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -0
  380. package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js +46 -0
  381. package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js.map +1 -0
  382. package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js +103 -0
  383. package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js.map +1 -0
  384. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +267 -0
  385. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -0
  386. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js +1058 -0
  387. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -0
  388. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +141 -0
  389. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -0
  390. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +924 -0
  391. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -0
  392. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +205 -0
  393. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -0
  394. package/dist-server/server/modules/providers/list/claude/claude.provider.js +23 -0
  395. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -0
  396. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js +204 -0
  397. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js.map +1 -0
  398. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js +84 -0
  399. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js.map +1 -0
  400. package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js +32 -0
  401. package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js.map +1 -0
  402. package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js +107 -0
  403. package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js.map +1 -0
  404. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +109 -0
  405. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -0
  406. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js +498 -0
  407. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -0
  408. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +153 -0
  409. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -0
  410. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +1955 -0
  411. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -0
  412. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +62 -0
  413. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -0
  414. package/dist-server/server/modules/providers/list/codex/codex.provider.js +23 -0
  415. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -0
  416. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +118 -0
  417. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -0
  418. package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js +80 -0
  419. package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js.map +1 -0
  420. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +100 -0
  421. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -0
  422. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js +305 -0
  423. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -0
  424. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +111 -0
  425. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -0
  426. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +566 -0
  427. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -0
  428. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js +35 -0
  429. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js.map +1 -0
  430. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +21 -0
  431. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -0
  432. package/dist-server/server/modules/providers/list/mistral/mistral-auth.provider.js +147 -0
  433. package/dist-server/server/modules/providers/list/mistral/mistral-auth.provider.js.map +1 -0
  434. package/dist-server/server/modules/providers/list/mistral/mistral-mcp.provider.js +15 -0
  435. package/dist-server/server/modules/providers/list/mistral/mistral-mcp.provider.js.map +1 -0
  436. package/dist-server/server/modules/providers/list/mistral/mistral-models.provider.js +69 -0
  437. package/dist-server/server/modules/providers/list/mistral/mistral-models.provider.js.map +1 -0
  438. package/dist-server/server/modules/providers/list/mistral/mistral-runtime.provider.js +326 -0
  439. package/dist-server/server/modules/providers/list/mistral/mistral-runtime.provider.js.map +1 -0
  440. package/dist-server/server/modules/providers/list/mistral/mistral-session-synchronizer.provider.js +12 -0
  441. package/dist-server/server/modules/providers/list/mistral/mistral-session-synchronizer.provider.js.map +1 -0
  442. package/dist-server/server/modules/providers/list/mistral/mistral-sessions.provider.js +180 -0
  443. package/dist-server/server/modules/providers/list/mistral/mistral-sessions.provider.js.map +1 -0
  444. package/dist-server/server/modules/providers/list/mistral/mistral-skills.provider.js +15 -0
  445. package/dist-server/server/modules/providers/list/mistral/mistral-skills.provider.js.map +1 -0
  446. package/dist-server/server/modules/providers/list/mistral/mistral.provider.js +25 -0
  447. package/dist-server/server/modules/providers/list/mistral/mistral.provider.js.map +1 -0
  448. package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js +91 -0
  449. package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js.map +1 -0
  450. package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js +181 -0
  451. package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js.map +1 -0
  452. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +257 -0
  453. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -0
  454. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +368 -0
  455. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js.map +1 -0
  456. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +225 -0
  457. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js.map +1 -0
  458. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +136 -0
  459. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -0
  460. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +404 -0
  461. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -0
  462. package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js +62 -0
  463. package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js.map +1 -0
  464. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js +21 -0
  465. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js.map +1 -0
  466. package/dist-server/server/modules/providers/provider.registry.js +33 -0
  467. package/dist-server/server/modules/providers/provider.registry.js.map +1 -0
  468. package/dist-server/server/modules/providers/provider.routes.js +676 -0
  469. package/dist-server/server/modules/providers/provider.routes.js.map +1 -0
  470. package/dist-server/server/modules/providers/services/mcp.service.js +84 -0
  471. package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -0
  472. package/dist-server/server/modules/providers/services/provider-auth.service.js +25 -0
  473. package/dist-server/server/modules/providers/services/provider-auth.service.js.map +1 -0
  474. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +94 -0
  475. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -0
  476. package/dist-server/server/modules/providers/services/provider-models.service.js +289 -0
  477. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -0
  478. package/dist-server/server/modules/providers/services/provider-runtime.service.js +66 -0
  479. package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -0
  480. package/dist-server/server/modules/providers/services/provider-token-usage.service.js +372 -0
  481. package/dist-server/server/modules/providers/services/provider-token-usage.service.js.map +1 -0
  482. package/dist-server/server/modules/providers/services/session-conversations-search.service.js +974 -0
  483. package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -0
  484. package/dist-server/server/modules/providers/services/session-history-cache.service.js +87 -0
  485. package/dist-server/server/modules/providers/services/session-history-cache.service.js.map +1 -0
  486. package/dist-server/server/modules/providers/services/session-synchronizer.service.js +130 -0
  487. package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -0
  488. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +214 -0
  489. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -0
  490. package/dist-server/server/modules/providers/services/sessions.service.js +519 -0
  491. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -0
  492. package/dist-server/server/modules/providers/services/skills.service.js +22 -0
  493. package/dist-server/server/modules/providers/services/skills.service.js.map +1 -0
  494. package/dist-server/server/modules/providers/shared/base/abstract.provider.js +13 -0
  495. package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -0
  496. package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js +102 -0
  497. package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js.map +1 -0
  498. package/dist-server/server/modules/providers/shared/skills/skills.provider.js +207 -0
  499. package/dist-server/server/modules/providers/shared/skills/skills.provider.js.map +1 -0
  500. package/dist-server/server/modules/providers/tests/claude-auth.test.js +174 -0
  501. package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -0
  502. package/dist-server/server/modules/providers/tests/claude-sessions.test.js +470 -0
  503. package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -0
  504. package/dist-server/server/modules/providers/tests/claude-subagent-echo.test.js +16 -0
  505. package/dist-server/server/modules/providers/tests/claude-subagent-echo.test.js.map +1 -0
  506. package/dist-server/server/modules/providers/tests/claude-token-budget.test.js +85 -0
  507. package/dist-server/server/modules/providers/tests/claude-token-budget.test.js.map +1 -0
  508. package/dist-server/server/modules/providers/tests/codex-message-editing.test.js +338 -0
  509. package/dist-server/server/modules/providers/tests/codex-message-editing.test.js.map +1 -0
  510. package/dist-server/server/modules/providers/tests/codex-session-fork.test.js +54 -0
  511. package/dist-server/server/modules/providers/tests/codex-session-fork.test.js.map +1 -0
  512. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +491 -0
  513. package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -0
  514. package/dist-server/server/modules/providers/tests/mcp.test.js +291 -0
  515. package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -0
  516. package/dist-server/server/modules/providers/tests/opencode-models.test.js +103 -0
  517. package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -0
  518. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +424 -0
  519. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -0
  520. package/dist-server/server/modules/providers/tests/provider-attachment-history.test.js +205 -0
  521. package/dist-server/server/modules/providers/tests/provider-attachment-history.test.js.map +1 -0
  522. package/dist-server/server/modules/providers/tests/provider-models.service.test.js +268 -0
  523. package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -0
  524. package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js +126 -0
  525. package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js.map +1 -0
  526. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +329 -0
  527. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js.map +1 -0
  528. package/dist-server/server/modules/providers/tests/provider.routes.test.js +161 -0
  529. package/dist-server/server/modules/providers/tests/provider.routes.test.js.map +1 -0
  530. package/dist-server/server/modules/providers/tests/session-fork.test.js +113 -0
  531. package/dist-server/server/modules/providers/tests/session-fork.test.js.map +1 -0
  532. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js +120 -0
  533. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js.map +1 -0
  534. package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js +90 -0
  535. package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js.map +1 -0
  536. package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js +122 -0
  537. package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js.map +1 -0
  538. package/dist-server/server/modules/providers/tests/sessions-details.test.js +62 -0
  539. package/dist-server/server/modules/providers/tests/sessions-details.test.js.map +1 -0
  540. package/dist-server/server/modules/providers/tests/sessions.service.test.js +131 -0
  541. package/dist-server/server/modules/providers/tests/sessions.service.test.js.map +1 -0
  542. package/dist-server/server/modules/providers/tests/skills.test.js +398 -0
  543. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -0
  544. package/dist-server/server/modules/scheduled-messages/index.js +5 -0
  545. package/dist-server/server/modules/scheduled-messages/index.js.map +1 -0
  546. package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js +47 -0
  547. package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js.map +1 -0
  548. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js +163 -0
  549. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js.map +1 -0
  550. package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js +95 -0
  551. package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js.map +1 -0
  552. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js +255 -0
  553. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js.map +1 -0
  554. package/dist-server/server/modules/settings/index.js +3 -0
  555. package/dist-server/server/modules/settings/index.js.map +1 -0
  556. package/dist-server/server/modules/settings/settings.module.js +35 -0
  557. package/dist-server/server/modules/settings/settings.module.js.map +1 -0
  558. package/dist-server/server/modules/settings/settings.routes.js +34 -0
  559. package/dist-server/server/modules/settings/settings.routes.js.map +1 -0
  560. package/dist-server/server/modules/settings/settings.service.js +116 -0
  561. package/dist-server/server/modules/settings/settings.service.js.map +1 -0
  562. package/dist-server/server/modules/settings/tests/settings.service.test.js +48 -0
  563. package/dist-server/server/modules/settings/tests/settings.service.test.js.map +1 -0
  564. package/dist-server/server/modules/system/index.js +3 -0
  565. package/dist-server/server/modules/system/index.js.map +1 -0
  566. package/dist-server/server/modules/system/system.module.js +44 -0
  567. package/dist-server/server/modules/system/system.module.js.map +1 -0
  568. package/dist-server/server/modules/system/system.routes.js +16 -0
  569. package/dist-server/server/modules/system/system.routes.js.map +1 -0
  570. package/dist-server/server/modules/system/system.service.js +45 -0
  571. package/dist-server/server/modules/system/system.service.js.map +1 -0
  572. package/dist-server/server/modules/system/tests/system.service.test.js +100 -0
  573. package/dist-server/server/modules/system/tests/system.service.test.js.map +1 -0
  574. package/dist-server/server/modules/taskmaster/index.js +3 -0
  575. package/dist-server/server/modules/taskmaster/index.js.map +1 -0
  576. package/dist-server/server/modules/taskmaster/taskmaster.module.js +20 -0
  577. package/dist-server/server/modules/taskmaster/taskmaster.module.js.map +1 -0
  578. package/dist-server/server/modules/taskmaster/taskmaster.routes.js +1372 -0
  579. package/dist-server/server/modules/taskmaster/taskmaster.routes.js.map +1 -0
  580. package/dist-server/server/modules/taskmaster/taskmaster.service.js +107 -0
  581. package/dist-server/server/modules/taskmaster/taskmaster.service.js.map +1 -0
  582. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js +180 -0
  583. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js.map +1 -0
  584. package/dist-server/server/modules/taskmaster/tests/taskmaster.service.test.js +85 -0
  585. package/dist-server/server/modules/taskmaster/tests/taskmaster.service.test.js.map +1 -0
  586. package/dist-server/server/modules/user/index.js +3 -0
  587. package/dist-server/server/modules/user/index.js.map +1 -0
  588. package/dist-server/server/modules/user/tests/user.service.test.js +123 -0
  589. package/dist-server/server/modules/user/tests/user.service.test.js.map +1 -0
  590. package/dist-server/server/modules/user/user.module.js +56 -0
  591. package/dist-server/server/modules/user/user.module.js.map +1 -0
  592. package/dist-server/server/modules/user/user.routes.js +88 -0
  593. package/dist-server/server/modules/user/user.routes.js.map +1 -0
  594. package/dist-server/server/modules/user/user.service.js +134 -0
  595. package/dist-server/server/modules/user/user.service.js.map +1 -0
  596. package/dist-server/server/modules/voice/index.js +3 -0
  597. package/dist-server/server/modules/voice/index.js.map +1 -0
  598. package/dist-server/server/modules/voice/tests/voice.service.test.js +87 -0
  599. package/dist-server/server/modules/voice/tests/voice.service.test.js.map +1 -0
  600. package/dist-server/server/modules/voice/voice.module.js +44 -0
  601. package/dist-server/server/modules/voice/voice.module.js.map +1 -0
  602. package/dist-server/server/modules/voice/voice.routes.js +87 -0
  603. package/dist-server/server/modules/voice/voice.routes.js.map +1 -0
  604. package/dist-server/server/modules/voice/voice.service.js +148 -0
  605. package/dist-server/server/modules/voice/voice.service.js.map +1 -0
  606. package/dist-server/server/modules/websocket/index.js +11 -0
  607. package/dist-server/server/modules/websocket/index.js.map +1 -0
  608. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +232 -0
  609. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -0
  610. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +135 -0
  611. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js.map +1 -0
  612. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +467 -0
  613. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -0
  614. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +52 -0
  615. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -0
  616. package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js +94 -0
  617. package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js.map +1 -0
  618. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +472 -0
  619. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -0
  620. package/dist-server/server/modules/websocket/services/websocket-auth.service.js +36 -0
  621. package/dist-server/server/modules/websocket/services/websocket-auth.service.js.map +1 -0
  622. package/dist-server/server/modules/websocket/services/websocket-server.service.js +90 -0
  623. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -0
  624. package/dist-server/server/modules/websocket/services/websocket-state.service.js +14 -0
  625. package/dist-server/server/modules/websocket/services/websocket-state.service.js.map +1 -0
  626. package/dist-server/server/modules/websocket/services/websocket-writer.service.js +32 -0
  627. package/dist-server/server/modules/websocket/services/websocket-writer.service.js.map +1 -0
  628. package/dist-server/server/modules/websocket/tests/chat-attachment-filter.test.js +40 -0
  629. package/dist-server/server/modules/websocket/tests/chat-attachment-filter.test.js.map +1 -0
  630. package/dist-server/server/modules/websocket/tests/chat-edit-send.test.js +263 -0
  631. package/dist-server/server/modules/websocket/tests/chat-edit-send.test.js.map +1 -0
  632. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +275 -0
  633. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -0
  634. package/dist-server/server/modules/websocket/tests/session-upsert-broadcast.test.js +106 -0
  635. package/dist-server/server/modules/websocket/tests/session-upsert-broadcast.test.js.map +1 -0
  636. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +177 -0
  637. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -0
  638. package/dist-server/server/modules/websocket/tests/websocket-heartbeat.service.test.js +61 -0
  639. package/dist-server/server/modules/websocket/tests/websocket-heartbeat.service.test.js.map +1 -0
  640. package/dist-server/server/modules/worktrees/index.js +3 -0
  641. package/dist-server/server/modules/worktrees/index.js.map +1 -0
  642. package/dist-server/server/modules/worktrees/services/worktree-create-and-open.service.js +37 -0
  643. package/dist-server/server/modules/worktrees/services/worktree-create-and-open.service.js.map +1 -0
  644. package/dist-server/server/modules/worktrees/services/worktree-create.service.js +67 -0
  645. package/dist-server/server/modules/worktrees/services/worktree-create.service.js.map +1 -0
  646. package/dist-server/server/modules/worktrees/services/worktree-git.service.js +172 -0
  647. package/dist-server/server/modules/worktrees/services/worktree-git.service.js.map +1 -0
  648. package/dist-server/server/modules/worktrees/services/worktree-list.service.js +91 -0
  649. package/dist-server/server/modules/worktrees/services/worktree-list.service.js.map +1 -0
  650. package/dist-server/server/modules/worktrees/services/worktree-merge.service.js +118 -0
  651. package/dist-server/server/modules/worktrees/services/worktree-merge.service.js.map +1 -0
  652. package/dist-server/server/modules/worktrees/services/worktree-open.service.js +58 -0
  653. package/dist-server/server/modules/worktrees/services/worktree-open.service.js.map +1 -0
  654. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js +65 -0
  655. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js.map +1 -0
  656. package/dist-server/server/modules/worktrees/tests/worktree-create-and-open.service.test.js +58 -0
  657. package/dist-server/server/modules/worktrees/tests/worktree-create-and-open.service.test.js.map +1 -0
  658. package/dist-server/server/modules/worktrees/tests/worktree-create.service.test.js +85 -0
  659. package/dist-server/server/modules/worktrees/tests/worktree-create.service.test.js.map +1 -0
  660. package/dist-server/server/modules/worktrees/tests/worktree-git.service.test.js +58 -0
  661. package/dist-server/server/modules/worktrees/tests/worktree-git.service.test.js.map +1 -0
  662. package/dist-server/server/modules/worktrees/tests/worktree-list.service.test.js +34 -0
  663. package/dist-server/server/modules/worktrees/tests/worktree-list.service.test.js.map +1 -0
  664. package/dist-server/server/modules/worktrees/tests/worktree-merge.service.test.js +137 -0
  665. package/dist-server/server/modules/worktrees/tests/worktree-merge.service.test.js.map +1 -0
  666. package/dist-server/server/modules/worktrees/tests/worktree-open.service.test.js +99 -0
  667. package/dist-server/server/modules/worktrees/tests/worktree-open.service.test.js.map +1 -0
  668. package/dist-server/server/modules/worktrees/tests/worktree-remove.service.test.js +157 -0
  669. package/dist-server/server/modules/worktrees/tests/worktree-remove.service.test.js.map +1 -0
  670. package/dist-server/server/modules/worktrees/tests/worktrees.routes.test.js +167 -0
  671. package/dist-server/server/modules/worktrees/tests/worktrees.routes.test.js.map +1 -0
  672. package/dist-server/server/modules/worktrees/worktrees.module.js +97 -0
  673. package/dist-server/server/modules/worktrees/worktrees.module.js.map +1 -0
  674. package/dist-server/server/modules/worktrees/worktrees.routes.js +84 -0
  675. package/dist-server/server/modules/worktrees/worktrees.routes.js.map +1 -0
  676. package/dist-server/server/piecemaker/activation/claude-mcp.cjs +109 -0
  677. package/dist-server/server/piecemaker/activation/claude-mcp.cjs.map +1 -0
  678. package/dist-server/server/piecemaker/activation/claude-plugins.cjs +60 -0
  679. package/dist-server/server/piecemaker/activation/claude-plugins.cjs.map +1 -0
  680. package/dist-server/server/piecemaker/activation/codex-mcp.cjs +93 -0
  681. package/dist-server/server/piecemaker/activation/codex-mcp.cjs.map +1 -0
  682. package/dist-server/server/piecemaker/activation/errors.cjs +14 -0
  683. package/dist-server/server/piecemaker/activation/errors.cjs.map +1 -0
  684. package/dist-server/server/piecemaker/activation/library.cjs +281 -0
  685. package/dist-server/server/piecemaker/activation/library.cjs.map +1 -0
  686. package/dist-server/server/piecemaker/activation/library.test.js +281 -0
  687. package/dist-server/server/piecemaker/activation/library.test.js.map +1 -0
  688. package/dist-server/server/piecemaker/activation/markdown.cjs +103 -0
  689. package/dist-server/server/piecemaker/activation/markdown.cjs.map +1 -0
  690. package/dist-server/server/piecemaker/activation/paths.cjs +103 -0
  691. package/dist-server/server/piecemaker/activation/paths.cjs.map +1 -0
  692. package/dist-server/server/piecemaker/activation/paths.test.js +91 -0
  693. package/dist-server/server/piecemaker/activation/paths.test.js.map +1 -0
  694. package/dist-server/server/piecemaker/activation/routes.cjs +100 -0
  695. package/dist-server/server/piecemaker/activation/routes.cjs.map +1 -0
  696. package/dist-server/server/piecemaker/activation/routes.test.js +307 -0
  697. package/dist-server/server/piecemaker/activation/routes.test.js.map +1 -0
  698. package/dist-server/server/piecemaker/activation/snapshot.cjs +28 -0
  699. package/dist-server/server/piecemaker/activation/snapshot.cjs.map +1 -0
  700. package/dist-server/server/piecemaker/anonymizer/anonymizer.test.js +282 -0
  701. package/dist-server/server/piecemaker/anonymizer/anonymizer.test.js.map +1 -0
  702. package/dist-server/server/piecemaker/anonymizer/client-config.cjs +224 -0
  703. package/dist-server/server/piecemaker/anonymizer/client-config.cjs.map +1 -0
  704. package/dist-server/server/piecemaker/anonymizer/codex-http.test.js +19 -0
  705. package/dist-server/server/piecemaker/anonymizer/codex-http.test.js.map +1 -0
  706. package/dist-server/server/piecemaker/anonymizer/dictionary.cjs +163 -0
  707. package/dist-server/server/piecemaker/anonymizer/dictionary.cjs.map +1 -0
  708. package/dist-server/server/piecemaker/anonymizer/lifecycle.js +20 -0
  709. package/dist-server/server/piecemaker/anonymizer/lifecycle.js.map +1 -0
  710. package/dist-server/server/piecemaker/anonymizer/lifecycle.test.js +35 -0
  711. package/dist-server/server/piecemaker/anonymizer/lifecycle.test.js.map +1 -0
  712. package/dist-server/server/piecemaker/anonymizer/providers.cjs +236 -0
  713. package/dist-server/server/piecemaker/anonymizer/providers.cjs.map +1 -0
  714. package/dist-server/server/piecemaker/anonymizer/proxy.cjs +338 -0
  715. package/dist-server/server/piecemaker/anonymizer/proxy.cjs.map +1 -0
  716. package/dist-server/server/piecemaker/anonymizer/rewrite.cjs +249 -0
  717. package/dist-server/server/piecemaker/anonymizer/rewrite.cjs.map +1 -0
  718. package/dist-server/server/piecemaker/anonymizer/service.cjs +217 -0
  719. package/dist-server/server/piecemaker/anonymizer/service.cjs.map +1 -0
  720. package/dist-server/server/piecemaker/harness/chat-harness.js +157 -0
  721. package/dist-server/server/piecemaker/harness/chat-harness.js.map +1 -0
  722. package/dist-server/server/piecemaker/harness/chat-harness.test.js +120 -0
  723. package/dist-server/server/piecemaker/harness/chat-harness.test.js.map +1 -0
  724. package/dist-server/server/piecemaker/harness/citation-instructions.js +17 -0
  725. package/dist-server/server/piecemaker/harness/citation-instructions.js.map +1 -0
  726. package/dist-server/server/piecemaker/harness/citation-store.js +72 -0
  727. package/dist-server/server/piecemaker/harness/citation-store.js.map +1 -0
  728. package/dist-server/server/piecemaker/harness/citation-turn.js +211 -0
  729. package/dist-server/server/piecemaker/harness/citation-turn.js.map +1 -0
  730. package/dist-server/server/piecemaker/harness/citation-turn.test.js +144 -0
  731. package/dist-server/server/piecemaker/harness/citation-turn.test.js.map +1 -0
  732. package/dist-server/server/piecemaker/harness/citations.routes.js +16 -0
  733. package/dist-server/server/piecemaker/harness/citations.routes.js.map +1 -0
  734. package/dist-server/server/piecemaker/harness/citations.routes.test.js +68 -0
  735. package/dist-server/server/piecemaker/harness/citations.routes.test.js.map +1 -0
  736. package/dist-server/server/piecemaker/harness/decisions.cjs +298 -0
  737. package/dist-server/server/piecemaker/harness/decisions.cjs.map +1 -0
  738. package/dist-server/server/piecemaker/harness/flux-sse.cjs +108 -0
  739. package/dist-server/server/piecemaker/harness/flux-sse.cjs.map +1 -0
  740. package/dist-server/server/piecemaker/harness/harness.test.js +259 -0
  741. package/dist-server/server/piecemaker/harness/harness.test.js.map +1 -0
  742. package/dist-server/server/piecemaker/harness/index.cjs +100 -0
  743. package/dist-server/server/piecemaker/harness/index.cjs.map +1 -0
  744. package/dist-server/server/piecemaker/harness/proxy-harness.test.js +199 -0
  745. package/dist-server/server/piecemaker/harness/proxy-harness.test.js.map +1 -0
  746. package/dist-server/server/piecemaker/harness/source-passages.js +19 -0
  747. package/dist-server/server/piecemaker/harness/source-passages.js.map +1 -0
  748. package/dist-server/server/piecemaker/harness/verification.cjs +152 -0
  749. package/dist-server/server/piecemaker/harness/verification.cjs.map +1 -0
  750. package/dist-server/server/piecemaker/index.js +46 -0
  751. package/dist-server/server/piecemaker/index.js.map +1 -0
  752. package/dist-server/server/piecemaker/library/index.js +66 -0
  753. package/dist-server/server/piecemaker/library/index.js.map +1 -0
  754. package/dist-server/server/piecemaker/library/marketplace.js +204 -0
  755. package/dist-server/server/piecemaker/library/marketplace.js.map +1 -0
  756. package/dist-server/server/piecemaker/library/migrate-cli.js +13 -0
  757. package/dist-server/server/piecemaker/library/migrate-cli.js.map +1 -0
  758. package/dist-server/server/piecemaker/library/migrate.js +53 -0
  759. package/dist-server/server/piecemaker/library/migrate.js.map +1 -0
  760. package/dist-server/server/piecemaker/library/provider-skills.js +40 -0
  761. package/dist-server/server/piecemaker/library/provider-skills.js.map +1 -0
  762. package/dist-server/server/piecemaker/library/provider-skills.test.js +55 -0
  763. package/dist-server/server/piecemaker/library/provider-skills.test.js.map +1 -0
  764. package/dist-server/server/piecemaker/library/routes.js +56 -0
  765. package/dist-server/server/piecemaker/library/routes.js.map +1 -0
  766. package/dist-server/server/piecemaker/library/runtime.js +34 -0
  767. package/dist-server/server/piecemaker/library/runtime.js.map +1 -0
  768. package/dist-server/server/piecemaker/library/store.js +440 -0
  769. package/dist-server/server/piecemaker/library/store.js.map +1 -0
  770. package/dist-server/server/piecemaker/library/store.test.js +265 -0
  771. package/dist-server/server/piecemaker/library/store.test.js.map +1 -0
  772. package/dist-server/server/piecemaker/library/workspace-installation.js +70 -0
  773. package/dist-server/server/piecemaker/library/workspace-installation.js.map +1 -0
  774. package/dist-server/server/piecemaker/originals-cache.cjs +45 -0
  775. package/dist-server/server/piecemaker/originals-cache.cjs.map +1 -0
  776. package/dist-server/server/piecemaker/originals-cache.test.js +68 -0
  777. package/dist-server/server/piecemaker/originals-cache.test.js.map +1 -0
  778. package/dist-server/server/piecemaker/protection/bypass.cjs +66 -0
  779. package/dist-server/server/piecemaker/protection/bypass.cjs.map +1 -0
  780. package/dist-server/server/piecemaker/protection/bypass.test.js +117 -0
  781. package/dist-server/server/piecemaker/protection/bypass.test.js.map +1 -0
  782. package/dist-server/server/piecemaker/protection/routes.cjs +38 -0
  783. package/dist-server/server/piecemaker/protection/routes.cjs.map +1 -0
  784. package/dist-server/server/piecemaker/timesheet/index.js +9 -0
  785. package/dist-server/server/piecemaker/timesheet/index.js.map +1 -0
  786. package/dist-server/server/piecemaker/timesheet/routes.js +42 -0
  787. package/dist-server/server/piecemaker/timesheet/routes.js.map +1 -0
  788. package/dist-server/server/piecemaker/timesheet/service.js +241 -0
  789. package/dist-server/server/piecemaker/timesheet/service.js.map +1 -0
  790. package/dist-server/server/piecemaker/timesheet/service.test.js +124 -0
  791. package/dist-server/server/piecemaker/timesheet/service.test.js.map +1 -0
  792. package/dist-server/server/piecemaker/timesheet/store.js +126 -0
  793. package/dist-server/server/piecemaker/timesheet/store.js.map +1 -0
  794. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/anonymization-state.cjs +147 -0
  795. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/anonymization-state.cjs.map +1 -0
  796. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folder-structure.cjs +285 -0
  797. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folder-structure.cjs.map +1 -0
  798. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folders.cjs +87 -0
  799. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folders.cjs.map +1 -0
  800. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/central-mapping.cjs +0 -0
  801. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/central-mapping.cjs.map +1 -0
  802. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/citation-sources.cjs +526 -0
  803. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/citation-sources.cjs.map +1 -0
  804. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/citations.cjs +304 -0
  805. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/citations.cjs.map +1 -0
  806. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/commits.cjs +1660 -0
  807. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/commits.cjs.map +1 -0
  808. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/institutional-terms.cjs +152 -0
  809. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/institutional-terms.cjs.map +1 -0
  810. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/legifrance-reads.cjs +84 -0
  811. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/legifrance-reads.cjs.map +1 -0
  812. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.cjs +332 -0
  813. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.cjs.map +1 -0
  814. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.test.js +64 -0
  815. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.test.js.map +1 -0
  816. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/protection.cjs +420 -0
  817. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/protection.cjs.map +1 -0
  818. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/session-timing.cjs +91 -0
  819. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/session-timing.cjs.map +1 -0
  820. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/substitution.cjs +304 -0
  821. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/substitution.cjs.map +1 -0
  822. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/verify-citations.cjs +293 -0
  823. package/dist-server/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/verify-citations.cjs.map +1 -0
  824. package/dist-server/server/piecemaker/vendor/websocket-server/case-folder-structure.cjs +5 -0
  825. package/dist-server/server/piecemaker/vendor/websocket-server/case-folder-structure.cjs.map +1 -0
  826. package/dist-server/server/piecemaker/vendor/websocket-server/legal-forms.cjs +91 -0
  827. package/dist-server/server/piecemaker/vendor/websocket-server/legal-forms.cjs.map +1 -0
  828. package/dist-server/server/piecemaker/vendor/websocket-server/legal-forms.test.js +11 -0
  829. package/dist-server/server/piecemaker/vendor/websocket-server/legal-forms.test.js.map +1 -0
  830. package/dist-server/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs +955 -0
  831. package/dist-server/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs.map +1 -0
  832. package/dist-server/server/shared/claude-cli-path.js +120 -0
  833. package/dist-server/server/shared/claude-cli-path.js.map +1 -0
  834. package/dist-server/server/shared/frontmatter.js +16 -0
  835. package/dist-server/server/shared/frontmatter.js.map +1 -0
  836. package/dist-server/server/shared/image-attachments.js +344 -0
  837. package/dist-server/server/shared/image-attachments.js.map +1 -0
  838. package/dist-server/server/shared/interfaces.js +2 -0
  839. package/dist-server/server/shared/interfaces.js.map +1 -0
  840. package/dist-server/server/shared/message-unification.js +376 -0
  841. package/dist-server/server/shared/message-unification.js.map +1 -0
  842. package/dist-server/server/shared/tests/application-data-root.test.js +33 -0
  843. package/dist-server/server/shared/tests/application-data-root.test.js.map +1 -0
  844. package/dist-server/server/shared/tests/claude-cli-path.test.js +89 -0
  845. package/dist-server/server/shared/tests/claude-cli-path.test.js.map +1 -0
  846. package/dist-server/server/shared/tests/image-attachments.test.js +262 -0
  847. package/dist-server/server/shared/tests/image-attachments.test.js.map +1 -0
  848. package/dist-server/server/shared/tests/message-unification.test.js +174 -0
  849. package/dist-server/server/shared/tests/message-unification.test.js.map +1 -0
  850. package/dist-server/server/shared/tests/slice-tail-page.test.js +35 -0
  851. package/dist-server/server/shared/tests/slice-tail-page.test.js.map +1 -0
  852. package/dist-server/server/shared/types.js +2 -0
  853. package/dist-server/server/shared/types.js.map +1 -0
  854. package/dist-server/server/shared/utils.js +1010 -0
  855. package/dist-server/server/shared/utils.js.map +1 -0
  856. package/dist-server/shared/networkHosts.js +20 -0
  857. package/dist-server/shared/networkHosts.js.map +1 -0
  858. package/dist-server/shared/product-config.mjs +79 -0
  859. package/dist-server/shared/product-config.mjs.map +1 -0
  860. package/package.json +271 -0
  861. package/product.config.json +17 -0
  862. package/public/api-docs.html +901 -0
  863. package/scripts/fix-node-pty.js +67 -0
  864. package/scripts/piecemaker/cli/install-command.mjs +130 -0
  865. package/scripts/piecemaker/cli/lib/composants.mjs +68 -0
  866. package/scripts/piecemaker/cli/lib/config.mjs +32 -0
  867. package/scripts/piecemaker/cli/lib/exec.mjs +79 -0
  868. package/scripts/piecemaker/cli/lib/node-runtime.mjs +76 -0
  869. package/scripts/piecemaker/cli/lib/ports.mjs +96 -0
  870. package/scripts/piecemaker/cli/lib/pwa.mjs +323 -0
  871. package/scripts/piecemaker/cli/lib/repos.mjs +140 -0
  872. package/scripts/piecemaker/cli/lib/services.mjs +71 -0
  873. package/scripts/piecemaker/cli/lib/ui.mjs +41 -0
  874. package/scripts/piecemaker/cli/piecemaker.mjs +159 -0
  875. package/scripts/piecemaker/cli/piecemaker.ps1 +63 -0
  876. package/scripts/piecemaker/cli/piecemaker.sh +60 -0
  877. package/scripts/piecemaker/generate-i18n-overrides.mjs +219 -0
  878. package/scripts/piecemaker/hooks/proxy-guard.mjs +286 -0
  879. package/scripts/promote-dist-server.mjs +50 -0
  880. package/scripts/release/build-server-bundle.js +178 -0
  881. package/scripts/release/package-piecemaker.sh +73 -0
  882. package/scripts/release/prepare-desktop-app.js +168 -0
  883. package/server/index.ts +410 -0
  884. package/server/load-env.ts +48 -0
  885. package/server/modules/agent/agent.module.ts +52 -0
  886. package/server/modules/agent/agent.routes.ts +1287 -0
  887. package/server/modules/agent/index.ts +2 -0
  888. package/server/modules/agent/tests/agent.routes.test.ts +205 -0
  889. package/server/modules/assets/assets.routes.ts +150 -0
  890. package/server/modules/assets/index.ts +3 -0
  891. package/server/modules/assets/services/image-assets.service.ts +127 -0
  892. package/server/modules/assets/tests/image-assets.service.test.ts +74 -0
  893. package/server/modules/auth/auth.middleware.ts +163 -0
  894. package/server/modules/auth/auth.module.ts +38 -0
  895. package/server/modules/auth/auth.routes.ts +57 -0
  896. package/server/modules/auth/auth.service.ts +155 -0
  897. package/server/modules/auth/index.ts +9 -0
  898. package/server/modules/auth/tests/auth.service.test.ts +95 -0
  899. package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -0
  900. package/server/modules/browser-use/browser-use-mcp.ts +386 -0
  901. package/server/modules/browser-use/browser-use-runtime.ts +10 -0
  902. package/server/modules/browser-use/browser-use.routes.ts +96 -0
  903. package/server/modules/browser-use/browser-use.service.ts +835 -0
  904. package/server/modules/browser-use/index.ts +11 -0
  905. package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -0
  906. package/server/modules/cli/cli.module.ts +110 -0
  907. package/server/modules/cli/cli.service.ts +266 -0
  908. package/server/modules/cli/cli.ts +19 -0
  909. package/server/modules/cli/index.ts +2 -0
  910. package/server/modules/cli/pwa-launcher.ts +131 -0
  911. package/server/modules/cli/sandbox.service.ts +413 -0
  912. package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +186 -0
  913. package/server/modules/cli/tests/cli.service.test.ts +107 -0
  914. package/server/modules/cli/tests/sandbox.service.test.ts +61 -0
  915. package/server/modules/commands/commands.module.ts +22 -0
  916. package/server/modules/commands/commands.routes.ts +605 -0
  917. package/server/modules/commands/index.ts +2 -0
  918. package/server/modules/commands/tests/commands.test.ts +114 -0
  919. package/server/modules/database/connection.ts +144 -0
  920. package/server/modules/database/index.ts +27 -0
  921. package/server/modules/database/init-db.ts +17 -0
  922. package/server/modules/database/migrations.ts +552 -0
  923. package/server/modules/database/repositories/api-keys.ts +119 -0
  924. package/server/modules/database/repositories/app-config.ts +53 -0
  925. package/server/modules/database/repositories/credentials.ts +106 -0
  926. package/server/modules/database/repositories/github-tokens.ts +100 -0
  927. package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -0
  928. package/server/modules/database/repositories/notification-preferences.ts +117 -0
  929. package/server/modules/database/repositories/projects.db.ts +196 -0
  930. package/server/modules/database/repositories/provider-models.ts +168 -0
  931. package/server/modules/database/repositories/push-subscriptions.ts +80 -0
  932. package/server/modules/database/repositories/scan-state.db.ts +42 -0
  933. package/server/modules/database/repositories/scheduled-messages.db.ts +127 -0
  934. package/server/modules/database/repositories/session-drafts.db.ts +171 -0
  935. package/server/modules/database/repositories/sessions.db.ts +714 -0
  936. package/server/modules/database/repositories/user-preferences.db.ts +80 -0
  937. package/server/modules/database/repositories/users.ts +140 -0
  938. package/server/modules/database/repositories/vapid-keys.ts +57 -0
  939. package/server/modules/database/schema.ts +306 -0
  940. package/server/modules/database/tests/projects.db.integration.test.ts +72 -0
  941. package/server/modules/database/tests/provider-models.db.integration.test.ts +125 -0
  942. package/server/modules/database/tests/sessions-provider-mapping.test.ts +109 -0
  943. package/server/modules/database/tests/sessions.db.integration.test.ts +116 -0
  944. package/server/modules/database/tests/user-preferences.db.integration.test.ts +135 -0
  945. package/server/modules/file-tree/file-tree.module.ts +116 -0
  946. package/server/modules/file-tree/file-tree.routes.ts +258 -0
  947. package/server/modules/file-tree/file-tree.service.ts +675 -0
  948. package/server/modules/file-tree/index.ts +2 -0
  949. package/server/modules/file-tree/tests/file-tree.routes.test.ts +157 -0
  950. package/server/modules/file-tree/tests/file-tree.service.test.ts +371 -0
  951. package/server/modules/git/git-branch.service.ts +43 -0
  952. package/server/modules/git/git-parsing.service.ts +66 -0
  953. package/server/modules/git/git.module.ts +22 -0
  954. package/server/modules/git/git.routes.ts +1600 -0
  955. package/server/modules/git/index.ts +2 -0
  956. package/server/modules/git/tests/git-branch.service.test.ts +60 -0
  957. package/server/modules/git/tests/git-init.routes.test.ts +135 -0
  958. package/server/modules/git/tests/git.test.ts +106 -0
  959. package/server/modules/notifications/index.ts +24 -0
  960. package/server/modules/notifications/notifications.routes.ts +127 -0
  961. package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -0
  962. package/server/modules/notifications/services/notification-orchestrator.service.js +310 -0
  963. package/server/modules/notifications/tests/notification-orchestrator.integration.test.ts +55 -0
  964. package/server/modules/notifications/vapid-keys.service.ts +38 -0
  965. package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -0
  966. package/server/modules/plugins/index.ts +9 -0
  967. package/server/modules/plugins/plugin-process.service.ts +217 -0
  968. package/server/modules/plugins/plugin-registry.service.ts +461 -0
  969. package/server/modules/plugins/plugins.module.ts +33 -0
  970. package/server/modules/plugins/plugins.routes.ts +66 -0
  971. package/server/modules/plugins/plugins.service.ts +147 -0
  972. package/server/modules/plugins/tests/plugins.service.test.ts +32 -0
  973. package/server/modules/projects/index.ts +11 -0
  974. package/server/modules/projects/projects.routes.ts +273 -0
  975. package/server/modules/projects/services/project-clone.service.ts +323 -0
  976. package/server/modules/projects/services/project-delete.service.ts +102 -0
  977. package/server/modules/projects/services/project-management.service.ts +144 -0
  978. package/server/modules/projects/services/project-star.service.ts +78 -0
  979. package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -0
  980. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +314 -0
  981. package/server/modules/projects/tests/project-clone.service.test.ts +183 -0
  982. package/server/modules/projects/tests/project-management.service.test.ts +117 -0
  983. package/server/modules/projects/tests/project-star.service.test.ts +123 -0
  984. package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -0
  985. package/server/modules/providers/README.md +380 -0
  986. package/server/modules/providers/index.ts +14 -0
  987. package/server/modules/providers/list/claude/claude-auth.provider.ts +180 -0
  988. package/server/modules/providers/list/claude/claude-fork.provider.ts +57 -0
  989. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -0
  990. package/server/modules/providers/list/claude/claude-models.provider.ts +314 -0
  991. package/server/modules/providers/list/claude/claude-runtime.provider.js +1217 -0
  992. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +203 -0
  993. package/server/modules/providers/list/claude/claude-sessions.provider.ts +1108 -0
  994. package/server/modules/providers/list/claude/claude-skills.provider.ts +265 -0
  995. package/server/modules/providers/list/claude/claude.provider.ts +33 -0
  996. package/server/modules/providers/list/codex/codex-app-server.client.ts +243 -0
  997. package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -0
  998. package/server/modules/providers/list/codex/codex-fork.provider.ts +40 -0
  999. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -0
  1000. package/server/modules/providers/list/codex/codex-models.provider.ts +123 -0
  1001. package/server/modules/providers/list/codex/codex-runtime.provider.js +572 -0
  1002. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +212 -0
  1003. package/server/modules/providers/list/codex/codex-sessions.provider.ts +2267 -0
  1004. package/server/modules/providers/list/codex/codex-skills.provider.ts +73 -0
  1005. package/server/modules/providers/list/codex/codex.provider.ts +33 -0
  1006. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -0
  1007. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -0
  1008. package/server/modules/providers/list/cursor/cursor-models.provider.ts +119 -0
  1009. package/server/modules/providers/list/cursor/cursor-runtime.provider.js +387 -0
  1010. package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +158 -0
  1011. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +654 -0
  1012. package/server/modules/providers/list/cursor/cursor-skills.provider.ts +39 -0
  1013. package/server/modules/providers/list/cursor/cursor.provider.ts +30 -0
  1014. package/server/modules/providers/list/mistral/mistral-auth.provider.ts +181 -0
  1015. package/server/modules/providers/list/mistral/mistral-mcp.provider.ts +20 -0
  1016. package/server/modules/providers/list/mistral/mistral-models.provider.ts +76 -0
  1017. package/server/modules/providers/list/mistral/mistral-runtime.provider.ts +417 -0
  1018. package/server/modules/providers/list/mistral/mistral-session-synchronizer.provider.ts +15 -0
  1019. package/server/modules/providers/list/mistral/mistral-sessions.provider.ts +210 -0
  1020. package/server/modules/providers/list/mistral/mistral-skills.provider.ts +20 -0
  1021. package/server/modules/providers/list/mistral/mistral.provider.ts +35 -0
  1022. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +110 -0
  1023. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -0
  1024. package/server/modules/providers/list/opencode/opencode-models.provider.ts +304 -0
  1025. package/server/modules/providers/list/opencode/opencode-runtime.provider.js +434 -0
  1026. package/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +261 -0
  1027. package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +179 -0
  1028. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +500 -0
  1029. package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -0
  1030. package/server/modules/providers/list/opencode/opencode.provider.ts +30 -0
  1031. package/server/modules/providers/provider.registry.ts +38 -0
  1032. package/server/modules/providers/provider.routes.ts +909 -0
  1033. package/server/modules/providers/services/mcp.service.ts +109 -0
  1034. package/server/modules/providers/services/provider-auth.service.ts +26 -0
  1035. package/server/modules/providers/services/provider-capabilities.service.ts +133 -0
  1036. package/server/modules/providers/services/provider-models.service.ts +401 -0
  1037. package/server/modules/providers/services/provider-runtime.service.ts +108 -0
  1038. package/server/modules/providers/services/provider-token-usage.service.ts +484 -0
  1039. package/server/modules/providers/services/session-conversations-search.service.ts +1321 -0
  1040. package/server/modules/providers/services/session-history-cache.service.ts +139 -0
  1041. package/server/modules/providers/services/session-synchronizer.service.ts +162 -0
  1042. package/server/modules/providers/services/sessions-watcher.service.ts +266 -0
  1043. package/server/modules/providers/services/sessions.service.ts +663 -0
  1044. package/server/modules/providers/services/skills.service.ts +39 -0
  1045. package/server/modules/providers/shared/base/abstract.provider.ts +32 -0
  1046. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -0
  1047. package/server/modules/providers/shared/skills/skills.provider.ts +287 -0
  1048. package/server/modules/providers/tests/claude-auth.test.ts +208 -0
  1049. package/server/modules/providers/tests/claude-sessions.test.ts +573 -0
  1050. package/server/modules/providers/tests/claude-subagent-echo.test.ts +25 -0
  1051. package/server/modules/providers/tests/claude-token-budget.test.ts +104 -0
  1052. package/server/modules/providers/tests/codex-message-editing.test.ts +419 -0
  1053. package/server/modules/providers/tests/codex-session-fork.test.ts +59 -0
  1054. package/server/modules/providers/tests/codex-sessions.test.ts +553 -0
  1055. package/server/modules/providers/tests/mcp.test.ts +349 -0
  1056. package/server/modules/providers/tests/opencode-models.test.ts +154 -0
  1057. package/server/modules/providers/tests/opencode-sessions.test.ts +522 -0
  1058. package/server/modules/providers/tests/provider-attachment-history.test.ts +247 -0
  1059. package/server/modules/providers/tests/provider-models.service.test.ts +353 -0
  1060. package/server/modules/providers/tests/provider-runtime.service.test.ts +138 -0
  1061. package/server/modules/providers/tests/provider-token-usage.service.test.ts +373 -0
  1062. package/server/modules/providers/tests/provider.routes.test.ts +244 -0
  1063. package/server/modules/providers/tests/session-fork.test.ts +173 -0
  1064. package/server/modules/providers/tests/session-history-cache.service.test.ts +143 -0
  1065. package/server/modules/providers/tests/session-orphan-prune.test.ts +107 -0
  1066. package/server/modules/providers/tests/session-synchronizer-coalescing.test.ts +136 -0
  1067. package/server/modules/providers/tests/sessions-details.test.ts +73 -0
  1068. package/server/modules/providers/tests/sessions.service.test.ts +193 -0
  1069. package/server/modules/providers/tests/skills.test.ts +692 -0
  1070. package/server/modules/scheduled-messages/index.ts +8 -0
  1071. package/server/modules/scheduled-messages/scheduled-messages.routes.ts +68 -0
  1072. package/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.ts +203 -0
  1073. package/server/modules/scheduled-messages/services/scheduled-messages.service.ts +121 -0
  1074. package/server/modules/scheduled-messages/tests/scheduled-messages.test.ts +310 -0
  1075. package/server/modules/settings/index.ts +2 -0
  1076. package/server/modules/settings/settings.module.ts +50 -0
  1077. package/server/modules/settings/settings.routes.ts +51 -0
  1078. package/server/modules/settings/settings.service.ts +186 -0
  1079. package/server/modules/settings/tests/settings.service.test.ts +54 -0
  1080. package/server/modules/system/index.ts +2 -0
  1081. package/server/modules/system/system.module.ts +62 -0
  1082. package/server/modules/system/system.routes.ts +21 -0
  1083. package/server/modules/system/system.service.ts +76 -0
  1084. package/server/modules/system/tests/system.service.test.ts +118 -0
  1085. package/server/modules/taskmaster/index.ts +2 -0
  1086. package/server/modules/taskmaster/taskmaster.module.ts +24 -0
  1087. package/server/modules/taskmaster/taskmaster.routes.ts +1472 -0
  1088. package/server/modules/taskmaster/taskmaster.service.ts +132 -0
  1089. package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +201 -0
  1090. package/server/modules/taskmaster/tests/taskmaster.service.test.ts +97 -0
  1091. package/server/modules/user/index.ts +2 -0
  1092. package/server/modules/user/tests/user.service.test.ts +151 -0
  1093. package/server/modules/user/user.module.ts +67 -0
  1094. package/server/modules/user/user.routes.ts +94 -0
  1095. package/server/modules/user/user.service.ts +190 -0
  1096. package/server/modules/voice/index.ts +2 -0
  1097. package/server/modules/voice/tests/voice.service.test.ts +99 -0
  1098. package/server/modules/voice/voice.module.ts +47 -0
  1099. package/server/modules/voice/voice.routes.ts +113 -0
  1100. package/server/modules/voice/voice.service.ts +192 -0
  1101. package/server/modules/websocket/README.md +273 -0
  1102. package/server/modules/websocket/index.ts +11 -0
  1103. package/server/modules/websocket/services/chat-run-registry.service.ts +310 -0
  1104. package/server/modules/websocket/services/chat-session-writer.service.ts +175 -0
  1105. package/server/modules/websocket/services/chat-websocket.service.ts +654 -0
  1106. package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -0
  1107. package/server/modules/websocket/services/session-upsert-broadcast.service.ts +108 -0
  1108. package/server/modules/websocket/services/shell-websocket.service.ts +628 -0
  1109. package/server/modules/websocket/services/websocket-auth.service.ts +59 -0
  1110. package/server/modules/websocket/services/websocket-server.service.ts +126 -0
  1111. package/server/modules/websocket/services/websocket-state.service.ts +16 -0
  1112. package/server/modules/websocket/services/websocket-writer.service.ts +38 -0
  1113. package/server/modules/websocket/tests/chat-attachment-filter.test.ts +59 -0
  1114. package/server/modules/websocket/tests/chat-edit-send.test.ts +309 -0
  1115. package/server/modules/websocket/tests/chat-run-registry.test.ts +313 -0
  1116. package/server/modules/websocket/tests/session-upsert-broadcast.test.ts +138 -0
  1117. package/server/modules/websocket/tests/shell-websocket.service.test.ts +227 -0
  1118. package/server/modules/websocket/tests/websocket-heartbeat.service.test.ts +78 -0
  1119. package/server/modules/worktrees/index.ts +2 -0
  1120. package/server/modules/worktrees/services/worktree-create-and-open.service.ts +53 -0
  1121. package/server/modules/worktrees/services/worktree-create.service.ts +104 -0
  1122. package/server/modules/worktrees/services/worktree-git.service.ts +207 -0
  1123. package/server/modules/worktrees/services/worktree-list.service.ts +143 -0
  1124. package/server/modules/worktrees/services/worktree-merge.service.ts +157 -0
  1125. package/server/modules/worktrees/services/worktree-open.service.ts +85 -0
  1126. package/server/modules/worktrees/services/worktree-remove.service.ts +88 -0
  1127. package/server/modules/worktrees/tests/worktree-create-and-open.service.test.ts +68 -0
  1128. package/server/modules/worktrees/tests/worktree-create.service.test.ts +142 -0
  1129. package/server/modules/worktrees/tests/worktree-git.service.test.ts +84 -0
  1130. package/server/modules/worktrees/tests/worktree-list.service.test.ts +45 -0
  1131. package/server/modules/worktrees/tests/worktree-merge.service.test.ts +213 -0
  1132. package/server/modules/worktrees/tests/worktree-open.service.test.ts +122 -0
  1133. package/server/modules/worktrees/tests/worktree-remove.service.test.ts +227 -0
  1134. package/server/modules/worktrees/tests/worktrees.routes.test.ts +199 -0
  1135. package/server/modules/worktrees/worktrees.module.ts +113 -0
  1136. package/server/modules/worktrees/worktrees.routes.ts +116 -0
  1137. package/server/piecemaker/activation/claude-mcp.cjs +115 -0
  1138. package/server/piecemaker/activation/claude-plugins.cjs +65 -0
  1139. package/server/piecemaker/activation/codex-mcp.cjs +102 -0
  1140. package/server/piecemaker/activation/errors.cjs +15 -0
  1141. package/server/piecemaker/activation/index.cjs +5 -0
  1142. package/server/piecemaker/activation/library.cjs +284 -0
  1143. package/server/piecemaker/activation/library.cjs.bak +223 -0
  1144. package/server/piecemaker/activation/library.test.js +365 -0
  1145. package/server/piecemaker/activation/markdown.cjs +108 -0
  1146. package/server/piecemaker/activation/markdown.cjs.bak +78 -0
  1147. package/server/piecemaker/activation/paths.cjs +104 -0
  1148. package/server/piecemaker/activation/paths.test.js +158 -0
  1149. package/server/piecemaker/activation/routes.cjs +101 -0
  1150. package/server/piecemaker/activation/routes.test.js +344 -0
  1151. package/server/piecemaker/activation/snapshot.cjs +30 -0
  1152. package/server/piecemaker/anonymizer/anonymizer.test.js +320 -0
  1153. package/server/piecemaker/anonymizer/client-config.cjs +228 -0
  1154. package/server/piecemaker/anonymizer/codex-http.test.js +20 -0
  1155. package/server/piecemaker/anonymizer/dictionary.cjs +174 -0
  1156. package/server/piecemaker/anonymizer/lifecycle.test.ts +37 -0
  1157. package/server/piecemaker/anonymizer/lifecycle.ts +22 -0
  1158. package/server/piecemaker/anonymizer/providers.cjs +241 -0
  1159. package/server/piecemaker/anonymizer/proxy.cjs +365 -0
  1160. package/server/piecemaker/anonymizer/rewrite.cjs +251 -0
  1161. package/server/piecemaker/anonymizer/routes.cjs +43 -0
  1162. package/server/piecemaker/anonymizer/service.cjs +218 -0
  1163. package/server/piecemaker/harness/chat-harness.test.ts +131 -0
  1164. package/server/piecemaker/harness/chat-harness.ts +151 -0
  1165. package/server/piecemaker/harness/citation-instructions.ts +18 -0
  1166. package/server/piecemaker/harness/citation-store.ts +80 -0
  1167. package/server/piecemaker/harness/citation-turn.test.ts +155 -0
  1168. package/server/piecemaker/harness/citation-turn.ts +197 -0
  1169. package/server/piecemaker/harness/citations.routes.test.ts +68 -0
  1170. package/server/piecemaker/harness/citations.routes.ts +18 -0
  1171. package/server/piecemaker/harness/decisions.cjs +302 -0
  1172. package/server/piecemaker/harness/flux-sse.cjs +111 -0
  1173. package/server/piecemaker/harness/harness.test.js +296 -0
  1174. package/server/piecemaker/harness/index.cjs +103 -0
  1175. package/server/piecemaker/harness/proxy-harness.test.js +226 -0
  1176. package/server/piecemaker/harness/source-passages.ts +21 -0
  1177. package/server/piecemaker/harness/verification.cjs +159 -0
  1178. package/server/piecemaker/index.ts +59 -0
  1179. package/server/piecemaker/library/index.ts +54 -0
  1180. package/server/piecemaker/library/marketplace.ts +152 -0
  1181. package/server/piecemaker/library/migrate-cli.ts +11 -0
  1182. package/server/piecemaker/library/migrate.ts +49 -0
  1183. package/server/piecemaker/library/policy.cjs +9 -0
  1184. package/server/piecemaker/library/provider-skills.test.ts +61 -0
  1185. package/server/piecemaker/library/provider-skills.ts +48 -0
  1186. package/server/piecemaker/library/routes.ts +38 -0
  1187. package/server/piecemaker/library/runtime.ts +39 -0
  1188. package/server/piecemaker/library/store.test.ts +280 -0
  1189. package/server/piecemaker/library/store.ts +429 -0
  1190. package/server/piecemaker/library/workspace-installation.ts +61 -0
  1191. package/server/piecemaker/originals-cache.cjs +54 -0
  1192. package/server/piecemaker/originals-cache.test.js +77 -0
  1193. package/server/piecemaker/protection/bypass.cjs +73 -0
  1194. package/server/piecemaker/protection/bypass.test.js +140 -0
  1195. package/server/piecemaker/protection/routes.cjs +39 -0
  1196. package/server/piecemaker/router.cjs +109 -0
  1197. package/server/piecemaker/timesheet/index.ts +9 -0
  1198. package/server/piecemaker/timesheet/routes.ts +48 -0
  1199. package/server/piecemaker/timesheet/service.test.ts +142 -0
  1200. package/server/piecemaker/timesheet/service.ts +298 -0
  1201. package/server/piecemaker/timesheet/store.ts +167 -0
  1202. package/server/piecemaker/vendor/.env +2 -0
  1203. package/server/piecemaker/vendor/installer/assets/PieceMakerApp.swift +189 -0
  1204. package/server/piecemaker/vendor/installer/assets/claude-hooks/piecemaker-guard-secrets.mjs +230 -0
  1205. package/server/piecemaker/vendor/installer/assets/claude-hooks/piecemaker-secret-paths.default.json +1 -0
  1206. package/server/piecemaker/vendor/installer/assets/piecemaker.icns +0 -0
  1207. package/server/piecemaker/vendor/installer/assets/piecemaker.ico +0 -0
  1208. package/server/piecemaker/vendor/installer/bin/piecemaker.mjs +1018 -0
  1209. package/server/piecemaker/vendor/installer/lib/banner.mjs +35 -0
  1210. package/server/piecemaker/vendor/installer/lib/codex-skills.mjs +343 -0
  1211. package/server/piecemaker/vendor/installer/lib/commandes.mjs +13 -0
  1212. package/server/piecemaker/vendor/installer/lib/desktop-launcher.mjs +305 -0
  1213. package/server/piecemaker/vendor/installer/lib/legacy-legifrance.mjs +72 -0
  1214. package/server/piecemaker/vendor/installer/lib/platform.mjs +163 -0
  1215. package/server/piecemaker/vendor/installer/lib/prompt.mjs +138 -0
  1216. package/server/piecemaker/vendor/installer/lib/resume-steps.mjs +174 -0
  1217. package/server/piecemaker/vendor/installer/lib/secrets-guard.mjs +193 -0
  1218. package/server/piecemaker/vendor/installer/lib/service.mjs +467 -0
  1219. package/server/piecemaker/vendor/installer/lib/state.mjs +114 -0
  1220. package/server/piecemaker/vendor/installer/lib/ui.mjs +159 -0
  1221. package/server/piecemaker/vendor/installer/steps/00-identite.mjs +71 -0
  1222. package/server/piecemaker/vendor/installer/steps/01-prerequis.mjs +119 -0
  1223. package/server/piecemaker/vendor/installer/steps/02-dependances-node.mjs +127 -0
  1224. package/server/piecemaker/vendor/installer/steps/03-python-gliner.mjs +249 -0
  1225. package/server/piecemaker/vendor/installer/steps/03b-python-graphify.mjs +161 -0
  1226. package/server/piecemaker/vendor/installer/steps/04-conversion-md.mjs +147 -0
  1227. package/server/piecemaker/vendor/installer/steps/05-certificats.mjs +171 -0
  1228. package/server/piecemaker/vendor/installer/steps/06-hooks.mjs +266 -0
  1229. package/server/piecemaker/vendor/installer/steps/07-legifrance.mjs +279 -0
  1230. package/server/piecemaker/vendor/installer/steps/08-telegram.mjs +482 -0
  1231. package/server/piecemaker/vendor/installer/steps/09-claude-assets.mjs +151 -0
  1232. package/server/piecemaker/vendor/installer/steps/09-codex-plugin.mjs +142 -0
  1233. package/server/piecemaker/vendor/installer/steps/10-libreoffice.mjs +130 -0
  1234. package/server/piecemaker/vendor/installer/steps/10-pandoc.mjs +212 -0
  1235. package/server/piecemaker/vendor/installer/steps/11-docx-cli.mjs +144 -0
  1236. package/server/piecemaker/vendor/installer/steps/12-mcp-piecemaker.mjs +124 -0
  1237. package/server/piecemaker/vendor/installer/steps/13-garde-secrets.mjs +136 -0
  1238. package/server/piecemaker/vendor/installer/steps/14-mxc-sandbox.mjs +271 -0
  1239. package/server/piecemaker/vendor/installer/steps/15-pwa-desktop.mjs +64 -0
  1240. package/server/piecemaker/vendor/installer/templates/root-CLAUDE.md +79 -0
  1241. package/server/piecemaker/vendor/installer/templates/workspace-CLAUDE.md +111 -0
  1242. package/server/piecemaker/vendor/mcp/README.md +13 -0
  1243. package/server/piecemaker/vendor/mcp/piecemaker/server.mjs +222 -0
  1244. package/server/piecemaker/vendor/mike-defaults-fr/PROVENANCE.md +10 -0
  1245. package/server/piecemaker/vendor/mike-defaults-fr/assistant-workflows/compare-documents/SKILL.md +51 -0
  1246. package/server/piecemaker/vendor/mike-defaults-fr/assistant-workflows/draft-from-template/SKILL.md +27 -0
  1247. package/server/piecemaker/vendor/mike-defaults-fr/assistant-workflows/extract-key-terms/SKILL.md +43 -0
  1248. package/server/piecemaker/vendor/mike-defaults-fr/assistant-workflows/proofread/SKILL.md +98 -0
  1249. package/server/piecemaker/vendor/mike-defaults-fr/catalog.json +22 -0
  1250. package/server/piecemaker/vendor/mike-defaults-fr/tabular-review-workflows/commercial-agreement-tabular-review/SKILL.md +31 -0
  1251. package/server/piecemaker/vendor/mike-defaults-fr/tabular-review-workflows/commercial-agreement-tabular-review/table-columns.yaml +92 -0
  1252. package/server/piecemaker/vendor/package.json +7 -0
  1253. package/server/piecemaker/vendor/piecemaker-plugin/README.md +115 -0
  1254. package/server/piecemaker/vendor/piecemaker-plugin/agents/analyste-piece.md +38 -0
  1255. package/server/piecemaker/vendor/piecemaker-plugin/agents/jurisprudence-scanner.md +50 -0
  1256. package/server/piecemaker/vendor/piecemaker-plugin/hooks/hooks.json +84 -0
  1257. package/server/piecemaker/vendor/piecemaker-plugin/scripts/billing-track.mjs +194 -0
  1258. package/server/piecemaker/vendor/piecemaker-plugin/scripts/build-recherche-pdf.mjs +91 -0
  1259. package/server/piecemaker/vendor/piecemaker-plugin/scripts/classify-ai-documents.mjs +123 -0
  1260. package/server/piecemaker/vendor/piecemaker-plugin/scripts/commit-track.mjs +71 -0
  1261. package/server/piecemaker/vendor/piecemaker-plugin/scripts/compile-recherche.mjs +107 -0
  1262. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/anonymization-state.cjs +146 -0
  1263. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folder-structure.cjs +303 -0
  1264. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folders.cjs +86 -0
  1265. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/central-mapping.cjs +0 -0
  1266. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/citation-sources.cjs +519 -0
  1267. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/citations.cjs +292 -0
  1268. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/commits.cjs +1683 -0
  1269. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/docx-text-worker.cjs +43 -0
  1270. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/hook-io.mjs +249 -0
  1271. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/institutional-terms.cjs +160 -0
  1272. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/legifrance-reads.cjs +85 -0
  1273. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.cjs +346 -0
  1274. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.test.js +68 -0
  1275. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/protection.cjs +419 -0
  1276. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/recherche-report.cjs +177 -0
  1277. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/session-timing.cjs +80 -0
  1278. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/substitution.cjs +318 -0
  1279. package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/verify-citations.cjs +318 -0
  1280. package/server/piecemaker/vendor/piecemaker-plugin/scripts/protect-originals.mjs +256 -0
  1281. package/server/piecemaker/vendor/piecemaker-plugin/scripts/session-commit-worker.mjs +260 -0
  1282. package/server/piecemaker/vendor/piecemaker-plugin/scripts/session-commit.mjs +83 -0
  1283. package/server/piecemaker/vendor/piecemaker-plugin/scripts/statusline.mjs +179 -0
  1284. package/server/piecemaker/vendor/piecemaker-plugin/scripts/track-legifrance-reads.mjs +46 -0
  1285. package/server/piecemaker/vendor/piecemaker-plugin/skills/ajout-de-fonctionnalites/SKILL.md +66 -0
  1286. package/server/piecemaker/vendor/piecemaker-plugin/skills/conversion-md/SKILL.md +60 -0
  1287. package/server/piecemaker/vendor/piecemaker-plugin/skills/graphe-juridique/SKILL.md +105 -0
  1288. package/server/piecemaker/vendor/piecemaker-plugin/skills/recherche-juridique/SKILL.md +234 -0
  1289. package/server/piecemaker/vendor/piecemaker-plugin/skills/redaction-juridique/SKILL.md +96 -0
  1290. package/server/piecemaker/vendor/piecemaker-plugin/skills/tamponnage/SKILL.md +148 -0
  1291. package/server/piecemaker/vendor/websocket-server/admin-routes.cjs +3195 -0
  1292. package/server/piecemaker/vendor/websocket-server/case-folder-structure.cjs +3 -0
  1293. package/server/piecemaker/vendor/websocket-server/case-instructions.cjs +114 -0
  1294. package/server/piecemaker/vendor/websocket-server/case-registry.cjs +93 -0
  1295. package/server/piecemaker/vendor/websocket-server/claude-assets.cjs +338 -0
  1296. package/server/piecemaker/vendor/websocket-server/claude-hooks.cjs +380 -0
  1297. package/server/piecemaker/vendor/websocket-server/document-index.cjs +682 -0
  1298. package/server/piecemaker/vendor/websocket-server/graphify-document-graph.cjs +456 -0
  1299. package/server/piecemaker/vendor/websocket-server/legal-chronology.cjs +502 -0
  1300. package/server/piecemaker/vendor/websocket-server/legal-forms.cjs +89 -0
  1301. package/server/piecemaker/vendor/websocket-server/legal-forms.test.js +10 -0
  1302. package/server/piecemaker/vendor/websocket-server/legal-graph-materializer.cjs +234 -0
  1303. package/server/piecemaker/vendor/websocket-server/legal-graph-prompt.txt +155 -0
  1304. package/server/piecemaker/vendor/websocket-server/legal-graph.cjs +2021 -0
  1305. package/server/piecemaker/vendor/websocket-server/legal-identity-boundary.cjs +247 -0
  1306. package/server/piecemaker/vendor/websocket-server/legal-party-registry.cjs +261 -0
  1307. package/server/piecemaker/vendor/websocket-server/lib/doc-generate.cjs +229 -0
  1308. package/server/piecemaker/vendor/websocket-server/lib/export-render.cjs +442 -0
  1309. package/server/piecemaker/vendor/websocket-server/lib/office-to-pdf.cjs +306 -0
  1310. package/server/piecemaker/vendor/websocket-server/lib/stamping.cjs +39 -0
  1311. package/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs +965 -0
  1312. package/server/piecemaker/vendor/websocket-server/scripts/ADDRESS_ANONYMIZATION.md +216 -0
  1313. package/server/piecemaker/vendor/websocket-server/scripts/DEDUPLICATION_CHANGES.md +134 -0
  1314. package/server/piecemaker/vendor/websocket-server/scripts/GLINER2_README.md +138 -0
  1315. package/server/piecemaker/vendor/websocket-server/scripts/__pycache__/scan_utils.cpython-312.pyc +0 -0
  1316. package/server/piecemaker/vendor/websocket-server/scripts/convert_and_scan_pipeline.py +1984 -0
  1317. package/server/piecemaker/vendor/websocket-server/scripts/graphify-legal-sitecustomize.py +50 -0
  1318. package/server/piecemaker/vendor/websocket-server/scripts/mineru_improved_1.py +208 -0
  1319. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/AUDIT_PERF_QUALITE.md +246 -0
  1320. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/MODELE_COREML.md +62 -0
  1321. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/__pycache__/coreml_runtime.cpython-312.pyc +0 -0
  1322. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/__pycache__/model_config.cpython-312.pyc +0 -0
  1323. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/build_coreml.py +118 -0
  1324. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/coreml_runtime.py +164 -0
  1325. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/BACKENDS_MESURES.md +384 -0
  1326. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/CRITERES_QUALITE.md +81 -0
  1327. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/__pycache__/coreml_encoder.cpython-312.pyc +0 -0
  1328. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/bench_backend.py +151 -0
  1329. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/bench_batchsize.py +47 -0
  1330. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/bench_coreml_pipeline.py +138 -0
  1331. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/bench_gensight.py +124 -0
  1332. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/check_gold.py +66 -0
  1333. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/coreml_encoder.py +182 -0
  1334. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/encoder_backends.py +179 -0
  1335. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/evaluate.py +130 -0
  1336. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/gold.py +59 -0
  1337. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/profile_split.py +65 -0
  1338. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/slice_A.md +67 -0
  1339. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/slice_B.md +57 -0
  1340. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/slice_C.md +907 -0
  1341. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/sweep.py +115 -0
  1342. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/verify_substitution.cjs +116 -0
  1343. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/verify_whitespace.py +67 -0
  1344. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/eval/verify_worker.py +106 -0
  1345. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/model_config.py +28 -0
  1346. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/presidio-gliner.py +471 -0
  1347. package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/scanner_worker.py +668 -0
  1348. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__init__.py +10 -0
  1349. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__pycache__/__init__.cpython-312.pyc +0 -0
  1350. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__pycache__/analysis_explanation.cpython-312.pyc +0 -0
  1351. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__pycache__/entity_recognizer.cpython-312.pyc +0 -0
  1352. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__pycache__/local_recognizer.cpython-312.pyc +0 -0
  1353. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__pycache__/pattern.cpython-312.pyc +0 -0
  1354. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__pycache__/pattern_recognizer.cpython-312.pyc +0 -0
  1355. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/__pycache__/recognizer_result.cpython-312.pyc +0 -0
  1356. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/analysis_explanation.py +65 -0
  1357. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/entity_recognizer.py +213 -0
  1358. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/input_validation/__init__.py +21 -0
  1359. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/input_validation/language_validation.py +18 -0
  1360. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/input_validation/schemas.py +132 -0
  1361. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/input_validation/yaml_recognizer_models.py +422 -0
  1362. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/local_recognizer.py +7 -0
  1363. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/__init__.py +15 -0
  1364. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/__pycache__/__init__.cpython-312.pyc +0 -0
  1365. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/__pycache__/device_detector.cpython-312.pyc +0 -0
  1366. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/__pycache__/ner_model_configuration.cpython-312.pyc +0 -0
  1367. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/__pycache__/nlp_artifacts.cpython-312.pyc +0 -0
  1368. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/__pycache__/nlp_engine.cpython-312.pyc +0 -0
  1369. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/__pycache__/spacy_nlp_engine.cpython-312.pyc +0 -0
  1370. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/device_detector.py +65 -0
  1371. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/ner_model_configuration.py +128 -0
  1372. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/nlp_artifacts.py +88 -0
  1373. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/nlp_engine.py +65 -0
  1374. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/nlp_engine_provider.py +114 -0
  1375. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/nlp_engine/spacy_nlp_engine.py +290 -0
  1376. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/pattern.py +66 -0
  1377. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/pattern_recognizer.py +297 -0
  1378. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/__init__.py +4 -0
  1379. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/__pycache__/__init__.cpython-312.pyc +0 -0
  1380. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/__pycache__/gliner_recognizer.cpython-312.pyc +0 -0
  1381. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__init__.py +0 -0
  1382. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/__init__.cpython-312.pyc +0 -0
  1383. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/credit_card_recognizer.cpython-312.pyc +0 -0
  1384. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/crypto_recognizer.cpython-312.pyc +0 -0
  1385. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/email_recognizer.cpython-312.pyc +0 -0
  1386. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/iban_patterns.cpython-312.pyc +0 -0
  1387. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/iban_recognizer.cpython-312.pyc +0 -0
  1388. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/ip_recognizer.cpython-312.pyc +0 -0
  1389. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/mac_recognizer.cpython-312.pyc +0 -0
  1390. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/__pycache__/url_recognizer.cpython-312.pyc +0 -0
  1391. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/credit_card_recognizer.py +82 -0
  1392. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/crypto_recognizer.py +141 -0
  1393. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/date_recognizer.py +102 -0
  1394. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/email_recognizer.py +48 -0
  1395. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/iban_patterns.py +173 -0
  1396. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/iban_recognizer.py +221 -0
  1397. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/ip_recognizer.py +65 -0
  1398. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/mac_recognizer.py +73 -0
  1399. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/generic/url_recognizer.py +50 -0
  1400. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/gliner_recognizer.py +218 -0
  1401. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/predefined_recognizers/spacy_recognizer.py +139 -0
  1402. package/server/piecemaker/vendor/websocket-server/scripts/presidio_analyzer/recognizer_result.py +188 -0
  1403. package/server/piecemaker/vendor/websocket-server/scripts/requirements.txt +29 -0
  1404. package/server/piecemaker/vendor/websocket-server/scripts/scan_utils.py +469 -0
  1405. package/server/piecemaker/vendor/websocket-server/scripts/smart_converter.py +356 -0
  1406. package/server/piecemaker/vendor/websocket-server/scripts/warmup.py +454 -0
  1407. package/server/piecemaker/vendor/websocket-server/stamping-routes.cjs +334 -0
  1408. package/server/piecemaker/vendor/websocket-server/telegram-admin.cjs +602 -0
  1409. package/server/piecemaker/vendor/websocket-server/workspace-paths.cjs +22 -0
  1410. package/server/shared/claude-cli-path.ts +157 -0
  1411. package/server/shared/frontmatter.ts +18 -0
  1412. package/server/shared/image-attachments.ts +437 -0
  1413. package/server/shared/interfaces.ts +241 -0
  1414. package/server/shared/message-unification.ts +449 -0
  1415. package/server/shared/tests/application-data-root.test.ts +29 -0
  1416. package/server/shared/tests/claude-cli-path.test.ts +118 -0
  1417. package/server/shared/tests/image-attachments.test.ts +353 -0
  1418. package/server/shared/tests/message-unification.test.ts +218 -0
  1419. package/server/shared/tests/slice-tail-page.test.ts +42 -0
  1420. package/server/shared/types.ts +1354 -0
  1421. package/server/shared/utils.ts +1212 -0
  1422. package/server/tsconfig.json +40 -0
  1423. package/shared/networkHosts.js +22 -0
  1424. package/shared/product-config.mjs +86 -0
@@ -0,0 +1,1683 @@
1
+ /** Git commit history for independent PieceMaker legal matters. */
2
+ const crypto = require('node:crypto');
3
+ const fs = require('node:fs');
4
+ const os = require('node:os');
5
+ const path = require('node:path');
6
+ const zlib = require('node:zlib');
7
+ const { spawn } = require('node:child_process');
8
+ const { performance } = require('node:perf_hooks');
9
+ const { promisify } = require('node:util');
10
+ const { Worker } = require('node:worker_threads');
11
+
12
+ const {
13
+ documentKey,
14
+ isProtectedFile,
15
+ isResourceFile,
16
+ readProtection,
17
+ WORKSPACE_SUBDIR,
18
+ } = require('./protection.cjs');
19
+ const {
20
+ isAnonymizedEntry,
21
+ isConvertedEntry,
22
+ readAnonymizationState,
23
+ stateKey,
24
+ } = require('./anonymization-state.cjs');
25
+ const { formatDurationFr } = require('./session-timing.cjs');
26
+
27
+ const fsp = fs.promises;
28
+
29
+ // Root commits (first commit of a case, diffed against the empty tree) can
30
+ // produce patches well into the tens of MB even though only MAX_PATCH_BYTES
31
+ // of it is ever kept (see revisionDetails/worktreeDetails). This ceiling only
32
+ // exists to bound memory on a runaway/corrupt diff, so it must stay well
33
+ // above realistic patch sizes — a 16MB cap was killing legitimate large
34
+ // root-commit diffs (e.g. ~33MB) and turning them into a 400 error.
35
+ const MAX_GIT_BUFFER = 128 * 1024 * 1024;
36
+ const MAX_PATCH_BYTES = 768 * 1024;
37
+ const MAX_SAFE_FILES = 10_000;
38
+ const MAX_SAFE_BYTES = 250 * 1024 * 1024;
39
+ const HISTORY_REF = 'refs/heads/main';
40
+ const LEGACY_HISTORY_REF = 'refs/heads/checkpoints';
41
+ // Le hook PostToolUse commite à chaque Write/Edit : un mois d'activité peut
42
+ // donc contenir des milliers de commits. `listHistory` plafonne à 250 pour un
43
+ // affichage récent ; l'export mensuel a besoin de tout, mais reste borné pour
44
+ // ne jamais renvoyer un volume qui exploserait MAX_GIT_BUFFER.
45
+ const MAX_HISTORY_PERIOD_COMMITS = 5000;
46
+ const SAFE_EXTENSIONS = new Set(['.md', '.json']);
47
+ const DOCX_MANIFEST_PATH = '.piecemaker/history-docx-ooxml.json';
48
+ const DOCX_MANIFEST_VERSION = 1;
49
+ const DOCX_FINGERPRINT_ALGORITHM = 'ooxml-central-directory-crc32-v1';
50
+ const MAX_DOCX_CENTRAL_BYTES = 16 * 1024 * 1024;
51
+ const MAX_DOCX_PARTS = 20_000;
52
+ const MAX_DOCX_TEXT_XML_BYTES = 32 * 1024 * 1024;
53
+ const TECHNICAL_CASE_NAMES = new Set(['piecemaker_output']);
54
+ /**
55
+ * Arborescences techniques jamais parcourues. Un dossier juridique finit par
56
+ * héberger autre chose que des pièces : le dossier de test embarque une copie
57
+ * complète d'un projet Node, dont les 53 000 fichiers noyaient la liste de
58
+ * l'administration (47 000 entrées) et faisaient entrer les `package.json` de
59
+ * `node_modules` dans l'historique du dossier.
60
+ */
61
+ const IGNORED_DIRECTORY_NAMES = new Set([
62
+ 'node_modules', 'dist', 'build', 'out', 'coverage', 'vendor', 'target', '__pycache__', 'venv',
63
+ ]);
64
+ /** Plafond de la liste de l'administration ; au-delà, `truncated` le signale. */
65
+ const MAX_ORIGINALS = 2000;
66
+ const PERF_SLOW_MS = 250;
67
+ const PERF_LOG_ALL = process.env.PIECEMAKER_PERF_LOG === '1';
68
+ const COMMIT_USER_NAME_KEY = 'PIECEMAKER_USER_NAME';
69
+ const TECHNICAL_COMMIT_EMAIL = 'commits@piecemaker.local';
70
+ // Repli d'auteur Git quand aucune identité n'a été renseignée : un commit
71
+ // automatique (ex. enregistrement du mapping) ne doit jamais être bloqué par
72
+ // une identité manquante.
73
+ const DEFAULT_COMMIT_USER_NAME = 'PieceMaker';
74
+ const GLOBAL_ENV_FILE = path.resolve(__dirname, '..', '..', '..', '.env');
75
+ // Identité de commit partagée par tous les clones. `GLOBAL_ENV_FILE` est résolu
76
+ // relativement à ce module : lancé depuis le cache du plugin (hook d'édition),
77
+ // il pointe à côté du clone runtime et n'existe pas — le `.env` de l'identité
78
+ // vit dans le clone runtime, hors de portée. `config.json` sous ~/.piecemaker
79
+ // est le seul emplacement stable que le hook lit à coup sûr, quel que soit le
80
+ // clone d'où il tourne.
81
+ const IDENTITY_CONFIG_FILE = path.join(os.homedir(), '.piecemaker', 'config.json');
82
+ const inflateRaw = promisify(zlib.inflateRaw);
83
+ const deflateRaw = promisify(zlib.deflateRaw);
84
+
85
+ function validateCommitUserName(value) {
86
+ const cleaned = String(value || '').trim();
87
+ if (!cleaned) {
88
+ throw new Error('Identité utilisateur absente : renseignez votre nom dans les paramètres administrateur.');
89
+ }
90
+ if (cleaned.length > 160 || /[\x00-\x1f\x7f<>]/.test(cleaned)) {
91
+ throw new Error('Nom utilisateur invalide pour la signature des commits.');
92
+ }
93
+ return cleaned;
94
+ }
95
+
96
+ function unquoteEnvValue(value) {
97
+ const raw = String(value || '').trim();
98
+ if (raw.length >= 2 && ((raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'")))) {
99
+ return raw.slice(1, -1);
100
+ }
101
+ return raw;
102
+ }
103
+
104
+ function readCommitIdentityEnv(file = GLOBAL_ENV_FILE) {
105
+ let value = '';
106
+ try {
107
+ if (file && fs.existsSync(file)) {
108
+ for (const line of fs.readFileSync(file, 'utf8').split(/\r?\n/)) {
109
+ const match = line.match(/^\s*PIECEMAKER_USER_NAME\s*=(.*)$/);
110
+ if (match) value = unquoteEnvValue(match[1]);
111
+ }
112
+ }
113
+ } catch {
114
+ // Le processus peut encore avoir reçu l'identité depuis son environnement.
115
+ }
116
+ return value || process.env[COMMIT_USER_NAME_KEY] || '';
117
+ }
118
+
119
+ /** Nom de l'utilisateur mémorisé dans ~/.piecemaker/config.json (tous clones). */
120
+ function readCommitIdentityConfig(file = IDENTITY_CONFIG_FILE) {
121
+ try {
122
+ if (file && fs.existsSync(file)) {
123
+ const config = JSON.parse(fs.readFileSync(file, 'utf8'));
124
+ const name = config?.commits?.userName ?? config?.userName;
125
+ if (typeof name === 'string' && name.trim()) return name.trim();
126
+ }
127
+ } catch {
128
+ // Config illisible : on retombe sur les autres sources d'identité.
129
+ }
130
+ return '';
131
+ }
132
+
133
+ /** Identité personnelle appliquée à l'auteur et au validateur Git. */
134
+ function resolveCommitIdentity({ identity = null, envFile = GLOBAL_ENV_FILE, configFile = IDENTITY_CONFIG_FILE } = {}) {
135
+ const requestedName = typeof identity === 'string' ? identity : identity?.name;
136
+ // Sans identité explicite (hook d'édition), on tente le `.env` du clone
137
+ // courant puis, à défaut, config.json — le hook tourne depuis le cache du
138
+ // plugin où `envFile` par défaut n'existe pas. À défaut de tout ça, un nom
139
+ // technique par défaut : l'absence d'identité ne doit jamais empêcher un
140
+ // commit automatique.
141
+ const name = validateCommitUserName(
142
+ (identity ? requestedName : readCommitIdentityEnv(envFile) || readCommitIdentityConfig(configFile)) || DEFAULT_COMMIT_USER_NAME
143
+ );
144
+ return {
145
+ name,
146
+ // Git exige une adresse dans son format d'identité, mais PieceMaker ne
147
+ // collecte aucune adresse personnelle pour signer les tâches.
148
+ email: TECHNICAL_COMMIT_EMAIL,
149
+ };
150
+ }
151
+
152
+ /**
153
+ * Journal de performance volontairement compact : aucun contenu de dossier ni
154
+ * argument Git n'est journalisé. Les opérations lentes sont visibles par
155
+ * défaut ; PIECEMAKER_PERF_LOG=1 affiche aussi les étapes rapides pendant un
156
+ * diagnostic ponctuel.
157
+ */
158
+ function logPerformance(operation, startedAt, details = {}, slowMs = PERF_SLOW_MS) {
159
+ const durationMs = Number((performance.now() - startedAt).toFixed(1));
160
+ if (PERF_LOG_ALL || durationMs >= slowMs) {
161
+ const write = durationMs >= slowMs ? console.warn : console.log;
162
+ write(`[PM-PERF] ${operation}`, { durationMs, ...details });
163
+ }
164
+ return durationMs;
165
+ }
166
+
167
+ async function runGit(cwd, args, {
168
+ gitDir,
169
+ workTree,
170
+ env = {},
171
+ input,
172
+ allowFailure = false,
173
+ encoding = 'utf8',
174
+ maxOutputBytes = MAX_GIT_BUFFER,
175
+ truncateOutput = false,
176
+ } = {}) {
177
+ const startedAt = performance.now();
178
+ const command = [
179
+ ...(gitDir ? [`--git-dir=${gitDir}`] : []),
180
+ ...(workTree ? [`--work-tree=${workTree}`] : []),
181
+ '-c',
182
+ 'core.quotePath=false',
183
+ ...args,
184
+ ];
185
+ // `spawn` plutôt que `spawnSync` : le serveur d'administration sert aussi le
186
+ // task pane et le WebSocket depuis la même boucle d'événements, qu'un git
187
+ // synchrone bloquerait le temps du parcours complet du dossier.
188
+ return new Promise((resolve, reject) => {
189
+ const child = spawn('git', command, {
190
+ cwd,
191
+ windowsHide: true,
192
+ env: { ...process.env, ...env },
193
+ });
194
+ const outChunks = [];
195
+ const errChunks = [];
196
+ let outBytes = 0;
197
+ let failure = null;
198
+ let truncated = false;
199
+
200
+ child.stdout.on('data', (chunk) => {
201
+ if (truncated) return;
202
+ const nextBytes = outBytes + chunk.length;
203
+ if (nextBytes > maxOutputBytes) {
204
+ if (truncateOutput) {
205
+ const remaining = Math.max(maxOutputBytes - outBytes, 0);
206
+ if (remaining) outChunks.push(chunk.subarray(0, remaining));
207
+ outBytes += remaining;
208
+ truncated = true;
209
+ child.kill();
210
+ return;
211
+ }
212
+ if (!failure) {
213
+ failure = new Error(`git ${args[0]} a produit une sortie trop volumineuse`);
214
+ child.kill();
215
+ }
216
+ return;
217
+ }
218
+ outBytes = nextBytes;
219
+ outChunks.push(chunk);
220
+ });
221
+ child.stderr.on('data', (chunk) => errChunks.push(chunk));
222
+ child.on('error', (error) => { failure = failure || error; });
223
+ child.on('close', (code) => {
224
+ const rawStdout = Buffer.concat(outChunks);
225
+ const rawStderr = Buffer.concat(errChunks).toString('utf8');
226
+ const stdout = encoding === null ? rawStdout : rawStdout.toString('utf8').trimEnd();
227
+ const stderr = encoding === null ? rawStderr : rawStderr.trim();
228
+ const status = failure ? null : truncated && truncateOutput ? 0 : code;
229
+ logPerformance('git', startedAt, {
230
+ command: args[0] || 'unknown',
231
+ status: status ?? 1,
232
+ stdoutBytes: rawStdout.length,
233
+ truncated,
234
+ });
235
+ if (!allowFailure && ((status ?? 1) !== 0 || failure)) {
236
+ reject(new Error(stderr.trim() || rawStdout.toString('utf8') || failure?.message || `git ${args[0]} a échoué`));
237
+ return;
238
+ }
239
+ resolve({ code: status ?? 1, stdout, stderr, error: failure, truncated });
240
+ });
241
+
242
+ child.stdin.on('error', () => {});
243
+ child.stdin.end(input === undefined ? undefined : input);
244
+ });
245
+ }
246
+
247
+ /** `PieceMaker_Output` et consorts ne sont pas des dossiers juridiques. */
248
+ function isTechnicalCaseDirectoryName(value) {
249
+ return TECHNICAL_CASE_NAMES.has(String(value || '').trim().toLowerCase());
250
+ }
251
+
252
+ function isIgnoredDirectoryName(value) {
253
+ const name = String(value || '').trim().toLowerCase();
254
+ return IGNORED_DIRECTORY_NAMES.has(name) || TECHNICAL_CASE_NAMES.has(name);
255
+ }
256
+
257
+ function isDocxPath(value) {
258
+ return path.extname(String(value || '')).toLowerCase() === '.docx';
259
+ }
260
+
261
+ function emptyDocxManifest() {
262
+ return { version: DOCX_MANIFEST_VERSION, algorithm: DOCX_FINGERPRINT_ALGORITHM, files: {} };
263
+ }
264
+
265
+ function findZipEnd(buffer) {
266
+ const first = Math.max(0, buffer.length - 65_557);
267
+ for (let offset = buffer.length - 22; offset >= first; offset -= 1) {
268
+ if (buffer.readUInt32LE(offset) === 0x06054b50) return offset;
269
+ }
270
+ return -1;
271
+ }
272
+
273
+ async function parseCentralDirectory(buffer, entries) {
274
+ if (entries > MAX_DOCX_PARTS) return null;
275
+ const parts = [];
276
+ let offset = 0;
277
+ for (let index = 0; index < entries; index += 1) {
278
+ if (offset + 46 > buffer.length || buffer.readUInt32LE(offset) !== 0x02014b50) return null;
279
+ const flags = buffer.readUInt16LE(offset + 8);
280
+ const compression = buffer.readUInt16LE(offset + 10);
281
+ const crc32 = buffer.readUInt32LE(offset + 16).toString(16).padStart(8, '0');
282
+ const compressedSize = buffer.readUInt32LE(offset + 20);
283
+ const size = buffer.readUInt32LE(offset + 24);
284
+ const nameLength = buffer.readUInt16LE(offset + 28);
285
+ const next = offset + 46 + nameLength + buffer.readUInt16LE(offset + 30) + buffer.readUInt16LE(offset + 32);
286
+ if (next > buffer.length) return null;
287
+ const name = buffer.subarray(offset + 46, offset + 46 + nameLength)
288
+ .toString((flags & 0x0800) !== 0 ? 'utf8' : 'latin1')
289
+ .replaceAll('\\', '/');
290
+ if (name && !name.endsWith('/')) {
291
+ parts.push({
292
+ name,
293
+ crc32,
294
+ size,
295
+ compressedSize,
296
+ compression,
297
+ localOffset: buffer.readUInt32LE(offset + 42),
298
+ });
299
+ }
300
+ offset = next;
301
+ if (index > 0 && index % 1000 === 0) await new Promise((resolve) => setImmediate(resolve));
302
+ }
303
+ parts.sort((left, right) => left.name.localeCompare(right.name));
304
+ return parts;
305
+ }
306
+
307
+ /** Empreinte canonique des entrées OOXML, indépendante du conteneur ZIP. */
308
+ async function fingerprintCentralDirectory(buffer, entries) {
309
+ const parts = await parseCentralDirectory(buffer, entries);
310
+ if (!parts) return null;
311
+ const hash = crypto.createHash('sha256');
312
+ for (let index = 0; index < parts.length; index += 1) {
313
+ const part = parts[index];
314
+ hash.update(`${part.name}\0${part.crc32}\0${part.size}\n`);
315
+ if (index > 0 && index % 1000 === 0) await new Promise((resolve) => setImmediate(resolve));
316
+ }
317
+ return { fingerprint: hash.digest('hex'), format: 'ooxml', partCount: parts.length };
318
+ }
319
+
320
+ const docxFingerprintCache = new Map();
321
+ const docxTreeCache = new Map();
322
+ const docxTextCache = new Map();
323
+
324
+ function boundedCacheSet(cache, key, value, max) {
325
+ if (cache.has(key)) cache.delete(key);
326
+ cache.set(key, value);
327
+ if (cache.size > max) cache.delete(cache.keys().next().value);
328
+ }
329
+
330
+ function docxStat(stat) {
331
+ return {
332
+ size: stat.size,
333
+ mtimeMs: Number(stat.mtimeMs.toFixed(3)),
334
+ ctimeMs: Number(stat.ctimeMs.toFixed(3)),
335
+ };
336
+ }
337
+
338
+ function sameDocxStat(entry, stat) {
339
+ return entry?.size === stat.size && entry?.mtimeMs === stat.mtimeMs && entry?.ctimeMs === stat.ctimeMs;
340
+ }
341
+
342
+ async function readRange(handle, length, position) {
343
+ const buffer = Buffer.allocUnsafe(length);
344
+ const { bytesRead } = await handle.read(buffer, 0, length, position);
345
+ return bytesRead === length ? buffer : buffer.subarray(0, bytesRead);
346
+ }
347
+
348
+ function normalizeWordSections(sections) {
349
+ return new Promise((resolve, reject) => {
350
+ const worker = new Worker(path.join(__dirname, 'docx-text-worker.cjs'), { workerData: sections });
351
+ worker.once('message', resolve);
352
+ worker.once('error', reject);
353
+ worker.once('exit', (code) => {
354
+ if (code !== 0) reject(new Error(`Extraction DOCX interrompue (${code}).`));
355
+ });
356
+ });
357
+ }
358
+
359
+ async function readZipPart(handle, part) {
360
+ if (![0, 8].includes(part.compression)
361
+ || part.compressedSize > MAX_DOCX_TEXT_XML_BYTES
362
+ || part.size > MAX_DOCX_TEXT_XML_BYTES) return null;
363
+ const header = await readRange(handle, 30, part.localOffset);
364
+ if (header.length !== 30 || header.readUInt32LE(0) !== 0x04034b50) return null;
365
+ const dataOffset = part.localOffset + 30 + header.readUInt16LE(26) + header.readUInt16LE(28);
366
+ const compressed = await readRange(handle, part.compressedSize, dataOffset);
367
+ if (compressed.length !== part.compressedSize) return null;
368
+ if (part.compression === 0) return compressed;
369
+ try {
370
+ return await inflateRaw(compressed, { maxOutputLength: MAX_DOCX_TEXT_XML_BYTES });
371
+ } catch {
372
+ return null;
373
+ }
374
+ }
375
+
376
+ function docxPartTitle(name) {
377
+ if (name === 'word/document.xml') return 'Corps du document';
378
+ if (/^word\/header\d*\.xml$/i.test(name)) return 'En-tête';
379
+ if (/^word\/footer\d*\.xml$/i.test(name)) return 'Pied de page';
380
+ if (name === 'word/footnotes.xml') return 'Notes de bas de page';
381
+ if (name === 'word/endnotes.xml') return 'Notes de fin';
382
+ if (name === 'word/comments.xml') return 'Commentaires';
383
+ return name;
384
+ }
385
+
386
+ async function extractDocxText(file, stat) {
387
+ const key = `${file}\0${stat.size}\0${stat.mtimeMs}\0${stat.ctimeMs}`;
388
+ if (docxTextCache.has(key)) return docxTextCache.get(key);
389
+ let handle;
390
+ let text = '';
391
+ try {
392
+ handle = await fsp.open(file, 'r');
393
+ const tailLength = Math.min(stat.size, 65_557);
394
+ const tail = await readRange(handle, tailLength, stat.size - tailLength);
395
+ const end = findZipEnd(tail);
396
+ if (end < 0) return '';
397
+ const entries = tail.readUInt16LE(end + 10);
398
+ const centralSize = tail.readUInt32LE(end + 12);
399
+ const centralOffset = tail.readUInt32LE(end + 16);
400
+ if (entries === 0xffff || centralSize > MAX_DOCX_CENTRAL_BYTES || centralOffset + centralSize > stat.size) return '';
401
+ const parts = await parseCentralDirectory(await readRange(handle, centralSize, centralOffset), entries);
402
+ if (!parts) return '';
403
+ const readable = parts.filter((part) => part.name === 'word/document.xml'
404
+ || /^word\/(?:header\d*|footer\d*|footnotes|endnotes|comments)\.xml$/i.test(part.name));
405
+ const sections = [];
406
+ let totalBytes = 0;
407
+ for (const part of readable) {
408
+ totalBytes += part.size;
409
+ if (totalBytes > MAX_DOCX_TEXT_XML_BYTES) break;
410
+ const xml = await readZipPart(handle, part);
411
+ if (!xml) continue;
412
+ sections.push({ title: docxPartTitle(part.name), xml: xml.toString('utf8') });
413
+ }
414
+ text = await normalizeWordSections(sections);
415
+ } finally {
416
+ await handle?.close().catch(() => {});
417
+ }
418
+ boundedCacheSet(docxTextCache, key, text, 2_000);
419
+ return text;
420
+ }
421
+
422
+ async function encodeTextSnapshot(text) {
423
+ const compressed = await deflateRaw(Buffer.from(String(text || ''), 'utf8'), { level: 6 });
424
+ return compressed.toString('base64');
425
+ }
426
+
427
+ async function decodeTextSnapshot(entry) {
428
+ if (!entry?.textDeflate) return null;
429
+ try {
430
+ return (await inflateRaw(Buffer.from(entry.textDeflate, 'base64'), { maxOutputLength: MAX_DOCX_TEXT_XML_BYTES })).toString('utf8');
431
+ } catch {
432
+ return null;
433
+ }
434
+ }
435
+
436
+ async function addDocxTextSnapshot(caseRoot, relative, entry) {
437
+ const absolute = path.join(caseRoot, ...relative.split('/'));
438
+ const stat = docxStat(await fsp.stat(absolute));
439
+ const text = await extractDocxText(absolute, stat);
440
+ return {
441
+ ...entry,
442
+ textDeflate: await encodeTextSnapshot(text),
443
+ textHash: crypto.createHash('sha256').update(text).digest('hex'),
444
+ };
445
+ }
446
+
447
+ async function fingerprintDocx(file, stat) {
448
+ const key = `${file}\0${stat.size}\0${stat.mtimeMs}\0${stat.ctimeMs}`;
449
+ if (docxFingerprintCache.has(key)) return docxFingerprintCache.get(key);
450
+ let fingerprint = null;
451
+ let handle;
452
+ try {
453
+ handle = await fsp.open(file, 'r');
454
+ const tailLength = Math.min(stat.size, 65_557);
455
+ const tail = await readRange(handle, tailLength, stat.size - tailLength);
456
+ const end = findZipEnd(tail);
457
+ if (end >= 0) {
458
+ const entries = tail.readUInt16LE(end + 10);
459
+ const centralSize = tail.readUInt32LE(end + 12);
460
+ const centralOffset = tail.readUInt32LE(end + 16);
461
+ if (entries !== 0xffff && centralSize <= MAX_DOCX_CENTRAL_BYTES && centralOffset + centralSize <= stat.size) {
462
+ fingerprint = await fingerprintCentralDirectory(await readRange(handle, centralSize, centralOffset), entries);
463
+ }
464
+ }
465
+ } catch {
466
+ fingerprint = null;
467
+ } finally {
468
+ await handle?.close().catch(() => {});
469
+ }
470
+ // Repli pour un faux/ZIP64 DOCX : métadonnées seulement, jamais le binaire.
471
+ fingerprint ||= {
472
+ fingerprint: crypto.createHash('sha256').update(`metadata\0${stat.size}\0${stat.mtimeMs}\0${stat.ctimeMs}`).digest('hex'),
473
+ format: 'metadata-fallback',
474
+ partCount: 0,
475
+ };
476
+ boundedCacheSet(docxFingerprintCache, key, fingerprint, 20_000);
477
+ return fingerprint;
478
+ }
479
+
480
+ async function currentDocxManifest(caseRoot, baseline = emptyDocxManifest(), { includeText = false } = {}) {
481
+ const root = await fsp.realpath(caseRoot);
482
+ const protection = includeText ? readProtection(root) : null;
483
+ const files = {};
484
+ let count = 0;
485
+ async function visit(directory, prefix = '') {
486
+ for (const entry of await fsp.readdir(directory, { withFileTypes: true })) {
487
+ if (entry.name.startsWith('.') || entry.name.startsWith('~$') || entry.isSymbolicLink()) continue;
488
+ const absolute = path.join(directory, entry.name);
489
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
490
+ if (entry.isDirectory()) {
491
+ if (!isIgnoredDirectoryName(entry.name)) await visit(absolute, relative);
492
+ continue;
493
+ }
494
+ if (!entry.isFile() || !isDocxPath(entry.name)) continue;
495
+ if (count >= MAX_SAFE_FILES) throw new Error('Ce dossier contient trop de documents Word pour calculer leur historique.');
496
+ const stat = docxStat(await fsp.stat(absolute));
497
+ const previous = baseline.files[relative];
498
+ let current;
499
+ if (sameDocxStat(previous, stat)) {
500
+ current = previous;
501
+ } else {
502
+ const fingerprint = await fingerprintDocx(absolute, stat);
503
+ current = previous?.fingerprint === fingerprint.fingerprint ? previous : { ...stat, ...fingerprint };
504
+ }
505
+ if (includeText) {
506
+ if (isProtectedFile(absolute, root, protection)) {
507
+ const { textDeflate: _textDeflate, textHash: _textHash, ...withoutText } = current;
508
+ current = withoutText;
509
+ } else if (!current.textDeflate) {
510
+ current = await addDocxTextSnapshot(root, relative, current);
511
+ }
512
+ }
513
+ files[relative] = current;
514
+ count += 1;
515
+ if (count % 100 === 0) await new Promise((resolve) => setImmediate(resolve));
516
+ }
517
+ }
518
+ await visit(root);
519
+ return {
520
+ version: DOCX_MANIFEST_VERSION,
521
+ algorithm: DOCX_FINGERPRINT_ALGORITHM,
522
+ files: Object.fromEntries(Object.entries(files).sort(([left], [right]) => left.localeCompare(right, 'fr'))),
523
+ };
524
+ }
525
+
526
+ function serializeDocxManifest(manifest) {
527
+ return `${JSON.stringify(manifest)}\n`;
528
+ }
529
+
530
+ function parseDocxManifest(value) {
531
+ try {
532
+ const manifest = JSON.parse(String(value || ''));
533
+ return manifest?.version === DOCX_MANIFEST_VERSION && manifest.files && typeof manifest.files === 'object'
534
+ ? manifest
535
+ : emptyDocxManifest();
536
+ } catch {
537
+ return emptyDocxManifest();
538
+ }
539
+ }
540
+
541
+ function resolveCasesRoot(casesRoot) {
542
+ if (!casesRoot) throw new Error('Le dossier racine PieceMaker n’est pas configuré.');
543
+ const root = path.resolve(String(casesRoot));
544
+ if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) {
545
+ throw new Error(`Le dossier racine PieceMaker est introuvable : ${root}`);
546
+ }
547
+ return fs.realpathSync(root);
548
+ }
549
+
550
+ function resolveCase(casesRoot, caseName) {
551
+ const root = resolveCasesRoot(casesRoot);
552
+ const name = String(caseName || '').trim();
553
+ if (!name || name === '.' || name === '..' || path.basename(name) !== name || name.startsWith('.')) {
554
+ throw new Error('Dossier juridique invalide.');
555
+ }
556
+ const candidate = path.join(root, name);
557
+ if (!fs.existsSync(candidate) || !fs.statSync(candidate).isDirectory()) {
558
+ throw new Error(`Le dossier juridique « ${name} » est introuvable.`);
559
+ }
560
+ const caseRoot = fs.realpathSync(candidate);
561
+ if (path.dirname(caseRoot) !== root) {
562
+ throw new Error('Le dossier juridique résout hors de la racine PieceMaker.');
563
+ }
564
+ return { casesRoot: root, name, root: caseRoot };
565
+ }
566
+
567
+ function locateCaseFile(casesRoot, filePath) {
568
+ const root = resolveCasesRoot(casesRoot);
569
+ const requested = path.resolve(String(filePath || ''));
570
+ let absolute = requested;
571
+ try {
572
+ absolute = fs.realpathSync(requested);
573
+ } catch {
574
+ try {
575
+ absolute = path.join(fs.realpathSync(path.dirname(requested)), path.basename(requested));
576
+ } catch {}
577
+ }
578
+ if (absolute === root || !absolute.startsWith(`${root}${path.sep}`)) return null;
579
+ const relativeToRoot = path.relative(root, absolute);
580
+ const [caseName, ...parts] = relativeToRoot.split(path.sep);
581
+ if (!caseName || parts.length === 0) return null;
582
+ const legalCase = resolveCase(root, caseName);
583
+ if (isProtectedFile(absolute, legalCase.root)) {
584
+ return { ...legalCase, absolute, protected: true, relative: parts.join('/') };
585
+ }
586
+ if (path.extname(absolute).toLowerCase() && !SAFE_EXTENSIONS.has(path.extname(absolute).toLowerCase())) {
587
+ return { ...legalCase, absolute, protected: false, safe: false, relative: parts.join('/') };
588
+ }
589
+ const relative = path.relative(legalCase.root, absolute).split(path.sep).join('/');
590
+ if (!relative || relative.startsWith('../')) return null;
591
+ return { ...legalCase, absolute, protected: false, safe: SAFE_EXTENSIONS.has(path.extname(relative).toLowerCase()), relative };
592
+ }
593
+
594
+ async function safeCaseFiles(caseRoot) {
595
+ const startedAt = performance.now();
596
+ const root = await fsp.realpath(caseRoot);
597
+ const files = [];
598
+ let bytes = 0;
599
+
600
+ async function visit(directory, prefix = '') {
601
+ for (const entry of await fsp.readdir(directory, { withFileTypes: true })) {
602
+ if (entry.name.startsWith('.') || entry.isSymbolicLink()) continue;
603
+ const absolute = path.join(directory, entry.name);
604
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
605
+ if (entry.isDirectory()) {
606
+ if (!isIgnoredDirectoryName(entry.name)) await visit(absolute, relative);
607
+ continue;
608
+ }
609
+ if (!entry.isFile() || !SAFE_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) continue;
610
+ const size = (await fsp.stat(absolute)).size;
611
+ bytes += size;
612
+ files.push(relative);
613
+ if (files.length > MAX_SAFE_FILES) throw new Error('Ce dossier contient trop de fichiers Markdown/JSON pour un commit sûr.');
614
+ if (bytes > MAX_SAFE_BYTES) throw new Error('Les fichiers accessibles à l’IA dépassent 250 Mo ; commit annulé.');
615
+ }
616
+ }
617
+
618
+ await visit(root);
619
+ const sorted = files.sort((a, b) => a.localeCompare(b, 'fr'));
620
+ logPerformance('safeCaseFiles', startedAt, { files: sorted.length, bytes });
621
+ return sorted;
622
+ }
623
+
624
+ /**
625
+ * Les pièces d'un dossier juridique, sous-dossiers compris.
626
+ *
627
+ * Le recensement ne dépend plus d'un sous-dossier « Pièces originales » : un
628
+ * cabinet range ses pièces à plat, à côté du Markdown qu'il en tire, et cette
629
+ * organisation-là ne protégeait donc rien. Est une pièce tout fichier qui n'est
630
+ * ni Markdown ni JSON — le reste, ce sont les dérivés que l'IA a le droit de
631
+ * lire (sous mapping) et le mapping lui-même.
632
+ *
633
+ * `converted` / `scanned` restent l'état du pipeline ; `protected` est la
634
+ * décision prise dans l'administration et appliquée par les hooks. Le scan
635
+ * n'est plus déduit de la présence d'un mapping sensible par pièce : le
636
+ * manifeste technique `.piecemaker/anonymization-state.json`, dépourvu de PII,
637
+ * mémorise les empreintes de conversion et de scan. Les anciens sensitive maps
638
+ * ne servent que de compatibilité pendant leur migration.
639
+ */
640
+ async function originalFilesOverview(caseRoot, { safeFiles: knownSafeFiles = null } = {}) {
641
+ const startedAt = performance.now();
642
+ const root = await fsp.realpath(caseRoot);
643
+ const safeFiles = knownSafeFiles || await safeCaseFiles(root);
644
+ const markdownKeys = new Set(safeFiles.filter((file) => path.extname(file).toLowerCase() === '.md').map(documentKey));
645
+ const scanKeys = new Set(
646
+ safeFiles
647
+ .filter((file) => file.toLowerCase().endsWith('_sensitive_map.json'))
648
+ .map((file) => documentKey(file).replace(/-sensitive-map$/, ''))
649
+ );
650
+ const anonymizationState = readAnonymizationState(root);
651
+ const protection = readProtection(root);
652
+ const originals = [];
653
+ let truncated = false;
654
+
655
+ async function visit(directory, prefix = '') {
656
+ const entries = await fsp.readdir(directory, { withFileTypes: true });
657
+ // MinerU écrit sa sortie dans `<nom de la pièce>/auto/` à côté de la pièce.
658
+ // Ces dérivés portent le même contenu que l'original — ils restent donc
659
+ // protégés par défaut — mais les lister doublerait chaque pièce dans
660
+ // l'administration.
661
+ const conversionOutputs = new Set(
662
+ entries.filter((entry) => entry.isFile()).map((entry) => documentKey(entry.name))
663
+ );
664
+ for (const entry of entries) {
665
+ if (entry.name.startsWith('.') || entry.name.startsWith('~$') || entry.isSymbolicLink()) continue;
666
+ const absolute = path.join(directory, entry.name);
667
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
668
+ if (entry.isDirectory()) {
669
+ // Le sous-dossier des fichiers produits (Markdown, mapping) n'est jamais
670
+ // une source de pièces : ses `.md`/`.json` sont déjà écartés par
671
+ // `SAFE_EXTENSIONS`, mais d'éventuels dérivés non-Markdown (images
672
+ // MinerU) qui y vivent ne doivent pas non plus être listés comme pièces.
673
+ // `safeCaseFiles`, lui, continue de le parcourir pour repérer les `.md`.
674
+ if (entry.name === WORKSPACE_SUBDIR) continue;
675
+ if (isIgnoredDirectoryName(entry.name) || conversionOutputs.has(documentKey(entry.name))) continue;
676
+ await visit(absolute, relative);
677
+ continue;
678
+ }
679
+ if (originals.length >= MAX_ORIGINALS) {
680
+ truncated = true;
681
+ return;
682
+ }
683
+ if (!entry.isFile()) continue;
684
+ if (SAFE_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) continue;
685
+ const stat = await fsp.stat(absolute);
686
+ const key = documentKey(entry.name);
687
+ const stateEntry = anonymizationState.files[stateKey(relative)];
688
+ // Un dossier ancien sans manifeste conserve le comportement historique
689
+ // (Markdown présent = converti). Dès qu'une empreinte existe, elle rend un
690
+ // Markdown périmé visible au lieu de le réutiliser silencieusement.
691
+ const converted = markdownKeys.has(key) && (!stateEntry || isConvertedEntry(stateEntry, stat));
692
+ const scanned = converted && (
693
+ isAnonymizedEntry(stateEntry, stat)
694
+ || scanKeys.has(key)
695
+ );
696
+ originals.push({
697
+ name: entry.name,
698
+ path: relative,
699
+ extension: path.extname(entry.name).toLowerCase(),
700
+ size: stat.size,
701
+ modifiedAt: stat.mtime.toISOString(),
702
+ converted,
703
+ scanned,
704
+ protected: isProtectedFile(absolute, root, protection),
705
+ resource: isResourceFile(absolute, root, protection),
706
+ status: converted ? (scanned ? 'ready' : 'awaiting-scan') : 'not-converted',
707
+ });
708
+ }
709
+ }
710
+
711
+ await visit(root);
712
+ const sorted = originals.sort((a, b) => a.path.localeCompare(b.path, 'fr'));
713
+ if (truncated) sorted.truncated = true;
714
+ logPerformance('originalFilesOverview', startedAt, {
715
+ safeFiles: safeFiles.length,
716
+ originals: sorted.length,
717
+ truncated,
718
+ });
719
+ return sorted;
720
+ }
721
+
722
+ function historyId(legalCase) {
723
+ const slug = legalCase.name
724
+ .normalize('NFKD')
725
+ .replace(/[\u0300-\u036f]/g, '')
726
+ .replace(/[^A-Za-z0-9._-]+/g, '-')
727
+ .replace(/^[.-]+|[.-]+$/g, '')
728
+ .slice(0, 60) || 'dossier';
729
+ const digest = crypto.createHash('sha256').update(legalCase.root).digest('hex').slice(0, 12);
730
+ return `${slug}-${digest}`;
731
+ }
732
+
733
+ const caseStateCache = new Map();
734
+
735
+ function caseStateCacheKey(homeDir, legalCase) {
736
+ return `${path.resolve(homeDir)}:${historyId(legalCase)}`;
737
+ }
738
+
739
+ function historyDirectory(homeDir = path.join(os.homedir(), '.piecemaker')) {
740
+ return path.join(homeDir, 'case-history');
741
+ }
742
+
743
+ function historyRepo(homeDir, legalCase) {
744
+ return path.join(historyDirectory(homeDir), `${historyId(legalCase)}.git`);
745
+ }
746
+
747
+ async function ensureHistoryRepo(homeDir, legalCase) {
748
+ const gitDir = historyRepo(homeDir, legalCase);
749
+ if (!fs.existsSync(gitDir)) {
750
+ fs.mkdirSync(path.dirname(gitDir), { recursive: true });
751
+ await runGit(legalCase.root, ['init', '--bare', gitDir]);
752
+ await runGit(legalCase.root, ['symbolic-ref', 'HEAD', HISTORY_REF], { gitDir });
753
+ }
754
+ const main = await runGit(legalCase.root, ['rev-parse', '--verify', HISTORY_REF], { gitDir, allowFailure: true });
755
+ if (main.code !== 0) {
756
+ const legacy = await runGit(legalCase.root, ['rev-parse', '--verify', LEGACY_HISTORY_REF], { gitDir, allowFailure: true });
757
+ if (legacy.code === 0) await runGit(legalCase.root, ['update-ref', HISTORY_REF, legacy.stdout], { gitDir });
758
+ }
759
+ const head = await runGit(legalCase.root, ['symbolic-ref', '-q', 'HEAD'], { gitDir, allowFailure: true });
760
+ const headCommit = head.code === 0
761
+ ? await runGit(legalCase.root, ['rev-parse', '--verify', head.stdout], { gitDir, allowFailure: true })
762
+ : { code: 1 };
763
+ const migratedMain = await runGit(legalCase.root, ['rev-parse', '--verify', HISTORY_REF], { gitDir, allowFailure: true });
764
+ if (head.code !== 0 || !head.stdout.startsWith('refs/heads/') || (headCommit.code !== 0 && migratedMain.code === 0)) {
765
+ await runGit(legalCase.root, ['symbolic-ref', 'HEAD', HISTORY_REF], { gitDir });
766
+ }
767
+ return gitDir;
768
+ }
769
+
770
+ async function activeHistoryRef(legalCase, gitDir) {
771
+ const result = await runGit(legalCase.root, ['symbolic-ref', '-q', 'HEAD'], { gitDir, allowFailure: true });
772
+ return result.code === 0 && result.stdout.startsWith('refs/heads/') ? result.stdout : HISTORY_REF;
773
+ }
774
+
775
+ async function latestCommit(legalCase, gitDir) {
776
+ const result = await runGit(legalCase.root, ['rev-parse', '--verify', await activeHistoryRef(legalCase, gitDir)], { gitDir, allowFailure: true });
777
+ return result.code === 0 ? result.stdout : '';
778
+ }
779
+
780
+ async function historyBranches(casesRoot, homeDir, caseName) {
781
+ const legalCase = resolveCase(casesRoot, caseName);
782
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
783
+ const activeRef = await activeHistoryRef(legalCase, gitDir);
784
+ const active = activeRef.slice('refs/heads/'.length);
785
+ const result = await runGit(legalCase.root, ['for-each-ref', '--format=%(refname:short)', 'refs/heads'], { gitDir });
786
+ const branches = [...new Set([active, ...result.stdout.split('\n').map((name) => name.trim()).filter(Boolean)])]
787
+ .sort((a, b) => a.localeCompare(b, 'fr'));
788
+ return { active, branches };
789
+ }
790
+
791
+ async function validatedBranchName(legalCase, gitDir, value) {
792
+ const name = String(value || '').trim();
793
+ if (!name || name.length > 120) throw new Error('Le nom de branche est requis.');
794
+ const valid = await runGit(legalCase.root, ['check-ref-format', '--branch', name], { gitDir, allowFailure: true });
795
+ if (valid.code !== 0) throw new Error('Nom de branche Git invalide.');
796
+ return name;
797
+ }
798
+
799
+ async function createHistoryBranch({ casesRoot, caseName, homeDir = path.join(os.homedir(), '.piecemaker'), name } = {}) {
800
+ const legalCase = resolveCase(casesRoot, caseName);
801
+ return withCaseLock(homeDir, legalCase, async () => {
802
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
803
+ const branch = await validatedBranchName(legalCase, gitDir, name);
804
+ const ref = `refs/heads/${branch}`;
805
+ const exists = await runGit(legalCase.root, ['show-ref', '--verify', '--quiet', ref], { gitDir, allowFailure: true });
806
+ if (exists.code === 0) throw new Error(`La branche « ${branch} » existe déjà.`);
807
+ const parent = await latestCommit(legalCase, gitDir);
808
+ if (parent) await runGit(legalCase.root, ['update-ref', ref, parent], { gitDir });
809
+ await runGit(legalCase.root, ['symbolic-ref', 'HEAD', ref], { gitDir });
810
+ caseStateCache.delete(caseStateCacheKey(homeDir, legalCase));
811
+ return historyBranches(casesRoot, homeDir, legalCase.name);
812
+ }, { waitMs: 10_000 });
813
+ }
814
+
815
+ async function checkoutHistoryBranch({ casesRoot, caseName, homeDir = path.join(os.homedir(), '.piecemaker'), name } = {}) {
816
+ const legalCase = resolveCase(casesRoot, caseName);
817
+ return withCaseLock(homeDir, legalCase, async () => {
818
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
819
+ const branch = await validatedBranchName(legalCase, gitDir, name);
820
+ const ref = `refs/heads/${branch}`;
821
+ const exists = await runGit(legalCase.root, ['show-ref', '--verify', '--quiet', ref], { gitDir, allowFailure: true });
822
+ const current = await activeHistoryRef(legalCase, gitDir);
823
+ if (exists.code !== 0 && current !== ref) throw new Error(`La branche « ${branch} » n’existe pas.`);
824
+ await runGit(legalCase.root, ['symbolic-ref', 'HEAD', ref], { gitDir });
825
+ caseStateCache.delete(caseStateCacheKey(homeDir, legalCase));
826
+ return historyBranches(casesRoot, homeDir, legalCase.name);
827
+ }, { waitMs: 10_000 });
828
+ }
829
+
830
+ async function withCaseLock(homeDir, legalCase, callback, { waitMs = 0 } = {}) {
831
+ const directory = historyDirectory(homeDir);
832
+ fs.mkdirSync(directory, { recursive: true });
833
+ const lock = path.join(directory, `${historyId(legalCase)}.lock`);
834
+ const deadline = Date.now() + Math.max(Number(waitMs) || 0, 0);
835
+ let fd;
836
+ try {
837
+ while (fd === undefined) {
838
+ try {
839
+ fd = fs.openSync(lock, 'wx');
840
+ } catch (error) {
841
+ if (error.code !== 'EEXIST') throw error;
842
+ let age = 0;
843
+ try {
844
+ age = Date.now() - fs.statSync(lock).mtimeMs;
845
+ } catch {
846
+ continue;
847
+ }
848
+ if (age >= 60_000) {
849
+ try { fs.unlinkSync(lock); } catch {}
850
+ continue;
851
+ }
852
+ if (Date.now() >= deadline) return { created: false, skipped: 'busy' };
853
+ await new Promise((resolve) => setTimeout(resolve, Math.min(50, Math.max(deadline - Date.now(), 1))));
854
+ }
855
+ }
856
+ fs.writeFileSync(fd, `${process.pid}\n`, 'utf8');
857
+ return await callback();
858
+ } finally {
859
+ if (fd !== undefined) {
860
+ try { fs.closeSync(fd); } catch {}
861
+ try { fs.unlinkSync(lock); } catch {}
862
+ }
863
+ }
864
+ }
865
+
866
+ async function putDocxManifestInIndex(legalCase, gitDir, env, manifest) {
867
+ if (!Object.keys(manifest.files).length) return;
868
+ const blob = (await runGit(legalCase.root, ['hash-object', '-w', '--stdin'], {
869
+ gitDir,
870
+ input: serializeDocxManifest(manifest),
871
+ })).stdout;
872
+ await runGit(legalCase.root, ['update-index', '--add', '--cacheinfo', `100644,${blob},${DOCX_MANIFEST_PATH}`], {
873
+ gitDir,
874
+ workTree: legalCase.root,
875
+ env,
876
+ });
877
+ }
878
+
879
+ async function treeDocxManifest(legalCase, gitDir, treeish) {
880
+ if (!treeish) return emptyDocxManifest();
881
+ const key = `${gitDir}\0${treeish}`;
882
+ if (docxTreeCache.has(key)) return docxTreeCache.get(key);
883
+ const result = await runGit(legalCase.root, ['show', `${treeish}:${DOCX_MANIFEST_PATH}`], { gitDir, allowFailure: true });
884
+ const manifest = result.code === 0 ? parseDocxManifest(result.stdout) : emptyDocxManifest();
885
+ boundedCacheSet(docxTreeCache, key, manifest, 2_000);
886
+ return manifest;
887
+ }
888
+
889
+ function docxChanges(beforeManifest, afterManifest) {
890
+ const before = beforeManifest.files;
891
+ const after = afterManifest.files;
892
+ return [...new Set([...Object.keys(before), ...Object.keys(after)])]
893
+ .sort((left, right) => left.localeCompare(right, 'fr'))
894
+ .flatMap((filePath) => {
895
+ if (!before[filePath]) return [{ status: 'A', path: filePath, previousPath: null, kind: 'added' }];
896
+ if (!after[filePath]) return [{ status: 'D', path: filePath, previousPath: null, kind: 'deleted' }];
897
+ return before[filePath].fingerprint === after[filePath].fingerprint
898
+ ? []
899
+ : [{ status: 'M', path: filePath, previousPath: null, kind: 'modified' }];
900
+ });
901
+ }
902
+
903
+ async function liveDocxText(legalCase, filePath, entry) {
904
+ if (!entry) return '';
905
+ const absolute = path.join(legalCase.root, ...filePath.split('/'));
906
+ try {
907
+ const stat = docxStat(await fsp.stat(absolute));
908
+ const fingerprint = await fingerprintDocx(absolute, stat);
909
+ if (fingerprint.fingerprint !== entry.fingerprint) return null;
910
+ return extractDocxText(absolute, stat);
911
+ } catch {
912
+ return null;
913
+ }
914
+ }
915
+
916
+ async function entryDocxText(legalCase, filePath, entry) {
917
+ if (!entry) return '';
918
+ return await decodeTextSnapshot(entry) ?? liveDocxText(legalCase, filePath, entry);
919
+ }
920
+
921
+ function limitPatch(value) {
922
+ const buffer = Buffer.from(String(value || ''), 'utf8');
923
+ if (buffer.length <= MAX_PATCH_BYTES) return { stdout: buffer.toString('utf8'), truncated: false };
924
+ return { stdout: `${buffer.subarray(0, MAX_PATCH_BYTES).toString('utf8')}…`, truncated: true };
925
+ }
926
+
927
+ async function docxTextDiff(legalCase, beforeManifest, afterManifest, filePath) {
928
+ const before = beforeManifest.files[filePath];
929
+ const after = afterManifest.files[filePath];
930
+ const absolute = path.join(legalCase.root, ...filePath.split('/'));
931
+ if (isProtectedFile(absolute, legalCase.root)) {
932
+ return {
933
+ stdout: `diff --text a/${filePath} b/${filePath}\n@@ Document protégé @@\n Le texte n’est pas extrait des pièces protégées.\n`,
934
+ truncated: false,
935
+ stats: { files: 1, added: 0, deleted: 0 },
936
+ };
937
+ }
938
+
939
+ const [beforeText, afterText] = await Promise.all([
940
+ entryDocxText(legalCase, filePath, before),
941
+ entryDocxText(legalCase, filePath, after),
942
+ ]);
943
+ if (beforeText === null || afterText === null) {
944
+ const available = afterText ?? beforeText ?? '';
945
+ const prefix = afterText !== null ? '+' : '-';
946
+ const lines = available.split('\n').map((line) => `${prefix}${line}`);
947
+ const patch = limitPatch([
948
+ `diff --text a/${filePath} b/${filePath}`,
949
+ `--- ${before ? `a/${filePath}` : '/dev/null'}`,
950
+ `+++ ${after ? `b/${filePath}` : '/dev/null'}`,
951
+ '@@ Texte partiellement disponible @@',
952
+ ' Le prochain commit servira de référence textuelle complète.',
953
+ ...lines,
954
+ '',
955
+ ].join('\n'));
956
+ return {
957
+ ...patch,
958
+ stats: {
959
+ files: 1,
960
+ added: prefix === '+' ? lines.length : 0,
961
+ deleted: prefix === '-' ? lines.length : 0,
962
+ },
963
+ };
964
+ }
965
+
966
+ const temporary = await fsp.mkdtemp(path.join(os.tmpdir(), 'piecemaker-docx-diff-'));
967
+ const beforeFile = path.join(temporary, 'avant.txt');
968
+ const afterFile = path.join(temporary, 'apres.txt');
969
+ try {
970
+ await Promise.all([
971
+ fsp.writeFile(beforeFile, `${beforeText}\n`, { encoding: 'utf8', mode: 0o600 }),
972
+ fsp.writeFile(afterFile, `${afterText}\n`, { encoding: 'utf8', mode: 0o600 }),
973
+ ]);
974
+ const result = await runGit(legalCase.root, [
975
+ 'diff', '--no-index', '--text', '--unified=3', '--', beforeFile, afterFile,
976
+ ], { allowFailure: true, maxOutputBytes: MAX_PATCH_BYTES, truncateOutput: true });
977
+ const hunk = String(result.stdout || '').match(/^@@[\s\S]*$/m)?.[0] || '';
978
+ const patch = [
979
+ `diff --text a/${filePath} b/${filePath}`,
980
+ `--- ${before ? `a/${filePath}` : '/dev/null'}`,
981
+ `+++ ${after ? `b/${filePath}` : '/dev/null'}`,
982
+ hunk,
983
+ ].filter(Boolean).join('\n');
984
+ const body = hunk.split('\n');
985
+ return {
986
+ stdout: patch,
987
+ truncated: result.truncated,
988
+ stats: {
989
+ files: 1,
990
+ added: body.filter((line) => line.startsWith('+') && !line.startsWith('+++')).length,
991
+ deleted: body.filter((line) => line.startsWith('-') && !line.startsWith('---')).length,
992
+ },
993
+ };
994
+ } finally {
995
+ await fsp.rm(temporary, { recursive: true, force: true });
996
+ }
997
+ }
998
+
999
+ async function buildCurrentTree(legalCase, gitDir, homeDir, baselineDocx = emptyDocxManifest(), { includeDocx = true } = {}) {
1000
+ const startedAt = performance.now();
1001
+ const temporaryIndex = path.join(historyDirectory(homeDir), `index-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);
1002
+ const env = { GIT_INDEX_FILE: temporaryIndex };
1003
+ const [files, docxManifest] = await Promise.all([
1004
+ safeCaseFiles(legalCase.root),
1005
+ currentDocxManifest(legalCase.root, baselineDocx, { includeText: includeDocx }),
1006
+ ]);
1007
+ try {
1008
+ await runGit(legalCase.root, ['read-tree', '--empty'], { gitDir, workTree: legalCase.root, env });
1009
+ if (files.length) {
1010
+ // Un seul processus Git reçoit les chemins en NUL sur stdin. L'ancien
1011
+ // découpage par groupes de 100 relançait Git 38 fois sur un gros dossier.
1012
+ await runGit(legalCase.root, [
1013
+ 'add', '-f', '--pathspec-from-file=-', '--pathspec-file-nul',
1014
+ ], {
1015
+ gitDir,
1016
+ workTree: legalCase.root,
1017
+ env,
1018
+ // Apple Git stocke les chemins précomposés dans l'index alors qu'APFS
1019
+ // les renvoie souvent décomposés. Les arguments argv étaient convertis
1020
+ // implicitement ; les pathspec lus sur stdin doivent l'être ici.
1021
+ input: Buffer.from(`${files.map((file) => process.platform === 'darwin' ? file.normalize('NFC') : file).join('\0')}\0`, 'utf8'),
1022
+ });
1023
+ }
1024
+ if (includeDocx) await putDocxManifestInIndex(legalCase, gitDir, env, docxManifest);
1025
+ const tree = (await runGit(legalCase.root, ['write-tree'], { gitDir, workTree: legalCase.root, env })).stdout;
1026
+ if (includeDocx) boundedCacheSet(docxTreeCache, `${gitDir}\0${tree}`, docxManifest, 2_000);
1027
+ const snapshot = includeDocx
1028
+ ? tree
1029
+ : crypto.createHash('sha1').update(`${tree}\0${serializeDocxManifest(docxManifest)}`).digest('hex');
1030
+ logPerformance('buildCurrentTree', startedAt, {
1031
+ files: files.length,
1032
+ gitAddBatches: files.length ? 1 : 0,
1033
+ });
1034
+ return { tree, snapshot, files, docxManifest };
1035
+ } finally {
1036
+ try { fs.unlinkSync(temporaryIndex); } catch {}
1037
+ }
1038
+ }
1039
+
1040
+ /**
1041
+ * Construit un arbre à partir du parent en n'y appliquant que les chemins de
1042
+ * l'opération courante. Les autres modifications présentes dans le work-tree
1043
+ * restent donc locales et ne peuvent pas fuiter dans un commit automatique.
1044
+ */
1045
+ async function buildSelectedTree(legalCase, gitDir, homeDir, parent, selectedPaths) {
1046
+ const startedAt = performance.now();
1047
+ const temporaryIndex = path.join(historyDirectory(homeDir), `index-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);
1048
+ const env = { GIT_INDEX_FILE: temporaryIndex };
1049
+ try {
1050
+ await runGit(legalCase.root, ['read-tree', ...(parent ? [parent] : ['--empty'])], {
1051
+ gitDir,
1052
+ workTree: legalCase.root,
1053
+ env,
1054
+ });
1055
+ if (selectedPaths.length) {
1056
+ await runGit(legalCase.root, [
1057
+ 'add', '-f', '-A', '--pathspec-from-file=-', '--pathspec-file-nul',
1058
+ ], {
1059
+ gitDir,
1060
+ workTree: legalCase.root,
1061
+ env,
1062
+ input: Buffer.from(`${selectedPaths.map((file) => process.platform === 'darwin' ? file.normalize('NFC') : file).join('\0')}\0`, 'utf8'),
1063
+ });
1064
+ }
1065
+ const tree = (await runGit(legalCase.root, ['write-tree'], { gitDir, workTree: legalCase.root, env })).stdout;
1066
+ logPerformance('buildSelectedTree', startedAt, { files: selectedPaths.length });
1067
+ return { tree, files: selectedPaths };
1068
+ } finally {
1069
+ try { fs.unlinkSync(temporaryIndex); } catch {}
1070
+ }
1071
+ }
1072
+
1073
+ async function emptyTree(legalCase, gitDir) {
1074
+ return (await runGit(legalCase.root, ['mktree'], { gitDir, input: '' })).stdout;
1075
+ }
1076
+
1077
+ function parseNameStatus(raw) {
1078
+ return String(raw || '').split(/\r?\n/).filter(Boolean).map((line) => {
1079
+ const columns = line.split('\t');
1080
+ return { status: columns[0] || 'M', path: columns.at(-1) || '', previousPath: columns.length > 2 ? columns[1] : null };
1081
+ });
1082
+ }
1083
+
1084
+ function statusKind(code) {
1085
+ const value = String(code || '').trim();
1086
+ if (value.includes('A') || value === '??') return 'added';
1087
+ if (value.includes('D')) return 'deleted';
1088
+ if (value.includes('R')) return 'renamed';
1089
+ return 'modified';
1090
+ }
1091
+
1092
+ async function diffTrees(legalCase, gitDir, from, to, manifests = null) {
1093
+ const raw = (await runGit(legalCase.root, ['diff-tree', '--no-commit-id', '--name-status', '-r', from, to], { gitDir })).stdout;
1094
+ const parsed = parseNameStatus(raw);
1095
+ const regular = parsed
1096
+ .filter((file) => file.path !== DOCX_MANIFEST_PATH)
1097
+ .map((file) => ({ ...file, kind: statusKind(file.status) }));
1098
+ let wordChanges = [];
1099
+ if (manifests) {
1100
+ wordChanges = docxChanges(manifests.before, manifests.after);
1101
+ } else if (parsed.some((file) => file.path === DOCX_MANIFEST_PATH)) {
1102
+ wordChanges = docxChanges(await treeDocxManifest(legalCase, gitDir, from), await treeDocxManifest(legalCase, gitDir, to));
1103
+ }
1104
+ return [...regular, ...wordChanges].sort((left, right) => left.path.localeCompare(right.path, 'fr'));
1105
+ }
1106
+
1107
+ async function workingState(casesRoot, homeDir, caseName) {
1108
+ const startedAt = performance.now();
1109
+ const legalCase = resolveCase(casesRoot, caseName);
1110
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
1111
+ const latest = await latestCommit(legalCase, gitDir);
1112
+ const base = latest || await emptyTree(legalCase, gitDir);
1113
+ const baselineDocx = latest ? await treeDocxManifest(legalCase, gitDir, base) : emptyDocxManifest();
1114
+ // L'admin compare le manifeste en mémoire. Il n'est écrit dans l'index Git
1115
+ // qu'au commit : aucun processus Git supplémentaire sur le chemin chaud.
1116
+ const current = await buildCurrentTree(legalCase, gitDir, homeDir, baselineDocx, { includeDocx: false });
1117
+ const changes = await diffTrees(legalCase, gitDir, base, current.tree, { before: baselineDocx, after: current.docxManifest });
1118
+ logPerformance('workingState', startedAt, { files: current.files.length, changes: changes.length });
1119
+ const state = { legalCase, gitDir, latest, current, base, baselineDocx, changes };
1120
+ caseStateCache.set(caseStateCacheKey(homeDir, legalCase), state);
1121
+ return state;
1122
+ }
1123
+
1124
+ /**
1125
+ * Structured git trailers appended at the end of a commit message.
1126
+ *
1127
+ * `PieceMaker-Session` is the durable join key between a case's commits and the
1128
+ * billing ledger (which records the authoritative final duration at session
1129
+ * Stop). `PieceMaker-Temps-Session` is the session time elapsed at the instant
1130
+ * of the commit — so the last commit of a session carries ~its full duration,
1131
+ * and every commit is self-documenting without needing the ledger. Both stay
1132
+ * parseable (`Clé: valeur`) and are read back by `listHistory` via `%b`.
1133
+ */
1134
+ function buildCommitTrailers({ sessionId, durationMs }) {
1135
+ const trailers = [];
1136
+ const session = String(sessionId || '').replace(/[\x00-\x1f\x7f]/g, '').trim().slice(0, 120);
1137
+ if (session) trailers.push(`PieceMaker-Session: ${session}`);
1138
+ if (Number.isFinite(durationMs) && durationMs >= 0) {
1139
+ const human = formatDurationFr(durationMs);
1140
+ if (human) trailers.push(`PieceMaker-Temps-Session: ${human} (${Math.round(durationMs)} ms)`);
1141
+ }
1142
+ return trailers;
1143
+ }
1144
+
1145
+ async function createCommit({
1146
+ casesRoot,
1147
+ caseName,
1148
+ homeDir = path.join(os.homedir(), '.piecemaker'),
1149
+ label = 'Commit PieceMaker',
1150
+ description = '',
1151
+ sessionId = null,
1152
+ durationMs = null,
1153
+ event = 'manual',
1154
+ paths = null,
1155
+ waitForLockMs = 0,
1156
+ identity = null,
1157
+ envFile = GLOBAL_ENV_FILE,
1158
+ } = {}) {
1159
+ const legalCase = resolveCase(casesRoot, caseName);
1160
+ caseStateCache.delete(caseStateCacheKey(homeDir, legalCase));
1161
+ const safeLabel = String(label || 'Commit PieceMaker').replace(/[\r\n]+/g, ' ').trim().slice(0, 140);
1162
+ const safeDescription = String(description || '').replaceAll('\0', '').replaceAll('\r\n', '\n').trim().slice(0, 4000);
1163
+ const selectedPaths = paths == null
1164
+ ? null
1165
+ : [...new Set((Array.isArray(paths) ? paths : [paths]).map((file) => validateRelativeSafePath(legalCase, file)))];
1166
+ return withCaseLock(homeDir, legalCase, async () => {
1167
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
1168
+ const parent = await latestCommit(legalCase, gitDir);
1169
+ const parentTree = parent
1170
+ ? (await runGit(legalCase.root, ['rev-parse', `${parent}^{tree}`], { gitDir })).stdout
1171
+ : await emptyTree(legalCase, gitDir);
1172
+ const baselineDocx = selectedPaths === null && parent
1173
+ ? await treeDocxManifest(legalCase, gitDir, parentTree)
1174
+ : emptyDocxManifest();
1175
+ const current = selectedPaths === null
1176
+ ? await buildCurrentTree(legalCase, gitDir, homeDir, baselineDocx)
1177
+ : await buildSelectedTree(legalCase, gitDir, homeDir, parent, selectedPaths);
1178
+ if (current.tree === parentTree) {
1179
+ return { created: false, commit: parent || null, caseName: legalCase.name, files: [] };
1180
+ }
1181
+
1182
+ const timestamp = new Date().toISOString();
1183
+ const trailers = buildCommitTrailers({ sessionId, durationMs });
1184
+ const message = `${safeLabel || 'Commit PieceMaker'}\n${safeDescription ? `\n${safeDescription}\n` : ''}${trailers.length ? `\n${trailers.join('\n')}\n` : ''}`;
1185
+ const commitIdentity = resolveCommitIdentity({ identity, envFile });
1186
+ const gitIdentity = {
1187
+ GIT_AUTHOR_NAME: commitIdentity.name,
1188
+ GIT_AUTHOR_EMAIL: commitIdentity.email,
1189
+ GIT_COMMITTER_NAME: commitIdentity.name,
1190
+ GIT_COMMITTER_EMAIL: commitIdentity.email,
1191
+ GIT_AUTHOR_DATE: timestamp,
1192
+ GIT_COMMITTER_DATE: timestamp,
1193
+ };
1194
+ const args = ['commit-tree', current.tree, ...(parent ? ['-p', parent] : [])];
1195
+ const commit = (await runGit(legalCase.root, args, { gitDir, env: gitIdentity, input: message })).stdout;
1196
+ await runGit(legalCase.root, ['update-ref', await activeHistoryRef(legalCase, gitDir), commit, ...(parent ? [parent] : [])], { gitDir });
1197
+ const files = await diffTrees(
1198
+ legalCase,
1199
+ gitDir,
1200
+ parentTree,
1201
+ current.tree,
1202
+ selectedPaths === null ? { before: baselineDocx, after: current.docxManifest } : null,
1203
+ );
1204
+ return {
1205
+ created: true,
1206
+ commit,
1207
+ parent: parent || null,
1208
+ timestamp,
1209
+ label: safeLabel || 'Commit PieceMaker',
1210
+ sessionId,
1211
+ durationMs: Number.isFinite(durationMs) && durationMs >= 0 ? durationMs : null,
1212
+ event,
1213
+ author: commitIdentity.name,
1214
+ caseName: legalCase.name,
1215
+ files,
1216
+ };
1217
+ }, { waitMs: waitForLockMs });
1218
+ }
1219
+
1220
+ function parseLog(raw) {
1221
+ return String(raw || '').split('\x1e').map((record) => record.trim()).filter(Boolean).map((record) => {
1222
+ const [hash, shortHash, author, timestamp, subject, ...body] = record.split('\x1f');
1223
+ return {
1224
+ hash,
1225
+ shortHash,
1226
+ author,
1227
+ timestamp,
1228
+ subject,
1229
+ body: body.join('\x1f').trim(),
1230
+ kind: 'commit',
1231
+ };
1232
+ }).filter((entry) => entry.hash);
1233
+ }
1234
+
1235
+ async function listHistory(casesRoot, homeDir, { caseName, limit = 120 } = {}) {
1236
+ const startedAt = performance.now();
1237
+ const legalCase = resolveCase(casesRoot, caseName);
1238
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
1239
+ if (!await latestCommit(legalCase, gitDir)) {
1240
+ logPerformance('listHistory', startedAt, { commits: 0 });
1241
+ return [];
1242
+ }
1243
+ const safeLimit = Math.min(Math.max(Number(limit) || 120, 1), 250);
1244
+ const historyRef = await activeHistoryRef(legalCase, gitDir);
1245
+ const raw = (await runGit(legalCase.root, [
1246
+ 'log', `--max-count=${safeLimit}`, '--date=iso-strict',
1247
+ '--pretty=format:%x1e%H%x1f%h%x1f%an%x1f%aI%x1f%s%x1f%b', historyRef,
1248
+ ], { gitDir })).stdout;
1249
+ const history = parseLog(raw);
1250
+ logPerformance('listHistory', startedAt, { commits: history.length, limit: safeLimit });
1251
+ return history;
1252
+ }
1253
+
1254
+ /**
1255
+ * Les mois `YYYY-MM` où le dossier a des commits, du plus récent au plus
1256
+ * ancien — alimente le menu déroulant de l'export mensuel. Une seule colonne
1257
+ * (`%aI`) suffit : dériver le mois ne demande que les 7 premiers caractères
1258
+ * d'une date ISO stricte, pas un `git log` structuré comme `listHistory`.
1259
+ */
1260
+ async function historyMonths(casesRoot, homeDir, { caseName } = {}) {
1261
+ const startedAt = performance.now();
1262
+ const legalCase = resolveCase(casesRoot, caseName);
1263
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
1264
+ if (!await latestCommit(legalCase, gitDir)) {
1265
+ logPerformance('historyMonths', startedAt, { months: 0 });
1266
+ return [];
1267
+ }
1268
+ const historyRef = await activeHistoryRef(legalCase, gitDir);
1269
+ const raw = (await runGit(legalCase.root, ['log', '--date=iso-strict', '--pretty=format:%aI', historyRef], { gitDir })).stdout;
1270
+ const months = [...new Set(
1271
+ raw.split('\n').map((line) => line.trim().slice(0, 7)).filter(Boolean)
1272
+ )].sort((left, right) => right.localeCompare(left));
1273
+ logPerformance('historyMonths', startedAt, { months: months.length });
1274
+ return months;
1275
+ }
1276
+
1277
+ /**
1278
+ * Variante de `parseLog` avec la liste des fichiers touchés par chaque
1279
+ * commit. Le format ajoute un `%x1f` terminal après le corps (`%b`) : ce
1280
+ * séparateur referme le champ « corps », multi-ligne, sans ambiguïté avec la
1281
+ * liste de fichiers de `--name-only` qui le suit jusqu'au `\x1e` du commit
1282
+ * suivant. `parseLog` reste inchangé pour `listHistory` (son format n'a pas
1283
+ * ce dernier séparateur).
1284
+ */
1285
+ function parseLogWithFiles(raw) {
1286
+ return String(raw || '').split('\x1e').map((record) => record.trim()).filter(Boolean).map((record) => {
1287
+ const fields = record.split('\x1f');
1288
+ const [hash, shortHash, author, timestamp, subject] = fields;
1289
+ // Entre le 5e séparateur et le dernier se trouve le corps (`%b`), qui ne
1290
+ // devrait jamais contenir de \x1f mais est rejoint par défense, comme le
1291
+ // fait déjà `parseLog` ; le tout dernier segment est la liste des
1292
+ // fichiers, un par ligne.
1293
+ const body = fields.slice(5, -1).join('\x1f').trim();
1294
+ const files = String(fields.at(-1) || '').split('\n').map((line) => line.trim()).filter(Boolean);
1295
+ return {
1296
+ hash,
1297
+ shortHash,
1298
+ author,
1299
+ timestamp,
1300
+ subject,
1301
+ body,
1302
+ kind: 'commit',
1303
+ files,
1304
+ filesCount: files.length,
1305
+ };
1306
+ }).filter((entry) => entry.hash);
1307
+ }
1308
+
1309
+ /**
1310
+ * Sépare les trailers techniques `PieceMaker-*` du corps d'un commit (voir
1311
+ * `buildCommitTrailers`). Miroir du parsing côté client
1312
+ * (`admin/app.js` → `parsePieceMakerTrailers`), avec en plus la durée brute
1313
+ * en millisecondes que l'affichage seul n'a pas besoin de connaître mais
1314
+ * qu'un export chiffré (temps facturable par mois) exploite directement.
1315
+ */
1316
+ function parseCommitTrailers(body) {
1317
+ const lines = String(body || '').split('\n');
1318
+ const kept = [];
1319
+ let sessionId = null;
1320
+ let durationMs = null;
1321
+ for (const line of lines) {
1322
+ const session = line.match(/^PieceMaker-Session:\s*(.+)$/);
1323
+ if (session) { sessionId = session[1].trim(); continue; }
1324
+ const time = line.match(/^PieceMaker-Temps-Session:\s*.+?\((\d+)\s*ms\)\s*$/);
1325
+ if (time) { durationMs = Number(time[1]); continue; }
1326
+ kept.push(line);
1327
+ }
1328
+ return { comment: kept.join('\n').trim(), sessionId, durationMs };
1329
+ }
1330
+
1331
+ /**
1332
+ * Commits d'une période `[since, until)`, fichiers touchés compris. `until`
1333
+ * est exclusif côté appelant (premier jour du mois suivant, typiquement) :
1334
+ * cette fonction ne fait aucune arithmétique de date, elle transmet telles
1335
+ * quelles à `--since`/`--until`. Pas de plafond façon `listHistory` — le hook
1336
+ * `PostToolUse` commite à chaque Write/Edit, un mois peut en compter des
1337
+ * milliers — seulement un plafond de sécurité large pour ne pas exploser
1338
+ * `MAX_GIT_BUFFER` sur un dossier anormalement actif.
1339
+ */
1340
+ async function listHistoryPeriod(casesRoot, homeDir, { caseName, since, until } = {}) {
1341
+ const startedAt = performance.now();
1342
+ const legalCase = resolveCase(casesRoot, caseName);
1343
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
1344
+ if (!await latestCommit(legalCase, gitDir)) {
1345
+ logPerformance('listHistoryPeriod', startedAt, { commits: 0 });
1346
+ return [];
1347
+ }
1348
+ const historyRef = await activeHistoryRef(legalCase, gitDir);
1349
+ const raw = (await runGit(legalCase.root, [
1350
+ 'log', `--max-count=${MAX_HISTORY_PERIOD_COMMITS}`, '--date=iso-strict', '--name-only',
1351
+ ...(since ? [`--since=${since}`] : []),
1352
+ ...(until ? [`--until=${until}`] : []),
1353
+ '--pretty=format:%x1e%H%x1f%h%x1f%an%x1f%aI%x1f%s%x1f%b%x1f', historyRef,
1354
+ ], { gitDir })).stdout;
1355
+ const history = parseLogWithFiles(raw).map((entry) => {
1356
+ const { comment, sessionId, durationMs } = parseCommitTrailers(entry.body);
1357
+ return { ...entry, comment, sessionId, durationMs };
1358
+ });
1359
+ logPerformance('listHistoryPeriod', startedAt, { commits: history.length, since, until });
1360
+ return history;
1361
+ }
1362
+
1363
+ function normalizeRelativeHistoryPath(relativePath) {
1364
+ const normalized = String(relativePath || '').replaceAll('\\', '/').replace(/^\.\//, '');
1365
+ if (!normalized || path.posix.isAbsolute(normalized) || normalized.split('/').includes('..')) {
1366
+ throw new Error('Chemin de fichier invalide.');
1367
+ }
1368
+ return normalized;
1369
+ }
1370
+
1371
+ function validateRelativeSafePath(legalCase, relativePath) {
1372
+ const normalized = normalizeRelativeHistoryPath(relativePath);
1373
+ const absolute = path.join(legalCase.root, ...normalized.split('/'));
1374
+ if (isProtectedFile(absolute, legalCase.root) || !SAFE_EXTENSIONS.has(path.extname(normalized).toLowerCase())) {
1375
+ throw new Error('Ce fichier n’est pas accessible à l’IA.');
1376
+ }
1377
+ return normalized;
1378
+ }
1379
+
1380
+ function validateRelativeHistoryPath(legalCase, relativePath) {
1381
+ const normalized = normalizeRelativeHistoryPath(relativePath);
1382
+ return isDocxPath(normalized) ? normalized : validateRelativeSafePath(legalCase, normalized);
1383
+ }
1384
+
1385
+ async function revisionMetadata(legalCase, gitDir, hash) {
1386
+ if (!/^[0-9a-f]{7,64}$/i.test(String(hash || ''))) throw new Error('Identifiant de révision invalide.');
1387
+ const commit = (await runGit(legalCase.root, ['rev-parse', '--verify', `${hash}^{commit}`], { gitDir })).stdout;
1388
+ if ((await runGit(legalCase.root, ['merge-base', '--is-ancestor', commit, await activeHistoryRef(legalCase, gitDir)], { gitDir, allowFailure: true })).code !== 0) {
1389
+ throw new Error('Cette révision ne fait pas partie de ce dossier juridique.');
1390
+ }
1391
+ const raw = (await runGit(legalCase.root, ['show', '-s', '--date=iso-strict', '--format=%H%x1f%h%x1f%an%x1f%aI%x1f%s%x1f%b', commit], { gitDir })).stdout;
1392
+ const [fullHash, shortHash, author, timestamp, subject, ...body] = raw.split('\x1f');
1393
+ return { commit, hash: fullHash, shortHash, author, timestamp, subject, body: body.join('\x1f').trim() };
1394
+ }
1395
+
1396
+ function parseShortStat(raw) {
1397
+ const value = String(raw || '');
1398
+ return {
1399
+ files: Number(value.match(/(\d+) files? changed/)?.[1] || 0),
1400
+ added: Number(value.match(/(\d+) insertions?\(\+\)/)?.[1] || 0),
1401
+ deleted: Number(value.match(/(\d+) deletions?\(-\)/)?.[1] || 0),
1402
+ };
1403
+ }
1404
+
1405
+ async function revisionDetails(casesRoot, homeDir, caseName, hash, filePath = '') {
1406
+ const startedAt = performance.now();
1407
+ const legalCase = resolveCase(casesRoot, caseName);
1408
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
1409
+ const meta = await revisionMetadata(legalCase, gitDir, hash);
1410
+ const commitTree = (await runGit(legalCase.root, ['rev-parse', `${meta.commit}^{tree}`], { gitDir })).stdout;
1411
+ const parent = await runGit(legalCase.root, ['rev-parse', '--verify', `${meta.commit}^`], { gitDir, allowFailure: true });
1412
+ const parentTree = parent.code === 0
1413
+ ? (await runGit(legalCase.root, ['rev-parse', `${parent.stdout}^{tree}`], { gitDir })).stdout
1414
+ : await emptyTree(legalCase, gitDir);
1415
+ const files = await diffTrees(legalCase, gitDir, parentTree, commitTree);
1416
+ const selectedPath = filePath ? validateRelativeHistoryPath(legalCase, filePath) : '';
1417
+ const selectedFile = selectedPath ? files.find((file) => file.path === selectedPath) : null;
1418
+ if (selectedPath && !selectedFile) throw new Error('Ce fichier ne fait pas partie de cette révision.');
1419
+ // Sur un commit complet, Git doit parcourir tous les blobs une deuxième fois
1420
+ // pour produire le shortstat. Le patch contient déjà l'information utile et
1421
+ // est borné ci-dessous : ne calculer les statistiques que pour un fichier
1422
+ // explicitement sélectionné évite ce parcours redondant.
1423
+ const wordDiff = isDocxPath(selectedPath)
1424
+ ? await docxTextDiff(
1425
+ legalCase,
1426
+ await treeDocxManifest(legalCase, gitDir, parentTree),
1427
+ await treeDocxManifest(legalCase, gitDir, commitTree),
1428
+ selectedPath,
1429
+ )
1430
+ : null;
1431
+ const stats = wordDiff?.stats || (selectedPath
1432
+ ? parseShortStat((await runGit(legalCase.root, [
1433
+ 'diff-tree', '--root', '--no-commit-id', '--shortstat', '-r', meta.commit, '--', selectedPath,
1434
+ ], { gitDir })).stdout)
1435
+ : { files: 0, added: 0, deleted: 0 });
1436
+ // Le premier clic sur un commit ne calcule que sa liste de fichiers. Le
1437
+ // patch, potentiellement volumineux, n'est demandé qu'après sélection d'un
1438
+ // fichier dans la colonne dédiée.
1439
+ const patchResult = wordDiff || (selectedPath
1440
+ ? await runGit(legalCase.root, [
1441
+ 'show', '--format=', '--no-ext-diff', '--unified=3', meta.commit, '--', selectedPath,
1442
+ ], {
1443
+ gitDir,
1444
+ maxOutputBytes: MAX_PATCH_BYTES,
1445
+ truncateOutput: true,
1446
+ })
1447
+ : { stdout: '', truncated: false });
1448
+ const result = {
1449
+ ...meta,
1450
+ kind: 'commit',
1451
+ files,
1452
+ filesCount: files.length,
1453
+ stats,
1454
+ selectedFile,
1455
+ selectedPath,
1456
+ patch: patchResult.stdout,
1457
+ truncated: patchResult.truncated,
1458
+ };
1459
+ logPerformance('revisionDetails', startedAt, {
1460
+ files: result.filesCount,
1461
+ selectedFile: Boolean(selectedPath),
1462
+ patchBytes: Buffer.byteLength(result.patch, 'utf8'),
1463
+ truncated: result.truncated,
1464
+ });
1465
+ return result;
1466
+ }
1467
+
1468
+ async function worktreeDetails(casesRoot, homeDir, caseName, filePath = '', snapshot = '') {
1469
+ const startedAt = performance.now();
1470
+ const legalCase = resolveCase(casesRoot, caseName);
1471
+ const cached = caseStateCache.get(caseStateCacheKey(homeDir, legalCase));
1472
+ const state = snapshot && cached?.current.snapshot === snapshot
1473
+ ? cached
1474
+ : await workingState(casesRoot, homeDir, caseName);
1475
+ const selectedPath = filePath ? validateRelativeHistoryPath(state.legalCase, filePath) : '';
1476
+ if (selectedPath && !state.changes.some((file) => file.path === selectedPath)) {
1477
+ throw new Error('Ce fichier ne fait pas partie des modifications actuelles.');
1478
+ }
1479
+ const selectedFile = selectedPath ? state.changes.find((file) => file.path === selectedPath) : null;
1480
+ const wordDiff = isDocxPath(selectedPath)
1481
+ ? await docxTextDiff(state.legalCase, state.baselineDocx, state.current.docxManifest, selectedPath)
1482
+ : null;
1483
+ const statsRaw = wordDiff || !selectedPath ? '' : (await runGit(state.legalCase.root, [
1484
+ 'diff', '--shortstat', state.base, state.current.tree, '--', selectedPath,
1485
+ ], { gitDir: state.gitDir })).stdout;
1486
+ const stats = wordDiff?.stats || parseShortStat(statsRaw);
1487
+ const patchResult = wordDiff || (!selectedPath
1488
+ ? { stdout: '', truncated: false }
1489
+ : await runGit(state.legalCase.root, [
1490
+ 'diff', '--no-ext-diff', '--unified=3', state.base, state.current.tree, '--', selectedPath,
1491
+ ], {
1492
+ gitDir: state.gitDir,
1493
+ maxOutputBytes: MAX_PATCH_BYTES,
1494
+ truncateOutput: true,
1495
+ }));
1496
+ const result = {
1497
+ hash: 'WORKTREE',
1498
+ shortHash: '',
1499
+ author: 'Modifications locales',
1500
+ timestamp: new Date().toISOString(),
1501
+ subject: 'Modifications depuis le dernier commit',
1502
+ kind: 'worktree',
1503
+ files: state.changes,
1504
+ filesCount: state.changes.length,
1505
+ stats,
1506
+ selectedFile,
1507
+ selectedPath,
1508
+ patch: patchResult.stdout,
1509
+ truncated: patchResult.truncated,
1510
+ };
1511
+ logPerformance('worktreeDetails', startedAt, {
1512
+ files: state.changes.length,
1513
+ selectedFile: Boolean(selectedPath),
1514
+ patchBytes: Buffer.byteLength(result.patch, 'utf8'),
1515
+ truncated: result.truncated,
1516
+ });
1517
+ return result;
1518
+ }
1519
+
1520
+ function listCases(casesRoot) {
1521
+ const requestedRoot = path.resolve(String(casesRoot || ''));
1522
+ if (!fs.existsSync(requestedRoot)) {
1523
+ return { name: 'PieceMaker', root: requestedRoot, branch: 'Dossiers indépendants', head: '', shortHead: '', folders: [], changes: [] };
1524
+ }
1525
+ const root = resolveCasesRoot(requestedRoot);
1526
+ const entries = fs.readdirSync(root, { withFileTypes: true })
1527
+ .filter((entry) => entry.isDirectory()
1528
+ && !entry.isSymbolicLink()
1529
+ && !entry.name.startsWith('.')
1530
+ && !isTechnicalCaseDirectoryName(entry.name))
1531
+ .sort((a, b) => a.name.localeCompare(b.name, 'fr'));
1532
+ return {
1533
+ name: path.basename(root),
1534
+ root,
1535
+ branch: 'Dossiers indépendants',
1536
+ head: '',
1537
+ shortHead: '',
1538
+ folders: entries.map((entry) => ({ name: entry.name, path: entry.name })),
1539
+ changes: [],
1540
+ };
1541
+ }
1542
+
1543
+ async function caseOverview(casesRoot, homeDir, caseName) {
1544
+ const startedAt = performance.now();
1545
+ const state = await workingState(casesRoot, homeDir, caseName);
1546
+ const originals = await originalFilesOverview(state.legalCase.root, { safeFiles: state.current.files });
1547
+ const enrichedChanges = await Promise.all(state.changes.map(async (change) => {
1548
+ if (change.kind === 'deleted') return change;
1549
+ try {
1550
+ const stat = await fsp.stat(path.join(state.legalCase.root, ...change.path.split('/')));
1551
+ return { ...change, modifiedAt: stat.mtime.toISOString() };
1552
+ } catch { return change; }
1553
+ }));
1554
+ const folder = {
1555
+ name: state.legalCase.name,
1556
+ path: state.legalCase.name,
1557
+ changes: enrichedChanges.length,
1558
+ workingChanges: enrichedChanges,
1559
+ head: state.latest,
1560
+ shortHead: state.latest.slice(0, 7),
1561
+ snapshot: state.current.snapshot,
1562
+ originals,
1563
+ protectedOriginals: originals.filter((file) => file.protected).length,
1564
+ };
1565
+ logPerformance('caseOverview', startedAt, {
1566
+ files: state.current.files.length,
1567
+ changes: state.changes.length,
1568
+ originals: originals.length,
1569
+ });
1570
+ return folder;
1571
+ }
1572
+
1573
+ async function repositoryOverview(casesRoot, homeDir = path.join(os.homedir(), '.piecemaker')) {
1574
+ const startedAt = performance.now();
1575
+ const repository = listCases(casesRoot);
1576
+ if (!repository.folders.length) {
1577
+ logPerformance('repositoryOverview', startedAt, { folders: 0 });
1578
+ return repository;
1579
+ }
1580
+ // Séquentiel : chaque dossier lance déjà une série de processus git, les
1581
+ // paralléliser en ferait exploser le nombre sur un poste de travail.
1582
+ const folders = [];
1583
+ for (const entry of repository.folders) {
1584
+ folders.push(await caseOverview(repository.root, homeDir, entry.name));
1585
+ }
1586
+ const result = { ...repository, folders };
1587
+ logPerformance('repositoryOverview', startedAt, {
1588
+ folders: folders.length,
1589
+ workingChanges: folders.reduce((count, folder) => count + folder.workingChanges.length, 0),
1590
+ originals: folders.reduce((count, folder) => count + folder.originals.length, 0),
1591
+ });
1592
+ return result;
1593
+ }
1594
+
1595
+ function safeDestination(legalCase, relativePath) {
1596
+ const normalized = validateRelativeSafePath(legalCase, relativePath);
1597
+ let current = legalCase.root;
1598
+ const parts = normalized.split('/');
1599
+ for (const part of parts.slice(0, -1)) {
1600
+ current = path.join(current, part);
1601
+ if (fs.existsSync(current) && fs.lstatSync(current).isSymbolicLink()) throw new Error('Restauration refusée à travers un lien symbolique.');
1602
+ }
1603
+ return { normalized, absolute: path.join(legalCase.root, ...parts) };
1604
+ }
1605
+
1606
+ async function restoreRevision({ casesRoot, caseName, homeDir = path.join(os.homedir(), '.piecemaker'), hash } = {}) {
1607
+ const legalCase = resolveCase(casesRoot, caseName);
1608
+ const gitDir = await ensureHistoryRepo(homeDir, legalCase);
1609
+ const meta = await revisionMetadata(legalCase, gitDir, hash);
1610
+ const safety = await createCommit({
1611
+ casesRoot: legalCase.casesRoot,
1612
+ caseName: legalCase.name,
1613
+ homeDir,
1614
+ label: `Sauvegarde avant restauration de ${meta.shortHash}`,
1615
+ event: 'before-restore',
1616
+ });
1617
+ if (safety.skipped === 'busy') throw new Error('Un commit est déjà en cours. Réessayez dans quelques secondes.');
1618
+
1619
+ const targetFiles = (await runGit(legalCase.root, ['ls-tree', '-r', '--name-only', meta.commit], { gitDir })).stdout
1620
+ .split(/\r?\n/)
1621
+ .filter((relative) => relative && relative !== DOCX_MANIFEST_PATH);
1622
+ const targetSet = new Set(targetFiles);
1623
+ for (const relative of await safeCaseFiles(legalCase.root)) {
1624
+ if (!targetSet.has(relative)) fs.unlinkSync(safeDestination(legalCase, relative).absolute);
1625
+ }
1626
+ for (const relative of targetFiles) {
1627
+ const destination = safeDestination(legalCase, relative);
1628
+ fs.mkdirSync(path.dirname(destination.absolute), { recursive: true });
1629
+ const content = (await runGit(legalCase.root, ['show', `${meta.commit}:${destination.normalized}`], { gitDir, encoding: null })).stdout;
1630
+ const temporary = `${destination.absolute}.piecemaker-${process.pid}.tmp`;
1631
+ fs.writeFileSync(temporary, content);
1632
+ fs.renameSync(temporary, destination.absolute);
1633
+ }
1634
+
1635
+ const restoredState = await createCommit({
1636
+ casesRoot: legalCase.casesRoot,
1637
+ caseName: legalCase.name,
1638
+ homeDir,
1639
+ label: `Restauration de ${meta.shortHash} · ${meta.subject}`,
1640
+ event: 'restore',
1641
+ });
1642
+ return {
1643
+ restored: true,
1644
+ revision: meta.commit,
1645
+ safetyCommit: safety.commit || null,
1646
+ restorationCommit: restoredState.commit || null,
1647
+ changes: (await workingState(legalCase.casesRoot, homeDir, legalCase.name)).changes,
1648
+ originalsPreserved: true,
1649
+ };
1650
+ }
1651
+
1652
+ module.exports = {
1653
+ COMMIT_USER_NAME_KEY,
1654
+ GLOBAL_ENV_FILE,
1655
+ IDENTITY_CONFIG_FILE,
1656
+ SAFE_EXTENSIONS,
1657
+ readCommitIdentityConfig,
1658
+ caseOverview,
1659
+ checkoutHistoryBranch,
1660
+ createCommit,
1661
+ createHistoryBranch,
1662
+ historyBranches,
1663
+ historyMonths,
1664
+ historyRepo,
1665
+ isProtectedFile,
1666
+ isTechnicalCaseDirectoryName,
1667
+ listCases,
1668
+ logPerformance,
1669
+ listHistory,
1670
+ listHistoryPeriod,
1671
+ locateCaseFile,
1672
+ parseCommitTrailers,
1673
+ originalFilesOverview,
1674
+ repositoryOverview,
1675
+ resolveCommitIdentity,
1676
+ resolveCase,
1677
+ resolveCasesRoot,
1678
+ restoreRevision,
1679
+ revisionDetails,
1680
+ runGit,
1681
+ safeCaseFiles,
1682
+ worktreeDetails,
1683
+ };