strikethroo 4.0.0 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (479) hide show
  1. package/README.md +16 -2
  2. package/dist/__tests__/fixtures/blueprint-trailing-summary.d.ts +14 -0
  3. package/dist/__tests__/fixtures/blueprint-trailing-summary.d.ts.map +1 -0
  4. package/dist/__tests__/fixtures/blueprint-trailing-summary.js +54 -0
  5. package/dist/__tests__/fixtures/blueprint-trailing-summary.js.map +1 -0
  6. package/dist/cli.js +23 -1
  7. package/dist/cli.js.map +1 -1
  8. package/dist/conflict-detector.d.ts +28 -12
  9. package/dist/conflict-detector.d.ts.map +1 -1
  10. package/dist/conflict-detector.js +45 -53
  11. package/dist/conflict-detector.js.map +1 -1
  12. package/dist/export-profile.d.ts +6 -0
  13. package/dist/export-profile.d.ts.map +1 -1
  14. package/dist/export-profile.js +46 -4
  15. package/dist/export-profile.js.map +1 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +97 -86
  18. package/dist/index.js.map +1 -1
  19. package/dist/metadata.d.ts +12 -1
  20. package/dist/metadata.d.ts.map +1 -1
  21. package/dist/metadata.js +76 -11
  22. package/dist/metadata.js.map +1 -1
  23. package/dist/profiles.d.ts.map +1 -1
  24. package/dist/profiles.js +52 -7
  25. package/dist/profiles.js.map +1 -1
  26. package/dist/prompts.d.ts +6 -0
  27. package/dist/prompts.d.ts.map +1 -1
  28. package/dist/prompts.js +47 -3
  29. package/dist/prompts.js.map +1 -1
  30. package/dist/serve/config-write.d.ts +6 -3
  31. package/dist/serve/config-write.d.ts.map +1 -1
  32. package/dist/serve/config-write.js +20 -21
  33. package/dist/serve/config-write.js.map +1 -1
  34. package/dist/serve/derivation.d.ts +17 -19
  35. package/dist/serve/derivation.d.ts.map +1 -1
  36. package/dist/serve/derivation.js +43 -82
  37. package/dist/serve/derivation.js.map +1 -1
  38. package/dist/serve/events.d.ts +37 -8
  39. package/dist/serve/events.d.ts.map +1 -1
  40. package/dist/serve/events.js +114 -28
  41. package/dist/serve/events.js.map +1 -1
  42. package/dist/serve/self-review.d.ts +37 -7
  43. package/dist/serve/self-review.d.ts.map +1 -1
  44. package/dist/serve/self-review.js +93 -33
  45. package/dist/serve/self-review.js.map +1 -1
  46. package/dist/serve/server.d.ts +107 -0
  47. package/dist/serve/server.d.ts.map +1 -1
  48. package/dist/serve/server.js +502 -135
  49. package/dist/serve/server.js.map +1 -1
  50. package/dist/serve/workspace-model.d.ts +11 -17
  51. package/dist/serve/workspace-model.d.ts.map +1 -1
  52. package/dist/serve/workspace-model.js +84 -83
  53. package/dist/serve/workspace-model.js.map +1 -1
  54. package/dist/skill-scripts/shared/blueprint-parse.d.ts +16 -0
  55. package/dist/skill-scripts/shared/blueprint-parse.d.ts.map +1 -0
  56. package/dist/skill-scripts/shared/blueprint-parse.js +66 -0
  57. package/dist/skill-scripts/shared/blueprint-parse.js.map +1 -0
  58. package/dist/skill-scripts/shared/root.d.ts +6 -0
  59. package/dist/skill-scripts/shared/root.d.ts.map +1 -1
  60. package/dist/skill-scripts/shared/root.js +10 -4
  61. package/dist/skill-scripts/shared/root.js.map +1 -1
  62. package/dist/skill-scripts/shared/safe-fs.d.ts +89 -0
  63. package/dist/skill-scripts/shared/safe-fs.d.ts.map +1 -0
  64. package/dist/skill-scripts/shared/safe-fs.js +324 -0
  65. package/dist/skill-scripts/shared/safe-fs.js.map +1 -0
  66. package/dist/types.d.ts +8 -0
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/types.js +13 -1
  69. package/dist/types.js.map +1 -1
  70. package/dist/update.d.ts.map +1 -1
  71. package/dist/update.js +15 -1
  72. package/dist/update.js.map +1 -1
  73. package/dist/validation/graph-checks.d.ts +6 -14
  74. package/dist/validation/graph-checks.d.ts.map +1 -1
  75. package/dist/validation/graph-checks.js +8 -15
  76. package/dist/validation/graph-checks.js.map +1 -1
  77. package/dist/validation/metadata-gate.d.ts +2 -6
  78. package/dist/validation/metadata-gate.d.ts.map +1 -1
  79. package/dist/validation/metadata-gate.js +17 -6
  80. package/dist/validation/metadata-gate.js.map +1 -1
  81. package/dist/validation/strict-pass.d.ts.map +1 -1
  82. package/dist/validation/strict-pass.js +50 -6
  83. package/dist/validation/strict-pass.js.map +1 -1
  84. package/dist-web/assets/abnfDiagram-VCTEODGH-CY8QEBrj.js +1 -0
  85. package/dist-web/assets/apl-gfMMiTNf.js +1 -0
  86. package/dist-web/assets/arc-Pry-7G1_.js +1 -0
  87. package/dist-web/assets/architecture-7GRP2DOG-drIky86B.js +1 -0
  88. package/dist-web/assets/architectureDiagram-5GKGNRK7-YZUSf-Fx.js +36 -0
  89. package/dist-web/assets/array-BifhSqXX.js +1 -0
  90. package/dist-web/assets/asciiarmor-C_eisQCp.js +1 -0
  91. package/dist-web/assets/asn1-DCl_8MCW.js +1 -0
  92. package/dist-web/assets/asterisk-BEn0Cwpx.js +1 -0
  93. package/dist-web/assets/blockDiagram-I7D4REHJ-ByyeaYP7.js +129 -0
  94. package/dist-web/assets/brainfuck-D5EjA2JK.js +1 -0
  95. package/dist-web/assets/c4Diagram-7LVT6UL2-YSA0IA7A.js +38 -0
  96. package/dist-web/assets/channel-DEeX8XvW.js +1 -0
  97. package/dist-web/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  98. package/dist-web/assets/chunk-4HAMMTFA-8VzDhfwy.js +62 -0
  99. package/dist-web/assets/{chunk-FMBD7UC4-zW3dYoIJ.js → chunk-5VM5RSS4-ZNzvKenW.js} +2 -2
  100. package/dist-web/assets/chunk-75Z2AOVW-D3fZto5-.js +2 -0
  101. package/dist-web/assets/chunk-DU6HZSFF-vtUmBAxv.js +125 -0
  102. package/dist-web/assets/chunk-F27PBJKO-BMcZVmbf.js +1 -0
  103. package/dist-web/assets/chunk-FOHPRMQF-DzxwRta7.js +161 -0
  104. package/dist-web/assets/chunk-GMAD6QVW-C5gwfNkR.js +72 -0
  105. package/dist-web/assets/chunk-GVQU2GXP-CqFZMp6I.js +1 -0
  106. package/dist-web/assets/chunk-IMKFNOWR-CJDfPbiX.js +231 -0
  107. package/dist-web/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  108. package/dist-web/assets/chunk-L3NEJ4N5-CHeJ2XSW.js +1 -0
  109. package/dist-web/assets/chunk-OSK3NFVY-CXOClbf5.js +10 -0
  110. package/dist-web/assets/chunk-P2QGCYS3-C9Wc2Z2I.js +1 -0
  111. package/dist-web/assets/chunk-POPQ4Y6H-CfiiGKfO.js +1 -0
  112. package/dist-web/assets/chunk-PWAF6VOD-CtZ4gx65.js +1 -0
  113. package/dist-web/assets/chunk-SHT3W25Y-C50-QCrR.js +168 -0
  114. package/dist-web/assets/chunk-SVP7TREG-EIHQbPfX.js +88 -0
  115. package/dist-web/assets/chunk-TICWLB2K-DOB5NZ4R.js +206 -0
  116. package/dist-web/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
  117. package/dist-web/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  118. package/dist-web/assets/classDiagram-ZZMXUADV-H5H_txsg.js +1 -0
  119. package/dist-web/assets/classDiagram-v2-VYDZK3BY-H5H_txsg.js +1 -0
  120. package/dist-web/assets/clike-D_6L3tnO.js +1 -0
  121. package/dist-web/assets/clojure-BflJGmDX.js +1 -0
  122. package/dist-web/assets/cmake-84nbDH0I.js +1 -0
  123. package/dist-web/assets/cobol-DHLQUbN7.js +1 -0
  124. package/dist-web/assets/coffeescript-De_zI4J0.js +1 -0
  125. package/dist-web/assets/commonlisp-DgAKBe0r.js +1 -0
  126. package/dist-web/assets/cose-bilkent-JH36ORCC-BEpcWcmK.js +1 -0
  127. package/dist-web/assets/crystal-Bsdphhtm.js +1 -0
  128. package/dist-web/assets/css-CnaYoQib.js +1 -0
  129. package/dist-web/assets/cynefin-OW5HDTMX-mR6pfDSH.js +1 -0
  130. package/dist-web/assets/cynefinDiagram-5FMLGOSQ-6-2oQdEg.js +62 -0
  131. package/dist-web/assets/cypher-p9eYesGn.js +1 -0
  132. package/dist-web/assets/cytoscape.esm-Yq6u8L66.js +321 -0
  133. package/dist-web/assets/d-DWkQyNnU.js +1 -0
  134. package/dist-web/assets/dagre-C-rnJpZF.js +1 -0
  135. package/dist-web/assets/dagre-GXQ25YYZ-Cm1zvIWj.js +4 -0
  136. package/dist-web/assets/defaultLocale-BFoDCU3G.js +1 -0
  137. package/dist-web/assets/diagram-S7CK7UJ4-D6mECnyP.js +30 -0
  138. package/dist-web/assets/diagram-UQ7AKVKN-CzmXABVS.js +41 -0
  139. package/dist-web/assets/diagram-VSXAHHWV-CpEauecU.js +3 -0
  140. package/dist-web/assets/diagram-VX7I27RA-CXPYrCgX.js +24 -0
  141. package/dist-web/assets/diagram-Z3DM3KII-RcMIMVWZ.js +24 -0
  142. package/dist-web/assets/diff-ChtP43wD.js +1 -0
  143. package/dist-web/assets/dist--eYrBgi0.js +2 -0
  144. package/dist-web/assets/dist-B-O4eZD_.js +1 -0
  145. package/dist-web/assets/dist-B27L6oW0.js +1 -0
  146. package/dist-web/assets/dist-BKXbBuAc.js +1 -0
  147. package/dist-web/assets/dist-BPcC0hnc.js +9 -0
  148. package/dist-web/assets/dist-BgwxV8e_.js +1 -0
  149. package/dist-web/assets/dist-BlG40nRw.js +1 -0
  150. package/dist-web/assets/dist-Bqc6e86z.js +1 -0
  151. package/dist-web/assets/dist-BsvASXHG.js +1 -0
  152. package/dist-web/assets/dist-C15GN054.js +1 -0
  153. package/dist-web/assets/dist-C4QRmcTO.js +1 -0
  154. package/dist-web/assets/dist-C4lZy0XG.js +6 -0
  155. package/dist-web/assets/dist-CFLbFzpB.js +23 -0
  156. package/dist-web/assets/dist-CP6AUVtv.js +1 -0
  157. package/dist-web/assets/dist-CpYnHHz6.js +1 -0
  158. package/dist-web/assets/dist-DHnGmK79.js +1 -0
  159. package/dist-web/assets/dist-DYmIHv0n.js +13 -0
  160. package/dist-web/assets/dist-DauRO0RO.js +1 -0
  161. package/dist-web/assets/dist-Day7i26p.js +1 -0
  162. package/dist-web/assets/dist-Do_t70vA.js +1 -0
  163. package/dist-web/assets/dist-G8nWWSie.js +11 -0
  164. package/dist-web/assets/dist-QfYLz_N1.js +1 -0
  165. package/dist-web/assets/dist-TZhb2tj2.js +1 -0
  166. package/dist-web/assets/dist-Wr2Wo_KE.js +1 -0
  167. package/dist-web/assets/dist-kYRo7Db1.js +1 -0
  168. package/dist-web/assets/dist-kfqV1Lu-.js +2 -0
  169. package/dist-web/assets/dist-v5Q1xZ2K.js +1 -0
  170. package/dist-web/assets/dockerfile-DJkHQgkl.js +1 -0
  171. package/dist-web/assets/dtd-DTF72YNO.js +1 -0
  172. package/dist-web/assets/dylan-BCDoL_-p.js +1 -0
  173. package/dist-web/assets/ebnf-D4c0_ac3.js +1 -0
  174. package/dist-web/assets/ebnfDiagram-PWID7BFC-MZpZ_VnU.js +1 -0
  175. package/dist-web/assets/ecl-BVIeWmwY.js +1 -0
  176. package/dist-web/assets/eiffel-BEjRio4Q.js +1 -0
  177. package/dist-web/assets/elm-Cshzl8qu.js +1 -0
  178. package/dist-web/assets/erDiagram-RLTQ6QDP-BcZ7Ctxy.js +99 -0
  179. package/dist-web/assets/erlang-BV0c4Hdn.js +1 -0
  180. package/dist-web/assets/esm-CQW0DO89.js +2 -0
  181. package/dist-web/assets/eventmodeling-NTZA5JFV-BwLlQZcI.js +1 -0
  182. package/dist-web/assets/factor-LKH5gN8L.js +1 -0
  183. package/dist-web/assets/fcl-ClOhbFR7.js +1 -0
  184. package/dist-web/assets/flowDiagram-HODETNUW-DGqUYaRC.js +1 -0
  185. package/dist-web/assets/forth-D6RzAl64.js +1 -0
  186. package/dist-web/assets/fortran-Bt6PBEDR.js +1 -0
  187. package/dist-web/assets/ganttDiagram-EL5Y4UJY-CcJ72sCU.js +292 -0
  188. package/dist-web/assets/gas-BHEdbvp9.js +1 -0
  189. package/dist-web/assets/gherkin-oBAE_ms0.js +1 -0
  190. package/dist-web/assets/gitGraph-4MIJSDKK-BheSjO6S.js +1 -0
  191. package/dist-web/assets/gitGraphDiagram-WWUBYQGX-Qv13SyYh.js +106 -0
  192. package/dist-web/assets/graphlib-DS17s2tU.js +1 -0
  193. package/dist-web/assets/groovy-CUpZ7dEl.js +1 -0
  194. package/dist-web/assets/haskell-BRsoo5mP.js +1 -0
  195. package/dist-web/assets/haxe-DjVOVvNP.js +1 -0
  196. package/dist-web/assets/http-CLVgA2GD.js +1 -0
  197. package/dist-web/assets/idl-BUZw3wgd.js +1 -0
  198. package/dist-web/assets/index-D0npIBvI.css +2 -0
  199. package/dist-web/assets/index-DsQxKERJ.js +103 -0
  200. package/dist-web/assets/info-A6RAGUB7-BemnwZ_B.js +1 -0
  201. package/dist-web/assets/infoDiagram-27XIBGKW-otpjj8PV.js +2 -0
  202. package/dist-web/assets/init-C-OQMol4.js +1 -0
  203. package/dist-web/assets/ishikawaDiagram-5VMMS53U-BuZBZkYN.js +70 -0
  204. package/dist-web/assets/javascript-Bu8mWwtz.js +1 -0
  205. package/dist-web/assets/journeyDiagram-3NMN7TZE-D-uflaQS.js +139 -0
  206. package/dist-web/assets/julia-CQfgDRfP.js +1 -0
  207. package/dist-web/assets/kanban-definition-UXKFOSKX-BI643rxH.js +89 -0
  208. package/dist-web/assets/katex-ZlcWpGUi.js +257 -0
  209. package/dist-web/assets/line-fay7lQM4.js +1 -0
  210. package/dist-web/assets/linear-SzVmGSw4.js +1 -0
  211. package/dist-web/assets/livescript-BXxG0Yva.js +1 -0
  212. package/dist-web/assets/lua-DPCEkfD_.js +1 -0
  213. package/dist-web/assets/mathematica-u8YMmbU0.js +1 -0
  214. package/dist-web/assets/mbox-BEMVcqjs.js +1 -0
  215. package/dist-web/assets/mermaid-parser.core-CI9Bt8lf.js +7 -0
  216. package/dist-web/assets/mermaid.core-CpvTzp9Q.js +44 -0
  217. package/dist-web/assets/mindmap-definition-YA3MSWOX-Dw-DFKfU.js +96 -0
  218. package/dist-web/assets/{mirc-CjQqDB4T.js → mirc-C9zpzAZU.js} +1 -1
  219. package/dist-web/assets/mllike-B45xgp2S.js +1 -0
  220. package/dist-web/assets/modelica-CqHI_q-D.js +1 -0
  221. package/dist-web/assets/mscgen-qgSLujhx.js +1 -0
  222. package/dist-web/assets/mumps-BSzj6Xyz.js +1 -0
  223. package/dist-web/assets/{nginx-DdIZxoE0.js → nginx-8H7HVH4w.js} +1 -1
  224. package/dist-web/assets/nsis-CfSuhXs5.js +1 -0
  225. package/dist-web/assets/ntriples-B9h1VB_g.js +1 -0
  226. package/dist-web/assets/octave-D2Q8cUp1.js +1 -0
  227. package/dist-web/assets/ordinal-BDEzSJ7C.js +1 -0
  228. package/dist-web/assets/oz-BwTct_5T.js +1 -0
  229. package/dist-web/assets/packet-AYTQ26CC-CsBrScsn.js +1 -0
  230. package/dist-web/assets/pascal-Dp_KdFgX.js +1 -0
  231. package/dist-web/assets/path-fybaL0A-.js +1 -0
  232. package/dist-web/assets/pegDiagram-XKGWAZYB-BVal7Apj.js +1 -0
  233. package/dist-web/assets/perl-BkSkiI9m.js +1 -0
  234. package/dist-web/assets/pie-WAS4IAKB-DZFMDceO.js +1 -0
  235. package/dist-web/assets/pieDiagram-E7YTZNPT-B3QEKixf.js +39 -0
  236. package/dist-web/assets/pig-AF4Hwhju.js +1 -0
  237. package/dist-web/assets/powershell-BcIto6Sf.js +1 -0
  238. package/dist-web/assets/properties-C357ku5U.js +1 -0
  239. package/dist-web/assets/protobuf-D1ij_kNL.js +1 -0
  240. package/dist-web/assets/pug-3K-JMW4g.js +1 -0
  241. package/dist-web/assets/puppet-BZyAS7I4.js +1 -0
  242. package/dist-web/assets/python-B_1Jd8HM.js +1 -0
  243. package/dist-web/assets/q-B9NhS7L_.js +1 -0
  244. package/dist-web/assets/quadrantDiagram-AXDQQJYC-CRgAf_p-.js +7 -0
  245. package/dist-web/assets/r-CxDmU1I4.js +1 -0
  246. package/dist-web/assets/radar-RG4KPBEZ-BkOoPAbJ.js +1 -0
  247. package/dist-web/assets/railroad-74A4TZTK-BgIna4sT.js +1 -0
  248. package/dist-web/assets/railroad-abnf-HS5TGJTU-CVlFeN1b.js +1 -0
  249. package/dist-web/assets/railroad-ebnf-LZEXJU2U-DCEa0WVT.js +1 -0
  250. package/dist-web/assets/railroad-peg-WCYAUIDC-BHX1T-4x.js +1 -0
  251. package/dist-web/assets/railroadDiagram-O6MQD6OU-BZwRaQM3.js +1 -0
  252. package/dist-web/assets/requirementDiagram-BXWQKSXE-BN3nmFpY.js +84 -0
  253. package/dist-web/assets/rolldown-runtime-hePW80VL.js +1 -0
  254. package/dist-web/assets/rough.esm-Dy-Kn_BL.js +1 -0
  255. package/dist-web/assets/rpm-gpDK5sbt.js +1 -0
  256. package/dist-web/assets/ruby-BjXV7-Qa.js +1 -0
  257. package/dist-web/assets/sankeyDiagram-P5KCCOFB-DBhFOKcq.js +40 -0
  258. package/dist-web/assets/{sas-B4kiWyti.js → sas-C2OyD2Y6.js} +1 -1
  259. package/dist-web/assets/scheme-D9qYN0V5.js +1 -0
  260. package/dist-web/assets/sequenceDiagram-WJ2MYXX4-CBc9y9xq.js +162 -0
  261. package/dist-web/assets/shell-DwuoZtxw.js +1 -0
  262. package/dist-web/assets/sieve-tLWDfEkZ.js +1 -0
  263. package/dist-web/assets/simple-mode-DXiLM1-G.js +1 -0
  264. package/dist-web/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
  265. package/dist-web/assets/smalltalk-BLp5-jwC.js +1 -0
  266. package/dist-web/assets/solr-B78wSQJQ.js +1 -0
  267. package/dist-web/assets/sparql-Dz-mlCAC.js +1 -0
  268. package/dist-web/assets/spreadsheet-CTIncYxj.js +1 -0
  269. package/dist-web/assets/sql-DuQMFDvy.js +1 -0
  270. package/dist-web/assets/src-B6xuSHsQ.js +1 -0
  271. package/dist-web/assets/stateDiagram-D77RDMKH-BDdsXTTr.js +1 -0
  272. package/dist-web/assets/stateDiagram-v2-MP3YSRHH-C04o4SeT.js +1 -0
  273. package/dist-web/assets/stex-DNzd62Q_.js +1 -0
  274. package/dist-web/assets/stylus-BOVgKnng.js +1 -0
  275. package/dist-web/assets/swift-DKB6_1j6.js +1 -0
  276. package/dist-web/assets/swimlanes-42K2YHIH-1QXV5L5H.js +1 -0
  277. package/dist-web/assets/swimlanesDiagram-VR7AAH4N-CQ46EU90.js +8 -0
  278. package/dist-web/assets/tcl-BGfruO1u.js +1 -0
  279. package/dist-web/assets/textile-C4jVoHG1.js +1 -0
  280. package/dist-web/assets/tiddlywiki-VlUiK86J.js +1 -0
  281. package/dist-web/assets/tiki-AK6FwT8q.js +1 -0
  282. package/dist-web/assets/timeline-definition-24CTP7MA-D9CdAGEV.js +120 -0
  283. package/dist-web/assets/toml-BPTmHmyx.js +1 -0
  284. package/dist-web/assets/treeView-Q6P3EWNA-CxKfpZsz.js +1 -0
  285. package/dist-web/assets/treemap-WGGIJYW6-Bg5-PJ6G.js +1 -0
  286. package/dist-web/assets/troff-C2dAgh7P.js +1 -0
  287. package/dist-web/assets/ttcn-PPSTk1ow.js +1 -0
  288. package/dist-web/assets/ttcn-cfg-2b4Gb5sE.js +1 -0
  289. package/dist-web/assets/turtle-Cx3rYX2g.js +1 -0
  290. package/dist-web/assets/vb-BthdM_4N.js +1 -0
  291. package/dist-web/assets/vbscript-D9f6rSsU.js +1 -0
  292. package/dist-web/assets/velocity-CqftRsjg.js +1 -0
  293. package/dist-web/assets/vennDiagram-4TSXK5OY-DIlZEQm_.js +34 -0
  294. package/dist-web/assets/verilog-CjI9Y6RI.js +1 -0
  295. package/dist-web/assets/vhdl-kS471soi.js +1 -0
  296. package/dist-web/assets/wardley-WFR3VGLG-DCKFxH5V.js +1 -0
  297. package/dist-web/assets/wardleyDiagram-VM6X3IG4-D8O8WtAP.js +78 -0
  298. package/dist-web/assets/webidl-D5jiJvOU.js +1 -0
  299. package/dist-web/assets/xquery-BKJx4mf9.js +1 -0
  300. package/dist-web/assets/xychartDiagram-S5SC5T6Z-Dz9bYgtE.js +7 -0
  301. package/dist-web/assets/yacas-CXXgtw0p.js +1 -0
  302. package/dist-web/assets/z80-Co3PbHdE.js +1 -0
  303. package/dist-web/index.html +6 -18
  304. package/dist-web/theme-guard.js +21 -0
  305. package/package.json +34 -26
  306. package/templates/strikethroo/config/config.yaml +2 -2
  307. package/templates/strikethroo/config/templates/TASK_TEMPLATE.md +1 -1
  308. package/dist-web/assets/apl-B4CMkyY2.js +0 -1
  309. package/dist-web/assets/arc-DA6tr0lU.js +0 -1
  310. package/dist-web/assets/architectureDiagram-3BPJPVTR-BEH2YihV.js +0 -36
  311. package/dist-web/assets/asciiarmor-Df11BRmG.js +0 -1
  312. package/dist-web/assets/asn1-EdZsLKOL.js +0 -1
  313. package/dist-web/assets/asterisk-B-8jnY81.js +0 -1
  314. package/dist-web/assets/blockDiagram-GPEHLZMM-jgUyFGxx.js +0 -132
  315. package/dist-web/assets/brainfuck-C4LP7Hcl.js +0 -1
  316. package/dist-web/assets/c4Diagram-AAUBKEIU-Do-n7I5O.js +0 -10
  317. package/dist-web/assets/channel-DJ33z8Wx.js +0 -1
  318. package/dist-web/assets/chunk-2J33WTMH-CgMvCn22.js +0 -1
  319. package/dist-web/assets/chunk-4BX2VUAB-FO8RQkkL.js +0 -1
  320. package/dist-web/assets/chunk-55IACEB6-DL_6pZjw.js +0 -1
  321. package/dist-web/assets/chunk-727SXJPM-DW7J3hiD.js +0 -206
  322. package/dist-web/assets/chunk-AQP2D5EJ-TPWnvFSC.js +0 -231
  323. package/dist-web/assets/chunk-ND2GUHAM-D0Nmkz3P.js +0 -1
  324. package/dist-web/assets/chunk-QZHKN3VN-BxgxRNWB.js +0 -1
  325. package/dist-web/assets/classDiagram-4FO5ZUOK--tqQjy0s.js +0 -1
  326. package/dist-web/assets/classDiagram-v2-Q7XG4LA2--tqQjy0s.js +0 -1
  327. package/dist-web/assets/clike-B9uivgTg.js +0 -1
  328. package/dist-web/assets/clojure-BMjYHr_A.js +0 -1
  329. package/dist-web/assets/cmake-BQqOBYOt.js +0 -1
  330. package/dist-web/assets/cobol-CWcv1MsR.js +0 -1
  331. package/dist-web/assets/coffeescript-S37ZYGWr.js +0 -1
  332. package/dist-web/assets/commonlisp-DBKNyK5s.js +0 -1
  333. package/dist-web/assets/cose-bilkent-S5V4N54A-ysHXC5GT.js +0 -1
  334. package/dist-web/assets/crystal-SjHAIU92.js +0 -1
  335. package/dist-web/assets/css-BnMrqG3P.js +0 -1
  336. package/dist-web/assets/cypher-C_CwsFkJ.js +0 -1
  337. package/dist-web/assets/cytoscape.esm-BHYC38rz.js +0 -331
  338. package/dist-web/assets/d-pRatUO7H.js +0 -1
  339. package/dist-web/assets/dagre-BM42HDAG-G_XIk8Dj.js +0 -4
  340. package/dist-web/assets/defaultLocale-CrowFXzY.js +0 -1
  341. package/dist-web/assets/diagram-2AECGRRQ-7HG2PLhr.js +0 -43
  342. package/dist-web/assets/diagram-5GNKFQAL-BdS1bF_R.js +0 -10
  343. package/dist-web/assets/diagram-KO2AKTUF-AFaiXGZQ.js +0 -3
  344. package/dist-web/assets/diagram-LMA3HP47-CTWrauj7.js +0 -24
  345. package/dist-web/assets/diagram-OG6HWLK6-BmBckGLa.js +0 -24
  346. package/dist-web/assets/diff-DbItnlRl.js +0 -1
  347. package/dist-web/assets/dockerfile-BKs6k2Af.js +0 -1
  348. package/dist-web/assets/dtd-DF_7sFjM.js +0 -1
  349. package/dist-web/assets/dylan-DwRh75JA.js +0 -1
  350. package/dist-web/assets/ebnf-CDyGwa7X.js +0 -1
  351. package/dist-web/assets/ecl-Cabwm37j.js +0 -1
  352. package/dist-web/assets/eiffel-CnydiIhH.js +0 -1
  353. package/dist-web/assets/elm-vLlmbW-K.js +0 -1
  354. package/dist-web/assets/erDiagram-TEJ5UH35-C0B2cXE-.js +0 -85
  355. package/dist-web/assets/erlang-BNw1qcRV.js +0 -1
  356. package/dist-web/assets/factor-kuTfRLto.js +0 -1
  357. package/dist-web/assets/fcl-Kvtd6kyn.js +0 -1
  358. package/dist-web/assets/flowDiagram-I6XJVG4X-CZ70tn_Q.js +0 -162
  359. package/dist-web/assets/forth-Ffai-XNe.js +0 -1
  360. package/dist-web/assets/fortran-DYz_wnZ1.js +0 -1
  361. package/dist-web/assets/ganttDiagram-6RSMTGT7-h7O-Xh-D.js +0 -292
  362. package/dist-web/assets/gas-Bneqetm1.js +0 -1
  363. package/dist-web/assets/gherkin-heZmZLOM.js +0 -1
  364. package/dist-web/assets/gitGraphDiagram-PVQCEYII-BDZixURw.js +0 -106
  365. package/dist-web/assets/graph-Dqkl27Ch.js +0 -1
  366. package/dist-web/assets/groovy-D9Dt4D0W.js +0 -1
  367. package/dist-web/assets/haskell-BWDZoCOh.js +0 -1
  368. package/dist-web/assets/haxe-H-WmDvRZ.js +0 -1
  369. package/dist-web/assets/http-DBlCnlav.js +0 -1
  370. package/dist-web/assets/idl-BEugSyMb.js +0 -1
  371. package/dist-web/assets/index-B-KlYMEI.js +0 -1
  372. package/dist-web/assets/index-B0a4C4Lb.js +0 -1
  373. package/dist-web/assets/index-B90tvIxG.js +0 -3
  374. package/dist-web/assets/index-BLXIwDvb.js +0 -1
  375. package/dist-web/assets/index-BjZYUODU.js +0 -1
  376. package/dist-web/assets/index-BmsczLPZ.js +0 -1
  377. package/dist-web/assets/index-BpU7RpGz.js +0 -1
  378. package/dist-web/assets/index-BwFIiA6J.js +0 -2
  379. package/dist-web/assets/index-C53NKwQ5.js +0 -1
  380. package/dist-web/assets/index-C73riuQN.js +0 -1
  381. package/dist-web/assets/index-C9RcHSPW.js +0 -1
  382. package/dist-web/assets/index-CEBV-m_B.js +0 -1
  383. package/dist-web/assets/index-CG1O2Vjg.js +0 -1
  384. package/dist-web/assets/index-CRL66wiY.js +0 -169
  385. package/dist-web/assets/index-CddJufqj.js +0 -1
  386. package/dist-web/assets/index-CrzBaw1K.css +0 -1
  387. package/dist-web/assets/index-CuBsNWzH.js +0 -13
  388. package/dist-web/assets/index-CuCAyRTw.js +0 -7
  389. package/dist-web/assets/index-CuUh3dvS.js +0 -1
  390. package/dist-web/assets/index-CwPWc9jQ.js +0 -1
  391. package/dist-web/assets/index-DHBbud_j.js +0 -1
  392. package/dist-web/assets/index-LLaxWDbg.js +0 -1
  393. package/dist-web/assets/index-XOpAvr0E.js +0 -13
  394. package/dist-web/assets/index-aX67gnlS.js +0 -2
  395. package/dist-web/assets/index-lkaAPBmM.js +0 -6
  396. package/dist-web/assets/index-pUkuW0EP.js +0 -1
  397. package/dist-web/assets/index-sbfqG9cy.js +0 -1
  398. package/dist-web/assets/index-udFbjSlZ.js +0 -2
  399. package/dist-web/assets/index-yjEPVwyN.js +0 -1
  400. package/dist-web/assets/infoDiagram-5YYISTIA-CKXHxMh_.js +0 -2
  401. package/dist-web/assets/init-Gi6I4Gst.js +0 -1
  402. package/dist-web/assets/ishikawaDiagram-YF4QCWOH-DGancylI.js +0 -70
  403. package/dist-web/assets/javascript-qCveANmP.js +0 -1
  404. package/dist-web/assets/journeyDiagram-JHISSGLW-DifvKy-w.js +0 -139
  405. package/dist-web/assets/julia-DuME0IfC.js +0 -1
  406. package/dist-web/assets/kanban-definition-UN3LZRKU-ByC-4YyY.js +0 -89
  407. package/dist-web/assets/katex-C5jXJg4s.js +0 -257
  408. package/dist-web/assets/layout-DO9UvE1P.js +0 -1
  409. package/dist-web/assets/linear-Cm0Y2OWD.js +0 -1
  410. package/dist-web/assets/livescript-BwQOo05w.js +0 -1
  411. package/dist-web/assets/lua-VAEuO923.js +0 -1
  412. package/dist-web/assets/mathematica-DTrFuWx2.js +0 -1
  413. package/dist-web/assets/mbox-CNhZ1qSd.js +0 -1
  414. package/dist-web/assets/mermaid.core-DBlLt9sa.js +0 -307
  415. package/dist-web/assets/mindmap-definition-RKZ34NQL-tkThiQWd.js +0 -96
  416. package/dist-web/assets/mllike-CXdrOF99.js +0 -1
  417. package/dist-web/assets/modelica-Dc1JOy9r.js +0 -1
  418. package/dist-web/assets/mscgen-BA5vi2Kp.js +0 -1
  419. package/dist-web/assets/mumps-BT43cFF4.js +0 -1
  420. package/dist-web/assets/nsis-LdVXkNf5.js +0 -1
  421. package/dist-web/assets/ntriples-BfvgReVJ.js +0 -1
  422. package/dist-web/assets/octave-Ck1zUtKM.js +0 -1
  423. package/dist-web/assets/ordinal-Cboi1Yqb.js +0 -1
  424. package/dist-web/assets/oz-BzwKVEFT.js +0 -1
  425. package/dist-web/assets/pascal--L3eBynH.js +0 -1
  426. package/dist-web/assets/perl-CdXCOZ3F.js +0 -1
  427. package/dist-web/assets/pieDiagram-4H26LBE5-BXGBVjcj.js +0 -30
  428. package/dist-web/assets/pig-CevX1Tat.js +0 -1
  429. package/dist-web/assets/powershell-CFHJl5sT.js +0 -1
  430. package/dist-web/assets/properties-C78fOPTZ.js +0 -1
  431. package/dist-web/assets/protobuf-ChK-085T.js +0 -1
  432. package/dist-web/assets/pug-DukmZTjD.js +0 -1
  433. package/dist-web/assets/puppet-DMA9R1ak.js +0 -1
  434. package/dist-web/assets/python-BuPzkPfP.js +0 -1
  435. package/dist-web/assets/q-pXgVlZs6.js +0 -1
  436. package/dist-web/assets/quadrantDiagram-W4KKPZXB-DnF0iEBo.js +0 -7
  437. package/dist-web/assets/r-DUYO_cvP.js +0 -1
  438. package/dist-web/assets/requirementDiagram-4Y6WPE33-BooGjmPb.js +0 -84
  439. package/dist-web/assets/rpm-CTu-6PCP.js +0 -1
  440. package/dist-web/assets/ruby-B2Rjki9n.js +0 -1
  441. package/dist-web/assets/sankeyDiagram-5OEKKPKP-7le5uaC7.js +0 -40
  442. package/dist-web/assets/scheme-C41bIUwD.js +0 -1
  443. package/dist-web/assets/sequenceDiagram-3UESZ5HK-B9GCKMDd.js +0 -162
  444. package/dist-web/assets/shell-CjFT_Tl9.js +0 -1
  445. package/dist-web/assets/sieve-C3Gn_uJK.js +0 -1
  446. package/dist-web/assets/simple-mode-GW_nhZxv.js +0 -1
  447. package/dist-web/assets/smalltalk-CnHTOXQT.js +0 -1
  448. package/dist-web/assets/solr-DehyRSwq.js +0 -1
  449. package/dist-web/assets/sparql-DkYu6x3z.js +0 -1
  450. package/dist-web/assets/spreadsheet-BCZA_wO0.js +0 -1
  451. package/dist-web/assets/sql-D0XecflT.js +0 -1
  452. package/dist-web/assets/stateDiagram-AJRCARHV-CO2qL8R6.js +0 -1
  453. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-DUkgqBTd.js +0 -1
  454. package/dist-web/assets/stex-C3f8Ysf7.js +0 -1
  455. package/dist-web/assets/stylus-B533Al4x.js +0 -1
  456. package/dist-web/assets/swift-BzpIVaGY.js +0 -1
  457. package/dist-web/assets/tcl-DVfN8rqt.js +0 -1
  458. package/dist-web/assets/textile-CnDTJFAw.js +0 -1
  459. package/dist-web/assets/tiddlywiki-DO-Gjzrf.js +0 -1
  460. package/dist-web/assets/tiki-DGYXhP31.js +0 -1
  461. package/dist-web/assets/timeline-definition-PNZ67QCA-FLzWM85F.js +0 -120
  462. package/dist-web/assets/toml-Bm5Em-hy.js +0 -1
  463. package/dist-web/assets/troff-wAsdV37c.js +0 -1
  464. package/dist-web/assets/ttcn-CfJYG6tj.js +0 -1
  465. package/dist-web/assets/ttcn-cfg-B9xdYoR4.js +0 -1
  466. package/dist-web/assets/turtle-B1tBg_DP.js +0 -1
  467. package/dist-web/assets/vb-CmGdzxic.js +0 -1
  468. package/dist-web/assets/vbscript-BuJXcnF6.js +0 -1
  469. package/dist-web/assets/velocity-D8B20fx6.js +0 -1
  470. package/dist-web/assets/vennDiagram-CIIHVFJN-Dt6p6Ib1.js +0 -34
  471. package/dist-web/assets/verilog-C6RDOZhf.js +0 -1
  472. package/dist-web/assets/vhdl-lSbBsy5d.js +0 -1
  473. package/dist-web/assets/wardley-L42UT6IY-D6k_B5It.js +0 -173
  474. package/dist-web/assets/wardleyDiagram-YWT4CUSO-jT3ItNLi.js +0 -78
  475. package/dist-web/assets/webidl-ZXfAyPTL.js +0 -1
  476. package/dist-web/assets/xquery-CQfU5ijd.js +0 -1
  477. package/dist-web/assets/xychartDiagram-2RQKCTM6-CpM6UhUO.js +0 -7
  478. package/dist-web/assets/yacas-BJ4BC0dw.js +0 -1
  479. package/dist-web/assets/z80-Hz9HOZM7.js +0 -1
@@ -3,15 +3,30 @@
3
3
  *
4
4
  * Provides `GET /api/events`: a `text/event-stream` that broadcasts a single
5
5
  * coalesced `changed` ping whenever the workspace mutates on disk. The event
6
- * carries no diff payload — clients refetch the affected API data (the browser
7
- * consumer is a later plan).
6
+ * carries no diff payload — clients refetch the affected API data.
8
7
  *
9
8
  * Exposes an {@link EventsHub} that owns the connected-client set and the
10
9
  * workspace watcher, plus an `ApiHandler` the server registers so this module
11
- * stays decoupled from routing. Connections are cleaned up on disconnect so no
12
- * listeners or sockets leak. Node built-ins only.
10
+ * stays decoupled from routing. Delivery is bounded per session: at most
11
+ * {@link MAX_SSE_CLIENTS} streams are admitted, a client whose socket stops
12
+ * accepting data is written to only once more (one coalesced `changed` on
13
+ * `drain`), and one still blocked after {@link BLOCKED_TIMEOUT_MS} is ended and
14
+ * removed. Disconnect and {@link EventsHub.close} release every per-client
15
+ * timer and listener so nothing leaks. Node built-ins only.
13
16
  */
14
17
  import * as http from 'http';
18
+ /** Keep-alive comment interval (ms) to hold idle proxies/streams open. */
19
+ export declare const KEEP_ALIVE_MS = 15000;
20
+ /** Upper bound on concurrently connected SSE clients per hub. */
21
+ export declare const MAX_SSE_CLIENTS = 16;
22
+ /** How long (ms) a client may stay blocked on backpressure before it is dropped. */
23
+ export declare const BLOCKED_TIMEOUT_MS = 30000;
24
+ /** The compiled bounds; tests shorten them through the constructor. */
25
+ export interface EventsHubLimits {
26
+ maxClients: number;
27
+ blockedTimeoutMs: number;
28
+ keepAliveMs: number;
29
+ }
15
30
  /**
16
31
  * Owns the SSE client set and the workspace watcher. One hub per server. Start
17
32
  * the watcher with {@link start} after the server is listening; release it with
@@ -22,16 +37,30 @@ export declare class EventsHub {
22
37
  private readonly debounceMs?;
23
38
  private readonly clients;
24
39
  private watcher;
25
- constructor(workspaceDir: string, debounceMs?: number | undefined);
40
+ private readonly limits;
41
+ constructor(workspaceDir: string, debounceMs?: number | undefined, limits?: Partial<EventsHubLimits>);
26
42
  /** Begins watching the workspace; coalesced changes broadcast to all clients. */
27
43
  start(): void;
28
44
  /** Stops the watcher and ends every open client connection. */
29
45
  close(): void;
30
46
  /** Number of currently connected SSE clients (used by tests). */
31
47
  get clientCount(): number;
32
- /** Sends a single coalesced `changed` event to every connected client. */
33
- private broadcast;
34
- /** Attaches an SSE response: writes headers, registers cleanup on close. */
48
+ /** Number of connected clients currently held back by backpressure. */
49
+ get blockedClientCount(): number;
50
+ /**
51
+ * Sends a single coalesced `changed` event to every connected client. A
52
+ * blocked client is owed exactly one `changed` on `drain`, however many
53
+ * broadcasts it misses. Called by the watcher; public so tests can drive the
54
+ * stream without touching disk.
55
+ */
56
+ broadcast(): void;
57
+ /**
58
+ * Writes one chunk, honoring backpressure: when `write()` returns `false` the
59
+ * client is marked blocked, further writes are skipped, a `drain` listener is
60
+ * armed to resume, and the slow timer starts.
61
+ */
62
+ private send;
63
+ /** Attaches an SSE response, or refuses it with `503` when at capacity. */
35
64
  handleConnection(req: http.IncomingMessage, res: http.ServerResponse): void;
36
65
  /** An {@link ApiHandler} for `GET /api/events`; returns false otherwise. */
37
66
  apiHandler: (req: http.IncomingMessage, res: http.ServerResponse, ctx: {
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAM7B;;;;GAIG;AACH,qBAAa,SAAS;IAKlB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAL9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,OAAO,CAAiC;gBAG7B,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,YAAA;IAGtC,iFAAiF;IACjF,KAAK,IAAI,IAAI;IASb,+DAA+D;IAC/D,KAAK,IAAI,IAAI;IAWb,iEAAiE;IACjE,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,0EAA0E;IAC1E,OAAO,CAAC,SAAS;IAMjB,4EAA4E;IAC5E,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,GAAG,IAAI;IAyB3E,4EAA4E;IAC5E,UAAU,GACR,KAAK,IAAI,CAAC,eAAe,EACzB,KAAK,IAAI,CAAC,cAAc,EACxB,KAAK;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KACxB,OAAO,CAMR;CACH"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,0EAA0E;AAC1E,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,iEAAiE;AACjE,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAQxC,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD;;;;GAIG;AACH,qBAAa,SAAS;IAMlB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAN9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+C;IACvE,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAGtB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,YAAA,EACpC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IASvC,iFAAiF;IACjF,KAAK,IAAI,IAAI;IASb,+DAA+D;IAC/D,KAAK,IAAI,IAAI;IAab,iEAAiE;IACjE,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,uEAAuE;IACvE,IAAI,kBAAkB,IAAI,MAAM,CAI/B;IAED;;;;;OAKG;IACH,SAAS,IAAI,IAAI;IAOjB;;;;OAIG;IACH,OAAO,CAAC,IAAI;IAYZ,2EAA2E;IAC3E,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,GAAG,IAAI;IAyD3E,4EAA4E;IAC5E,UAAU,GACR,KAAK,IAAI,CAAC,eAAe,EACzB,KAAK,IAAI,CAAC,cAAc,EACxB,KAAK;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KACxB,OAAO,CAMR;CACH"}
@@ -4,29 +4,40 @@
4
4
  *
5
5
  * Provides `GET /api/events`: a `text/event-stream` that broadcasts a single
6
6
  * coalesced `changed` ping whenever the workspace mutates on disk. The event
7
- * carries no diff payload — clients refetch the affected API data (the browser
8
- * consumer is a later plan).
7
+ * carries no diff payload — clients refetch the affected API data.
9
8
  *
10
9
  * Exposes an {@link EventsHub} that owns the connected-client set and the
11
10
  * workspace watcher, plus an `ApiHandler` the server registers so this module
12
- * stays decoupled from routing. Connections are cleaned up on disconnect so no
13
- * listeners or sockets leak. Node built-ins only.
11
+ * stays decoupled from routing. Delivery is bounded per session: at most
12
+ * {@link MAX_SSE_CLIENTS} streams are admitted, a client whose socket stops
13
+ * accepting data is written to only once more (one coalesced `changed` on
14
+ * `drain`), and one still blocked after {@link BLOCKED_TIMEOUT_MS} is ended and
15
+ * removed. Disconnect and {@link EventsHub.close} release every per-client
16
+ * timer and listener so nothing leaks. Node built-ins only.
14
17
  */
15
18
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.EventsHub = void 0;
19
+ exports.EventsHub = exports.BLOCKED_TIMEOUT_MS = exports.MAX_SSE_CLIENTS = exports.KEEP_ALIVE_MS = void 0;
17
20
  const watcher_1 = require("./watcher");
18
21
  /** Keep-alive comment interval (ms) to hold idle proxies/streams open. */
19
- const KEEP_ALIVE_MS = 15000;
22
+ exports.KEEP_ALIVE_MS = 15000;
23
+ /** Upper bound on concurrently connected SSE clients per hub. */
24
+ exports.MAX_SSE_CLIENTS = 16;
25
+ /** How long (ms) a client may stay blocked on backpressure before it is dropped. */
26
+ exports.BLOCKED_TIMEOUT_MS = 30000;
27
+ /** `Retry-After` (seconds) sent with the `503` for a refused connection. */
28
+ const RETRY_AFTER_SECONDS = 5;
29
+ const CHANGED_EVENT = 'event: changed\ndata: {}\n\n';
30
+ const KEEP_ALIVE_COMMENT = ': keep-alive\n\n';
20
31
  /**
21
32
  * Owns the SSE client set and the workspace watcher. One hub per server. Start
22
33
  * the watcher with {@link start} after the server is listening; release it with
23
34
  * {@link close} when the server closes.
24
35
  */
25
36
  class EventsHub {
26
- constructor(workspaceDir, debounceMs) {
37
+ constructor(workspaceDir, debounceMs, limits = {}) {
27
38
  this.workspaceDir = workspaceDir;
28
39
  this.debounceMs = debounceMs;
29
- this.clients = new Set();
40
+ this.clients = new Map();
30
41
  this.watcher = null;
31
42
  /** An {@link ApiHandler} for `GET /api/events`; returns false otherwise. */
32
43
  this.apiHandler = (req, res, ctx) => {
@@ -36,6 +47,11 @@ class EventsHub {
36
47
  }
37
48
  return false;
38
49
  };
50
+ this.limits = {
51
+ maxClients: limits.maxClients ?? exports.MAX_SSE_CLIENTS,
52
+ blockedTimeoutMs: limits.blockedTimeoutMs ?? exports.BLOCKED_TIMEOUT_MS,
53
+ keepAliveMs: limits.keepAliveMs ?? exports.KEEP_ALIVE_MS,
54
+ };
39
55
  }
40
56
  /** Begins watching the workspace; coalesced changes broadcast to all clients. */
41
57
  start() {
@@ -49,42 +65,112 @@ class EventsHub {
49
65
  this.watcher.close();
50
66
  this.watcher = null;
51
67
  }
52
- for (const res of this.clients) {
53
- res.end();
68
+ for (const [res, state] of [...this.clients]) {
69
+ state.cleanup();
70
+ // A blocked socket cannot flush an `end()`; drop it instead.
71
+ if (state.blocked)
72
+ res.destroy();
73
+ else
74
+ res.end();
54
75
  }
55
- this.clients.clear();
56
76
  }
57
77
  /** Number of currently connected SSE clients (used by tests). */
58
78
  get clientCount() {
59
79
  return this.clients.size;
60
80
  }
61
- /** Sends a single coalesced `changed` event to every connected client. */
81
+ /** Number of connected clients currently held back by backpressure. */
82
+ get blockedClientCount() {
83
+ let count = 0;
84
+ for (const state of this.clients.values())
85
+ if (state.blocked)
86
+ count += 1;
87
+ return count;
88
+ }
89
+ /**
90
+ * Sends a single coalesced `changed` event to every connected client. A
91
+ * blocked client is owed exactly one `changed` on `drain`, however many
92
+ * broadcasts it misses. Called by the watcher; public so tests can drive the
93
+ * stream without touching disk.
94
+ */
62
95
  broadcast() {
63
- for (const res of this.clients) {
64
- res.write('event: changed\ndata: {}\n\n');
96
+ for (const [res, state] of this.clients) {
97
+ if (state.blocked)
98
+ state.pending = true;
99
+ else
100
+ this.send(res, state, CHANGED_EVENT);
65
101
  }
66
102
  }
67
- /** Attaches an SSE response: writes headers, registers cleanup on close. */
103
+ /**
104
+ * Writes one chunk, honoring backpressure: when `write()` returns `false` the
105
+ * client is marked blocked, further writes are skipped, a `drain` listener is
106
+ * armed to resume, and the slow timer starts.
107
+ */
108
+ send(res, state, chunk) {
109
+ if (state.blocked)
110
+ return;
111
+ if (res.write(chunk))
112
+ return;
113
+ state.blocked = true;
114
+ res.once('drain', state.onDrain);
115
+ state.slowTimer = setTimeout(() => {
116
+ state.cleanup();
117
+ res.destroy();
118
+ }, this.limits.blockedTimeoutMs);
119
+ state.slowTimer.unref?.();
120
+ }
121
+ /** Attaches an SSE response, or refuses it with `503` when at capacity. */
68
122
  handleConnection(req, res) {
123
+ if (this.clients.size >= this.limits.maxClients) {
124
+ const body = JSON.stringify({ error: 'Too many event-stream clients.' });
125
+ res.writeHead(503, {
126
+ 'Content-Type': 'application/json; charset=utf-8',
127
+ 'Content-Length': Buffer.byteLength(body),
128
+ 'Retry-After': String(RETRY_AFTER_SECONDS),
129
+ });
130
+ res.end(body);
131
+ return;
132
+ }
69
133
  res.writeHead(200, {
70
134
  'Content-Type': 'text/event-stream',
71
135
  'Cache-Control': 'no-cache',
72
136
  Connection: 'keep-alive',
73
137
  });
74
- // Initial comment opens the stream and flushes headers to the client.
75
- res.write(': connected\n\n');
76
- this.clients.add(res);
77
- const keepAlive = setInterval(() => {
78
- res.write(': keep-alive\n\n');
79
- }, KEEP_ALIVE_MS);
80
- // Don't let the keep-alive timer hold the event loop / process open.
81
- keepAlive.unref?.();
82
- const cleanup = () => {
83
- clearInterval(keepAlive);
84
- this.clients.delete(res);
138
+ const state = {
139
+ blocked: false,
140
+ pending: false,
141
+ keepAlive: setInterval(() => this.send(res, state, KEEP_ALIVE_COMMENT), this.limits.keepAliveMs),
142
+ slowTimer: null,
143
+ onDrain: () => {
144
+ if (!this.clients.has(res))
145
+ return;
146
+ state.blocked = false;
147
+ if (state.slowTimer) {
148
+ clearTimeout(state.slowTimer);
149
+ state.slowTimer = null;
150
+ }
151
+ if (state.pending) {
152
+ state.pending = false;
153
+ this.send(res, state, CHANGED_EVENT);
154
+ }
155
+ },
156
+ cleanup: () => {
157
+ if (!this.clients.delete(res))
158
+ return;
159
+ clearInterval(state.keepAlive);
160
+ if (state.slowTimer)
161
+ clearTimeout(state.slowTimer);
162
+ res.removeListener('drain', state.onDrain);
163
+ req.removeListener('close', state.cleanup);
164
+ res.removeListener('close', state.cleanup);
165
+ },
85
166
  };
86
- req.on('close', cleanup);
87
- res.on('close', cleanup);
167
+ // Don't let the keep-alive timer hold the event loop / process open.
168
+ state.keepAlive.unref?.();
169
+ this.clients.set(res, state);
170
+ req.on('close', state.cleanup);
171
+ res.on('close', state.cleanup);
172
+ // Initial comment opens the stream and flushes headers to the client.
173
+ this.send(res, state, ': connected\n\n');
88
174
  }
89
175
  }
90
176
  exports.EventsHub = EventsHub;
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAGH,uCAAqE;AAErE,0EAA0E;AAC1E,MAAM,aAAa,GAAG,KAAK,CAAC;AAE5B;;;;GAIG;AACH,MAAa,SAAS;IAIpB,YACmB,YAAoB,EACpB,UAAmB;QADnB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,eAAU,GAAV,UAAU,CAAS;QALrB,YAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;QAClD,YAAO,GAA4B,IAAI,CAAC;QAmEhD,4EAA4E;QAC5E,eAAU,GAAG,CACX,GAAyB,EACzB,GAAwB,EACxB,GAAyB,EAChB,EAAE;YACX,IAAI,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,GAAG,CAAC,QAAQ,KAAK,cAAc,EAAE,CAAC;gBACtE,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;IAzEC,CAAC;IAEJ,iFAAiF;IACjF,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAA,gCAAsB,EACnC,IAAI,CAAC,YAAY,EACjB,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,EACtB,IAAI,CAAC,UAAU,CAChB,CAAC;IACJ,CAAC;IAED,+DAA+D;IAC/D,KAAK;QACH,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,iEAAiE;IACjE,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,0EAA0E;IAClE,SAAS;QACf,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,GAAG,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,gBAAgB,CAAC,GAAyB,EAAE,GAAwB;QAClE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,UAAU,EAAE,YAAY;SACzB,CAAC,CAAC;QACH,sEAAsE;QACtE,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAE7B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YACjC,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAChC,CAAC,EAAE,aAAa,CAAC,CAAC;QAClB,qEAAqE;QACrE,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;QAEpB,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,aAAa,CAAC,SAAS,CAAC,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC;CAcF;AAjFD,8BAiFC"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":"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"}
@@ -14,9 +14,17 @@
14
14
  * Untrusted input (the path string) is never passed to the shell: `spawn` is
15
15
  * invoked with an argv array, and the path is rejected before spawning unless it
16
16
  * resolves to an existing file under `plans/` or `archive/`. Node built-ins only.
17
+ *
18
+ * Launches are bounded: a {@link LaunchRegistry} tracks the plans whose child is
19
+ * still running, refusing a duplicate for the same plan and anything past
20
+ * {@link MAX_CONCURRENT_SELF_REVIEWS}. The registry is in-memory and per server
21
+ * instance: a restart resets the accounting, and the detached children — which
22
+ * the viewer never waits on — can outlive it. It is not a job manager.
17
23
  */
18
24
  /** The binary name looked up on PATH and spawned. */
19
25
  export declare const SELF_REVIEW_BINARY = "self-review";
26
+ /** Upper bound on self-review children running at once per server instance. */
27
+ export declare const MAX_CONCURRENT_SELF_REVIEWS = 2;
20
28
  /** Where to obtain self-review; surfaced by the SPA when it is not installed. */
21
29
  export declare const SELF_REVIEW_URL = "https://github.com/e0ipso/self-review";
22
30
  /**
@@ -40,11 +48,26 @@ export interface LaunchResult {
40
48
  ok: false;
41
49
  error: string;
42
50
  };
51
+ /** Extra response headers (e.g. `Retry-After` on a busy refusal). */
52
+ headers?: Record<string, string>;
53
+ }
54
+ /**
55
+ * The plans (by canonical absolute path) whose self-review child is running.
56
+ * One per server instance; see the module comment for what it is not.
57
+ */
58
+ export type LaunchRegistry = Set<string>;
59
+ /** Creates an empty {@link LaunchRegistry}. */
60
+ export declare const createLaunchRegistry: () => LaunchRegistry;
61
+ /** The slice of `ChildProcess` the launcher relies on; fakes implement it. */
62
+ export interface SpawnedChild {
63
+ once(event: string, listener: (...args: never[]) => void): unknown;
64
+ unref(): void;
43
65
  }
44
- /** Seams for testing: availability probe and the detached spawn. */
66
+ /** Seams for testing: availability probe, the spawn, and the registry. */
45
67
  export interface LaunchDeps {
46
68
  available?: () => boolean;
47
- spawnDetached?: (command: string, args: string[]) => void;
69
+ spawn?: (command: string, args: string[]) => SpawnedChild;
70
+ registry?: LaunchRegistry;
48
71
  }
49
72
  /**
50
73
  * Resolves a client-supplied plan path to an absolute path, requiring it to be
@@ -54,7 +77,10 @@ export interface LaunchDeps {
54
77
  * `root` is the absolute `.ai/strikethroo` directory; client paths are the
55
78
  * workspace-relative form the SPA shows (e.g. `.ai/strikethroo/plans/NN--s/…`),
56
79
  * so they are resolved against the project root (`root/../..`). Absolute client
57
- * paths are accepted too — the containment check is what enforces safety.
80
+ * paths are accepted too — the containment check is what enforces safety: the
81
+ * lexical check below picks the subtree, and the shared helper walks the real
82
+ * components so a symlinked plan file or directory is refused rather than
83
+ * followed out of the workspace.
58
84
  */
59
85
  export declare const resolveReviewPath: (root: string, clientPath: string) => {
60
86
  absPath: string;
@@ -63,9 +89,13 @@ export declare const resolveReviewPath: (root: string, clientPath: string) => {
63
89
  status: number;
64
90
  };
65
91
  /**
66
- * Validates `clientPath` and, if the binary is available, launches
67
- * `self-review <absolutePath>` detached. Pure of HTTP concerns: returns the
68
- * status/body the endpoint should send so it stays unit-testable.
92
+ * Validates `clientPath` and, if the binary is available and a slot is free,
93
+ * launches `self-review <absolutePath>` detached. Resolves `200` only after the
94
+ * child's `spawn` event; a launch `error` (e.g. `ENOENT`) is a fixed `500`. The
95
+ * plan's slot is taken synchronously before the spawn, so two simultaneous
96
+ * requests for one plan cannot both launch, and is released — idempotently —
97
+ * when the child exits, errors, or fails to launch. Pure of HTTP concerns:
98
+ * returns the status/body the endpoint should send so it stays unit-testable.
69
99
  */
70
- export declare const launchSelfReview: (root: string, clientPath: string, deps?: LaunchDeps) => LaunchResult;
100
+ export declare const launchSelfReview: (root: string, clientPath: string, deps?: LaunchDeps) => Promise<LaunchResult>;
71
101
  //# sourceMappingURL=self-review.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"self-review.d.ts","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,iFAAiF;AACjF,eAAO,MAAM,eAAe,0CAA0C,CAAC;AAmCvE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,KACpD,OAQF,CAAC;AAEF,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC3D;AAWD;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,YAAY,MAAM,KACjB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CA4BvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,YAAY,MAAM,EAClB,OAAM,UAAe,KACpB,YAwBF,CAAC"}
1
+ {"version":3,"file":"self-review.d.ts","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,+EAA+E;AAC/E,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAK7C,iFAAiF;AACjF,eAAO,MAAM,eAAe,0CAA0C,CAAC;AAmCvE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,KACpD,OAQF,CAAC;AAEF,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;AAEzC,+CAA+C;AAC/C,eAAO,MAAM,oBAAoB,QAAO,cAAmC,CAAC;AAK5E,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC;IACnE,KAAK,IAAI,IAAI,CAAC;CACf;AAED,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,YAAY,CAAC;IAC1D,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAkBD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,YAAY,MAAM,KACjB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAqCvD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,YAAY,MAAM,EAClB,OAAM,UAAe,KACpB,OAAO,CAAC,YAAY,CAmDtB,CAAC"}
@@ -15,6 +15,12 @@
15
15
  * Untrusted input (the path string) is never passed to the shell: `spawn` is
16
16
  * invoked with an argv array, and the path is rejected before spawning unless it
17
17
  * resolves to an existing file under `plans/` or `archive/`. Node built-ins only.
18
+ *
19
+ * Launches are bounded: a {@link LaunchRegistry} tracks the plans whose child is
20
+ * still running, refusing a duplicate for the same plan and anything past
21
+ * {@link MAX_CONCURRENT_SELF_REVIEWS}. The registry is in-memory and per server
22
+ * instance: a restart resets the accounting, and the detached children — which
23
+ * the viewer never waits on — can outlive it. It is not a job manager.
18
24
  */
19
25
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
20
26
  if (k2 === undefined) k2 = k;
@@ -50,12 +56,17 @@ var __importStar = (this && this.__importStar) || (function () {
50
56
  };
51
57
  })();
52
58
  Object.defineProperty(exports, "__esModule", { value: true });
53
- exports.launchSelfReview = exports.resolveReviewPath = exports.isSelfReviewAvailable = exports.SELF_REVIEW_URL = exports.SELF_REVIEW_BINARY = void 0;
59
+ exports.launchSelfReview = exports.resolveReviewPath = exports.createLaunchRegistry = exports.isSelfReviewAvailable = exports.SELF_REVIEW_URL = exports.MAX_CONCURRENT_SELF_REVIEWS = exports.SELF_REVIEW_BINARY = void 0;
54
60
  const fs = __importStar(require("fs"));
55
61
  const path = __importStar(require("path"));
56
62
  const child_process_1 = require("child_process");
63
+ const safe_fs_1 = require("../skill-scripts/shared/safe-fs");
57
64
  /** The binary name looked up on PATH and spawned. */
58
65
  exports.SELF_REVIEW_BINARY = 'self-review';
66
+ /** Upper bound on self-review children running at once per server instance. */
67
+ exports.MAX_CONCURRENT_SELF_REVIEWS = 2;
68
+ /** Seconds a client should wait before retrying a `429` launch. */
69
+ const BUSY_RETRY_AFTER_SECONDS = 30;
59
70
  /** Where to obtain self-review; surfaced by the SPA when it is not installed. */
60
71
  exports.SELF_REVIEW_URL = 'https://github.com/e0ipso/self-review';
61
72
  /** Cache key derived from the environment inputs that affect the PATH scan. */
@@ -104,13 +115,21 @@ const isSelfReviewAvailable = (env = process.env) => {
104
115
  return result;
105
116
  };
106
117
  exports.isSelfReviewAvailable = isSelfReviewAvailable;
107
- /** Spawns the binary detached and unref'd so it outlives the request. */
108
- const spawnDetached = (command, args) => {
109
- const child = (0, child_process_1.spawn)(command, args, { stdio: 'ignore', detached: true });
110
- child.on('error', () => {
111
- /* a failed launch must not crash the server */
112
- });
113
- child.unref();
118
+ /** Creates an empty {@link LaunchRegistry}. */
119
+ const createLaunchRegistry = () => new Set();
120
+ exports.createLaunchRegistry = createLaunchRegistry;
121
+ /** Fallback registry for callers that do not own one (tests pass their own). */
122
+ const defaultRegistry = (0, exports.createLaunchRegistry)();
123
+ /** Spawns the binary detached with no stdio so it can outlive the request. */
124
+ const spawnDetached = (command, args) => (0, child_process_1.spawn)(command, args, { stdio: 'ignore', detached: true });
125
+ /** Resolves once the child reports `spawn`; rejects on a launch `error`. */
126
+ const awaitSpawn = (child) => new Promise((resolve, reject) => {
127
+ child.once('spawn', () => resolve());
128
+ child.once('error', (err) => reject(err));
129
+ });
130
+ const LAUNCH_FAILED = {
131
+ status: 500,
132
+ body: { ok: false, error: 'Failed to launch self-review.' },
114
133
  };
115
134
  /**
116
135
  * Resolves a client-supplied plan path to an absolute path, requiring it to be
@@ -120,40 +139,56 @@ const spawnDetached = (command, args) => {
120
139
  * `root` is the absolute `.ai/strikethroo` directory; client paths are the
121
140
  * workspace-relative form the SPA shows (e.g. `.ai/strikethroo/plans/NN--s/…`),
122
141
  * so they are resolved against the project root (`root/../..`). Absolute client
123
- * paths are accepted too — the containment check is what enforces safety.
142
+ * paths are accepted too — the containment check is what enforces safety: the
143
+ * lexical check below picks the subtree, and the shared helper walks the real
144
+ * components so a symlinked plan file or directory is refused rather than
145
+ * followed out of the workspace.
124
146
  */
125
147
  const resolveReviewPath = (root, clientPath) => {
126
148
  if (typeof clientPath !== 'string' || clientPath.trim() === '') {
127
149
  return { error: 'A plan path is required.', status: 400 };
128
150
  }
129
- const projectRoot = path.resolve(root, '..', '..');
151
+ const absRoot = path.resolve(root);
152
+ const projectRoot = path.resolve(absRoot, '..', '..');
130
153
  const resolved = path.resolve(projectRoot, clientPath);
131
- const plansDir = path.join(root, 'plans');
132
- const archiveDir = path.join(root, 'archive');
133
- const within = (dir) => resolved === dir || resolved.startsWith(dir + path.sep);
134
- if (!within(plansDir) && !within(archiveDir)) {
135
- return {
136
- error: 'Plan path must be inside the workspace plans/ or archive/ directory.',
137
- status: 400,
138
- };
154
+ const rel = path.relative(absRoot, resolved);
155
+ const first = rel.split(path.sep)[0];
156
+ const outside = {
157
+ error: 'Plan path must be inside the workspace plans/ or archive/ directory.',
158
+ status: 400,
159
+ };
160
+ if (path.isAbsolute(rel) || first === '..' || (first !== 'plans' && first !== 'archive')) {
161
+ return outside;
139
162
  }
140
- try {
141
- if (!fs.statSync(resolved).isFile()) {
142
- return { error: 'Plan path does not point to a file.', status: 404 };
163
+ const contained = (0, safe_fs_1.resolveContained)(absRoot, rel);
164
+ if ('error' in contained) {
165
+ switch (contained.error) {
166
+ case 'not-found':
167
+ return { error: 'Plan file not found.', status: 404 };
168
+ case 'not-a-file':
169
+ case 'not-a-directory':
170
+ return { error: 'Plan path does not point to a file.', status: 404 };
171
+ case 'fs-error':
172
+ return { error: 'Plan path could not be inspected.', status: 500 };
173
+ default:
174
+ // invalid-path, outside-root, symlink: the path does not denote a plain
175
+ // file inside the workspace.
176
+ return outside;
143
177
  }
144
178
  }
145
- catch {
146
- return { error: 'Plan file not found.', status: 404 };
147
- }
148
179
  return { absPath: resolved };
149
180
  };
150
181
  exports.resolveReviewPath = resolveReviewPath;
151
182
  /**
152
- * Validates `clientPath` and, if the binary is available, launches
153
- * `self-review <absolutePath>` detached. Pure of HTTP concerns: returns the
154
- * status/body the endpoint should send so it stays unit-testable.
183
+ * Validates `clientPath` and, if the binary is available and a slot is free,
184
+ * launches `self-review <absolutePath>` detached. Resolves `200` only after the
185
+ * child's `spawn` event; a launch `error` (e.g. `ENOENT`) is a fixed `500`. The
186
+ * plan's slot is taken synchronously before the spawn, so two simultaneous
187
+ * requests for one plan cannot both launch, and is released — idempotently —
188
+ * when the child exits, errors, or fails to launch. Pure of HTTP concerns:
189
+ * returns the status/body the endpoint should send so it stays unit-testable.
155
190
  */
156
- const launchSelfReview = (root, clientPath, deps = {}) => {
191
+ const launchSelfReview = async (root, clientPath, deps = {}) => {
157
192
  const available = deps.available ?? exports.isSelfReviewAvailable;
158
193
  if (!available()) {
159
194
  return {
@@ -165,15 +200,40 @@ const launchSelfReview = (root, clientPath, deps = {}) => {
165
200
  if ('error' in resolved) {
166
201
  return { status: resolved.status, body: { ok: false, error: resolved.error } };
167
202
  }
168
- try {
169
- (deps.spawnDetached ?? spawnDetached)(exports.SELF_REVIEW_BINARY, [resolved.absPath]);
203
+ const registry = deps.registry ?? defaultRegistry;
204
+ const key = resolved.absPath;
205
+ if (registry.has(key)) {
206
+ return {
207
+ status: 409,
208
+ body: { ok: false, error: 'A self-review is already running for this plan.' },
209
+ };
170
210
  }
171
- catch (err) {
211
+ if (registry.size >= exports.MAX_CONCURRENT_SELF_REVIEWS) {
172
212
  return {
173
- status: 500,
174
- body: { ok: false, error: `Failed to launch self-review: ${err.message}` },
213
+ status: 429,
214
+ body: {
215
+ ok: false,
216
+ error: `Too many self-reviews are running (limit ${exports.MAX_CONCURRENT_SELF_REVIEWS}). Try again when one finishes.`,
217
+ },
218
+ headers: { 'Retry-After': String(BUSY_RETRY_AFTER_SECONDS) },
175
219
  };
176
220
  }
221
+ registry.add(key);
222
+ const release = () => {
223
+ registry.delete(key);
224
+ };
225
+ let child;
226
+ try {
227
+ child = (deps.spawn ?? spawnDetached)(exports.SELF_REVIEW_BINARY, [key]);
228
+ await awaitSpawn(child);
229
+ }
230
+ catch {
231
+ release();
232
+ return LAUNCH_FAILED;
233
+ }
234
+ child.once('exit', release);
235
+ child.once('error', release);
236
+ child.unref();
177
237
  return { status: 200, body: { ok: true } };
178
238
  };
179
239
  exports.launchSelfReview = launchSelfReview;
@@ -1 +1 @@
1
- {"version":3,"file":"self-review.js","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"self-review.js","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"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"}