@canonical/pragma-cli 0.36.0 → 0.38.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 (312) hide show
  1. package/README.md +3 -2
  2. package/bundled-skills/adoption-a1-styles/SKILL.md +24 -0
  3. package/bundled-skills/adoption-a2-components/SKILL.md +22 -6
  4. package/bundled-skills/anatomy-author/ANATOMY_DSL_SPEC.md +1397 -327
  5. package/bundled-skills/anatomy-author/SKILL.md +840 -137
  6. package/bundled-skills/design-auditor/SKILL.md +133 -9
  7. package/bundled-skills/implement-component/SKILL.md +192 -23
  8. package/bundled-skills/specify-component/SKILL.md +124 -12
  9. package/bundled-skills/specify-pattern/SKILL.md +47 -8
  10. package/dist/package.json +23 -20
  11. package/dist/pragma.conf.js +963 -40
  12. package/dist/pragma.conf.js.map +1 -1
  13. package/dist/src/capabilities/capabilities/catalog.js +14 -5
  14. package/dist/src/capabilities/capabilities/catalog.js.map +1 -1
  15. package/dist/src/capabilities/capabilities/hints.js +33 -5
  16. package/dist/src/capabilities/capabilities/hints.js.map +1 -1
  17. package/dist/src/capabilities/config/show.render.js +30 -2
  18. package/dist/src/capabilities/config/show.render.js.map +1 -1
  19. package/dist/src/capabilities/create/create.verb.js +2 -1
  20. package/dist/src/capabilities/create/create.verb.js.map +1 -1
  21. package/dist/src/capabilities/create/createSurface.generated.js +23 -1
  22. package/dist/src/capabilities/create/createSurface.generated.js.map +1 -1
  23. package/dist/src/capabilities/doctor/checks/checkNodeVersion.js +11 -6
  24. package/dist/src/capabilities/doctor/checks/checkNodeVersion.js.map +1 -1
  25. package/dist/src/capabilities/doctor/checks/harnessInventory.js +1 -1
  26. package/dist/src/capabilities/doctor/checks/harnessInventory.js.map +1 -1
  27. package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js +38 -0
  28. package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js.map +1 -0
  29. package/dist/src/capabilities/doctor/checks/targetHealth.js +104 -14
  30. package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -1
  31. package/dist/src/capabilities/graph/connect.render.js +101 -0
  32. package/dist/src/capabilities/graph/connect.render.js.map +1 -0
  33. package/dist/src/capabilities/graph/connect.types.js +21 -0
  34. package/dist/src/capabilities/graph/connect.types.js.map +1 -0
  35. package/dist/src/capabilities/graph/connect.verb.js +147 -0
  36. package/dist/src/capabilities/graph/connect.verb.js.map +1 -0
  37. package/dist/src/capabilities/graph/index.js +5 -3
  38. package/dist/src/capabilities/graph/index.js.map +1 -1
  39. package/dist/src/capabilities/graph/queryText.js +206 -0
  40. package/dist/src/capabilities/graph/queryText.js.map +1 -0
  41. package/dist/src/capabilities/graph/relationIndex.js +302 -0
  42. package/dist/src/capabilities/graph/relationIndex.js.map +1 -0
  43. package/dist/src/capabilities/graph/runConnect.js +456 -0
  44. package/dist/src/capabilities/graph/runConnect.js.map +1 -0
  45. package/dist/src/capabilities/graph/runQuery.js +21 -4
  46. package/dist/src/capabilities/graph/runQuery.js.map +1 -1
  47. package/dist/src/capabilities/setup/buildPlan.js +6 -2
  48. package/dist/src/capabilities/setup/buildPlan.js.map +1 -1
  49. package/dist/src/capabilities/setup/operations/index.js +7 -2
  50. package/dist/src/capabilities/setup/operations/index.js.map +1 -1
  51. package/dist/src/capabilities/setup/operations/setupCompletions.js +6 -2
  52. package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -1
  53. package/dist/src/capabilities/setup/operations/setupConfig.js +4 -2
  54. package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -1
  55. package/dist/src/capabilities/setup/operations/setupGenerator.js +72 -14
  56. package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -1
  57. package/dist/src/capabilities/setup/operations/setupLsp.js +372 -62
  58. package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -1
  59. package/dist/src/capabilities/setup/operations/setupMcp.js +150 -5
  60. package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -1
  61. package/dist/src/capabilities/setup/operations/setupSkills.js +4 -2
  62. package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -1
  63. package/dist/src/capabilities/setup/operations/writability.js +114 -0
  64. package/dist/src/capabilities/setup/operations/writability.js.map +1 -0
  65. package/dist/src/capabilities/setup/plan.js.map +1 -1
  66. package/dist/src/capabilities/setup/setup.verb.js +80 -31
  67. package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
  68. package/dist/src/capabilities/setup/targets.js +124 -42
  69. package/dist/src/capabilities/setup/targets.js.map +1 -1
  70. package/dist/src/capabilities/shared/index.js +1 -1
  71. package/dist/src/capabilities/shared/index.js.map +1 -1
  72. package/dist/src/constants.js +7 -1
  73. package/dist/src/constants.js.map +1 -1
  74. package/dist/src/kernel/error/renderError.js +3 -2
  75. package/dist/src/kernel/error/renderError.js.map +1 -1
  76. package/dist/src/kernel/error/validOptions.js +41 -0
  77. package/dist/src/kernel/error/validOptions.js.map +1 -0
  78. package/dist/src/kernel/packs/compile.js +90 -6
  79. package/dist/src/kernel/packs/compile.js.map +1 -1
  80. package/dist/src/kernel/packs/cursor.js +135 -0
  81. package/dist/src/kernel/packs/cursor.js.map +1 -0
  82. package/dist/src/kernel/packs/graphql/buildLookupDocument.js +9 -2
  83. package/dist/src/kernel/packs/graphql/buildLookupDocument.js.map +1 -1
  84. package/dist/src/kernel/packs/paging.js +108 -0
  85. package/dist/src/kernel/packs/paging.js.map +1 -0
  86. package/dist/src/kernel/packs/renderPack.js +154 -5
  87. package/dist/src/kernel/packs/renderPack.js.map +1 -1
  88. package/dist/src/kernel/packs/resolveEntity.js +118 -19
  89. package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
  90. package/dist/src/kernel/packs/runBodies.js +156 -18
  91. package/dist/src/kernel/packs/runBodies.js.map +1 -1
  92. package/dist/src/kernel/packs/schema.js +160 -12
  93. package/dist/src/kernel/packs/schema.js.map +1 -1
  94. package/dist/src/kernel/packs/sparql/authorQuery.js +227 -0
  95. package/dist/src/kernel/packs/sparql/authorQuery.js.map +1 -0
  96. package/dist/src/kernel/packs/sparql/buildListQuery.js +251 -0
  97. package/dist/src/kernel/packs/sparql/buildListQuery.js.map +1 -0
  98. package/dist/src/kernel/packs/sparql/buildLookupQuery.js +125 -22
  99. package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
  100. package/dist/src/kernel/packs/sparql/filterValues.js +145 -0
  101. package/dist/src/kernel/packs/sparql/filterValues.js.map +1 -0
  102. package/dist/src/kernel/packs/sparql/index.js +24 -14
  103. package/dist/src/kernel/packs/sparql/index.js.map +1 -1
  104. package/dist/src/kernel/packs/sparql/runSelect.js +10 -4
  105. package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -1
  106. package/dist/src/kernel/packs/sparql/searchTerm.js +25 -0
  107. package/dist/src/kernel/packs/sparql/searchTerm.js.map +1 -0
  108. package/dist/src/kernel/packs/storyRules.js +151 -0
  109. package/dist/src/kernel/packs/storyRules.js.map +1 -0
  110. package/dist/src/kernel/packs/tierScope.js +310 -0
  111. package/dist/src/kernel/packs/tierScope.js.map +1 -0
  112. package/dist/src/kernel/packs/types.js +80 -0
  113. package/dist/src/kernel/packs/types.js.map +1 -1
  114. package/dist/src/kernel/project/cli/buildProgram.js +10 -1
  115. package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
  116. package/dist/src/kernel/project/cli/dispatch.js +104 -3
  117. package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
  118. package/dist/src/kernel/project/cli/rootHelp.js +8 -5
  119. package/dist/src/kernel/project/cli/rootHelp.js.map +1 -1
  120. package/dist/src/kernel/project/cli/suggestNames.js +31 -7
  121. package/dist/src/kernel/project/cli/suggestNames.js.map +1 -1
  122. package/dist/src/kernel/project/mcp/registerVerb.js +5 -1
  123. package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
  124. package/dist/src/kernel/render/renderers.js +34 -2
  125. package/dist/src/kernel/render/renderers.js.map +1 -1
  126. package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js +2 -3
  127. package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -1
  128. package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +1 -1
  129. package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -1
  130. package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js +4 -0
  131. package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js.map +1 -0
  132. package/dist/src/kernel/runtime/graphpack/embedded.js +13 -6
  133. package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -1
  134. package/dist/src/kernel/runtime/graphpack/read.js +17 -10
  135. package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
  136. package/dist/src/kernel/runtime/loadSession.js +3 -1
  137. package/dist/src/kernel/runtime/loadSession.js.map +1 -1
  138. package/dist/src/kernel/runtime/probe.js +1 -1
  139. package/dist/src/kernel/runtime/probe.js.map +1 -1
  140. package/dist/src/kernel/runtime/readEntity.js +19 -4
  141. package/dist/src/kernel/runtime/readEntity.js.map +1 -1
  142. package/dist/src/kernel/runtime/refs/parseRef.js +17 -1
  143. package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -1
  144. package/dist/src/kernel/runtime/refs/resolve.js +38 -5
  145. package/dist/src/kernel/runtime/refs/resolve.js.map +1 -1
  146. package/dist/src/kernel/spec/emitReference.js +1 -1
  147. package/dist/src/kernel/spec/emitReference.js.map +1 -1
  148. package/package.json +23 -20
  149. package/pragma.conf.ts +983 -40
  150. package/src/capabilities/block.parity.test.ts +207 -27
  151. package/src/capabilities/block.shipped.exec.test.ts +156 -14
  152. package/src/capabilities/block.tierRank.exec.test.ts +46 -9
  153. package/src/capabilities/capabilities/catalog.ts +14 -5
  154. package/src/capabilities/capabilities/hints.ts +40 -5
  155. package/src/capabilities/config/collectConfigShow.test.ts +1 -0
  156. package/src/capabilities/config/set.test.ts +24 -25
  157. package/src/capabilities/config/show.render.test.ts +9 -4
  158. package/src/capabilities/config/show.render.ts +30 -2
  159. package/src/capabilities/create/byteEquality.test.ts +28 -1
  160. package/src/capabilities/create/create.test.ts +1 -0
  161. package/src/capabilities/create/create.verb.ts +2 -1
  162. package/src/capabilities/create/createGrammar.test.ts +4 -1
  163. package/src/capabilities/create/createSurface.generated.ts +23 -1
  164. package/src/capabilities/create/crossCli.subprocess.test.ts +10 -3
  165. package/src/capabilities/distribution.parity.test.ts +12 -11
  166. package/src/capabilities/distribution.test.ts +77 -7
  167. package/src/capabilities/doctor/checks/checkNodeVersion.test.ts +49 -0
  168. package/src/capabilities/doctor/checks/checkNodeVersion.ts +11 -7
  169. package/src/capabilities/doctor/checks/harnessInventory.test.ts +13 -6
  170. package/src/capabilities/doctor/checks/harnessInventory.ts +8 -4
  171. package/src/capabilities/doctor/checks/isSupportedNodeVersion.test.ts +111 -0
  172. package/src/capabilities/doctor/checks/isSupportedNodeVersion.ts +34 -0
  173. package/src/capabilities/doctor/checks/mcpCommand.test.ts +7 -1
  174. package/src/capabilities/doctor/checks/targetHealth.ts +114 -13
  175. package/src/capabilities/doctor/doctor.test.ts +327 -36
  176. package/src/capabilities/emptyRecovery.test.ts +84 -28
  177. package/src/capabilities/graph/connect.render.ts +141 -0
  178. package/src/capabilities/graph/connect.shipped.exec.test.ts +370 -0
  179. package/src/capabilities/graph/connect.test.ts +361 -0
  180. package/src/capabilities/graph/connect.types.ts +136 -0
  181. package/src/capabilities/graph/connect.verb.ts +165 -0
  182. package/src/capabilities/graph/index.ts +5 -3
  183. package/src/capabilities/graph/query.shipped.exec.test.ts +66 -0
  184. package/src/capabilities/graph/query.test.ts +17 -0
  185. package/src/capabilities/graph/queryText.test.ts +121 -0
  186. package/src/capabilities/graph/queryText.ts +240 -0
  187. package/src/capabilities/graph/relationIndex.ts +372 -0
  188. package/src/capabilities/graph/runConnect.ts +577 -0
  189. package/src/capabilities/graph/runQuery.ts +21 -6
  190. package/src/capabilities/lazy.test.ts +32 -2
  191. package/src/capabilities/listBudget.shipped.exec.test.ts +239 -0
  192. package/src/capabilities/listLookup.shipped.exec.test.ts +387 -0
  193. package/src/capabilities/listQuery.shipped.exec.test.ts +400 -0
  194. package/src/capabilities/resources/resources.test.ts +38 -2
  195. package/src/capabilities/setup/buildPlan.ts +7 -1
  196. package/src/capabilities/setup/operations/index.ts +14 -0
  197. package/src/capabilities/setup/operations/setupCompletions.ts +9 -2
  198. package/src/capabilities/setup/operations/setupConfig.ts +7 -2
  199. package/src/capabilities/setup/operations/setupGenerator.ts +93 -15
  200. package/src/capabilities/setup/operations/setupLsp.ts +544 -85
  201. package/src/capabilities/setup/operations/setupMcp.ts +212 -4
  202. package/src/capabilities/setup/operations/setupSkills.ts +7 -2
  203. package/src/capabilities/setup/operations/writability.test.ts +151 -0
  204. package/src/capabilities/setup/operations/writability.ts +135 -0
  205. package/src/capabilities/setup/plan.ts +11 -0
  206. package/src/capabilities/setup/setup.test.ts +992 -16
  207. package/src/capabilities/setup/setup.verb.ts +84 -36
  208. package/src/capabilities/setup/targets.ts +152 -48
  209. package/src/capabilities/setup/types.ts +41 -5
  210. package/src/capabilities/shared/index.ts +1 -0
  211. package/src/capabilities/sources/sources.test.ts +55 -0
  212. package/src/capabilities/surface.test.ts +59 -11
  213. package/src/capabilities/tier.parity.test.ts +2 -2
  214. package/src/capabilities/token.parity.test.ts +784 -0
  215. package/src/capabilities/tokenGraph.cli.test.ts +279 -0
  216. package/src/capabilities/tokenGraph.shipped.exec.test.ts +653 -0
  217. package/src/capabilities/variable.parity.test.ts +448 -0
  218. package/src/constants.ts +8 -0
  219. package/src/kernel/completion/shellDrive.test.ts +32 -30
  220. package/src/kernel/config/defaults.test.ts +21 -2
  221. package/src/kernel/config/readConfig.test.ts +1 -1
  222. package/src/kernel/error/renderError.ts +3 -2
  223. package/src/kernel/error/validOptions.test.ts +57 -0
  224. package/src/kernel/error/validOptions.ts +45 -0
  225. package/src/kernel/packs/collect.test.ts +2 -0
  226. package/src/kernel/packs/compile.test.ts +188 -15
  227. package/src/kernel/packs/compile.ts +109 -14
  228. package/src/kernel/packs/cursor.ts +135 -0
  229. package/src/kernel/packs/filteredEmpty.test.ts +213 -0
  230. package/src/kernel/packs/graphql/buildLookupDocument.ts +16 -9
  231. package/src/kernel/packs/graphqlSource.test.ts +152 -0
  232. package/src/kernel/packs/listNotice.test.ts +156 -0
  233. package/src/kernel/packs/paging.ts +110 -0
  234. package/src/kernel/packs/renderPack.ts +186 -13
  235. package/src/kernel/packs/resolveEntity.test.ts +62 -3
  236. package/src/kernel/packs/resolveEntity.ts +186 -26
  237. package/src/kernel/packs/runBodies.ts +196 -26
  238. package/src/kernel/packs/schema.ts +180 -13
  239. package/src/kernel/packs/sparql/authorQuery.test.ts +179 -0
  240. package/src/kernel/packs/sparql/authorQuery.ts +257 -0
  241. package/src/kernel/packs/sparql/buildListQuery.test.ts +344 -0
  242. package/src/kernel/packs/sparql/buildListQuery.ts +344 -0
  243. package/src/kernel/packs/sparql/buildLookupQuery.test.ts +138 -0
  244. package/src/kernel/packs/sparql/buildLookupQuery.ts +140 -20
  245. package/src/kernel/packs/sparql/filterValues.test.ts +86 -0
  246. package/src/kernel/packs/sparql/filterValues.ts +182 -0
  247. package/src/kernel/packs/sparql/index.ts +30 -14
  248. package/src/kernel/packs/sparql/runSelect.test.ts +63 -0
  249. package/src/kernel/packs/sparql/runSelect.ts +42 -2
  250. package/src/kernel/packs/sparql/searchTerm.ts +29 -0
  251. package/src/kernel/packs/storyRules.ts +180 -0
  252. package/src/kernel/packs/tierScope.test.ts +487 -0
  253. package/src/kernel/packs/tierScope.ts +409 -0
  254. package/src/kernel/packs/toolDescription.test.ts +13 -10
  255. package/src/kernel/packs/types.ts +311 -9
  256. package/src/kernel/project/cli/buildProgram.ts +17 -1
  257. package/src/kernel/project/cli/dispatch.test.ts +87 -0
  258. package/src/kernel/project/cli/dispatch.ts +114 -4
  259. package/src/kernel/project/cli/rootHelp.ts +8 -5
  260. package/src/kernel/project/cli/suggest.test.ts +35 -0
  261. package/src/kernel/project/cli/suggestNames.ts +34 -7
  262. package/src/kernel/project/mcp/registerVerb.ts +5 -1
  263. package/src/kernel/render/contracts.ts +2 -0
  264. package/src/kernel/render/prefixes.test.ts +2 -0
  265. package/src/kernel/render/renderers.test.ts +43 -0
  266. package/src/kernel/render/renderers.ts +34 -1
  267. package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +2 -3
  268. package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +1 -1
  269. package/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.ts +3 -0
  270. package/src/kernel/runtime/graphpack/embedded.ts +14 -6
  271. package/src/kernel/runtime/graphpack/graphpack.test.ts +31 -5
  272. package/src/kernel/runtime/graphpack/read.ts +17 -13
  273. package/src/kernel/runtime/loadSession.ts +3 -1
  274. package/src/kernel/runtime/probe.ts +1 -1
  275. package/src/kernel/runtime/readEntity.ts +19 -4
  276. package/src/kernel/runtime/refs/parseRef.test.ts +49 -1
  277. package/src/kernel/runtime/refs/parseRef.ts +25 -1
  278. package/src/kernel/runtime/refs/resolve.ts +39 -5
  279. package/src/kernel/runtime/types.ts +30 -0
  280. package/src/kernel/spec/emitReference.ts +1 -1
  281. package/src/kernel/spec/surfaceConformance.test.ts +2 -2
  282. package/src/kernel/spec/types.ts +17 -0
  283. package/src/testing/PARITY_GAPS.ts +4 -4
  284. package/src/testing/behavioral/agentSession.mcp.test.ts +43 -39
  285. package/src/testing/behavioral/completion.test.ts +7 -6
  286. package/src/testing/behavioral/disclosure.test.ts +39 -37
  287. package/src/testing/behavioral/errorMatrix.mcp.test.ts +82 -64
  288. package/src/testing/behavioral/errorMatrix.storeless.test.ts +11 -10
  289. package/src/testing/behavioral/journeys.cli.test.ts +71 -32
  290. package/src/testing/behavioral/journeys.defaultPack.test.ts +6 -4
  291. package/src/testing/behavioral/journeys.firstInstall.test.ts +70 -5
  292. package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +4 -3
  293. package/src/testing/behavioral/journeys.packageStories.test.ts +2 -1
  294. package/src/testing/behavioral/mcpSurface.test.ts +28 -25
  295. package/src/testing/behavioral/parity.test.ts +25 -23
  296. package/src/testing/eval/__snapshots__/eval.test.ts.snap +20 -0
  297. package/src/testing/eval/cases/effectful.ts +7 -1
  298. package/src/testing/eval/cases/readNouns.ts +100 -11
  299. package/src/testing/fixtures/blockGraph.ts +89 -5
  300. package/src/testing/fixtures/connectGraph.ts +159 -0
  301. package/src/testing/fixtures/graph/canonical.ts +128 -32
  302. package/src/testing/helpers/fsProbe.ts +88 -0
  303. package/src/testing/helpers/runCli.test.ts +44 -0
  304. package/src/testing/helpers/runCli.ts +27 -3
  305. package/src/testing/perf/budgets.test.ts +3 -1
  306. package/src/testing/perf/budgets.ts +138 -54
  307. package/dist/src/kernel/packs/sparql/applyFilters.js +0 -167
  308. package/dist/src/kernel/packs/sparql/applyFilters.js.map +0 -1
  309. package/dist/src/kernel/packs/sparql/applySearch.js +0 -25
  310. package/dist/src/kernel/packs/sparql/applySearch.js.map +0 -1
  311. package/src/kernel/packs/sparql/applyFilters.ts +0 -203
  312. package/src/kernel/packs/sparql/applySearch.ts +0 -33
@@ -11,18 +11,39 @@
11
11
  * NOT used: it hardcodes the `code` CLI, which is precisely what left
12
12
  * VSCodium/Cursor/Windsurf/Antigravity machines unable to install at all.
13
13
  *
14
- * `detectLsp` probes FOR REAL up front, and spawns NOTHING: an editor is
15
- * detected when its CLI resolves on PATH (the `editorClis` registry names
16
- * them), carries the extension when its extensions dir holds a
14
+ * `detectLsp` probes FOR REAL up front, and spawns NOTHING. An editor is
15
+ * detected THREE ways, and each row records which one found it, because "no
16
+ * editor found" and "found but nothing can be installed into it" are different
17
+ * answers and only one of them is about this machine lacking the editor:
18
+ *
19
+ * 1. its CLI on PATH (the `editorClis` registry names them);
20
+ * 2. its CLI inside its macOS APP BUNDLE — a stock macOS install puts nothing
21
+ * on PATH until the user runs the palette's "Shell Command: Install
22
+ * '<cli>' command in PATH", which is opt-in and usually never taken, so a
23
+ * PATH-only probe reported a machine that HAS VS Code as having none;
24
+ * 3. its per-user configuration DIRECTORY, which is the last trace a fresh
25
+ * install leaves. Nothing can be installed through a directory, so such an
26
+ * editor carries no CLI path at all and its remedy is the palette command
27
+ * that settles it.
28
+ *
29
+ * It carries the extension when its extensions dir holds a
17
30
  * `canonical.terrazzo-lsp-extension-<version>/` entry, and is "installed" when
18
- * that entry is also new enough to work. Running
19
- * `--list-extensions` instead would be the natural probe, but Cursor's Linux
20
- * launcher OPENS THE EDITOR on that flag — a detection step must never launch
21
- * an app, so the fs is the source of truth. The full extension id is matched
22
- * (not the old `terrazzo` substring, which any other terrazzo-named extension
23
- * could false-positive).
24
- *
25
- * No editor CLI found is a NAMED SKIP, not an error: the message says what was
31
+ * that entry is also new enough to work. Running `--list-extensions` instead
32
+ * would be the natural probe, but Cursor's Linux launcher OPENS THE EDITOR on
33
+ * that flag — a detection step must never launch an app, so the fs is the
34
+ * source of truth. The full extension id is matched (not the old `terrazzo`
35
+ * substring, which any other terrazzo-named extension could false-positive).
36
+ *
37
+ * Detection also asks whether the extensions directory could be WRITTEN, via
38
+ * `probeWritable`, BEFORE any install is composed. A home-manager-managed
39
+ * `~/.vscode/extensions` is a symlink into `/nix/store`, so
40
+ * `--install-extension` there failed with a raw fs error or silently changed
41
+ * nothing; that is now a named skip carrying the declaration that does work.
42
+ * Per the owner, 2026-09-16, the decision is made by the DIRECTORY, never by
43
+ * the OS: a Nix user's home is ordinary, and a non-Nix user can have a
44
+ * read-only mount.
45
+ *
46
+ * Every one of those is a NAMED SKIP, not an error: the message says what was
26
47
  * looked for and what to do, and the run exits 0 — there is nothing on this
27
48
  * machine the step could honestly fail at. Real failures (fetch, sideload)
28
49
  * travel the task failure channel (`checkExecOk`) with a recovery that names a
@@ -31,16 +52,44 @@
31
52
  */
32
53
  import { existsSync, readdirSync } from "node:fs";
33
54
  import { join } from "node:path";
34
- import { exec, flatMap, mkdir, sequence_, } from "@canonical/task";
55
+ import { exec, exists, flatMap, mkdir, pure, sequence, sequence_, } from "@canonical/task";
35
56
  import { BIN_NAME } from "../../../constants.js";
36
- import { checkExecOk, guardMissingBinary } from "../../shared/index.js";
57
+ import { PragmaError } from "../../../kernel/error/index.js";
58
+ import { checkExecOk, failPragma, guardMissingBinary, } from "../../shared/index.js";
59
+ import { shortenPath } from "../plan.js";
60
+ import { probeWritable } from "./writability.js";
61
+ /**
62
+ * The extension's publisher and name. Separate constants because the Nix
63
+ * declaration names all three parts (`vscodeExtPublisher`, `vscodeExtName`,
64
+ * `vscodeExtUniqueId`), and composing the id from them is what keeps the three
65
+ * from drifting apart in one string.
66
+ */
67
+ const EXTENSION_PUBLISHER = "canonical";
68
+ const EXTENSION_NAME = "terrazzo-lsp-extension";
37
69
  /** The full extension id, as the editor's extensions dir spells it. */
38
- const EXTENSION_ID = "canonical.terrazzo-lsp-extension";
70
+ const EXTENSION_ID = `${EXTENSION_PUBLISHER}.${EXTENSION_NAME}`;
39
71
  /** The npm package whose tarball bundles the VSIX. */
40
72
  const LSP_PACKAGE = "@canonical/terrazzo-lsp-extension";
41
73
  /**
42
- * Whether an editor CLI resolves on PATH, given the candidate paths the host
43
- * would consider for it.
74
+ * Whether an install can act on an editor at all: there is a CLI to RUN, and
75
+ * its extensions folder can be WRITTEN.
76
+ *
77
+ * One predicate, because the answer is one question. Five call sites used to
78
+ * spell their own half of it (`!e.installed && e.block === undefined`,
79
+ * `e.present && e.block === undefined`, …), so adding a third way to be
80
+ * unreachable would have meant finding all five.
81
+ *
82
+ * @param e - One detected editor.
83
+ * @returns Whether the sideload can run for it.
84
+ * @note Pure — reads the detection record.
85
+ */
86
+ const installable = (e) => e.foundBy !== "user-dir" && e.block === undefined;
87
+ /** The editors nothing can be installed into, in registry order. */
88
+ const blockedEditors = (d) => d.editors.filter((e) => !installable(e));
89
+ /**
90
+ * The FIRST candidate path that exists, or `undefined` when none does — used
91
+ * for both candidate lists (PATH, then the macOS app bundle), so a caller
92
+ * learns not only whether the CLI is there but which file it is.
44
93
  *
45
94
  * The candidates come from `@canonical/harnesses`' `executableCandidates` —
46
95
  * the same helper harness detection resolves `process` signals with — rather
@@ -52,8 +101,12 @@ const LSP_PACKAGE = "@canonical/terrazzo-lsp-extension";
52
101
  * the editor — a wrong skip reads as correct, which is worse than a wrong
53
102
  * failure. One implementation of the platform rules means the probe cannot
54
103
  * drift away from detection's.
104
+ *
105
+ * @param candidates - The candidate paths, strongest first.
106
+ * @returns The first candidate that exists, or `undefined` when none does.
107
+ * @note Impure — stats each candidate until one exists.
55
108
  */
56
- const cliOnPath = (candidates) => candidates.some((candidate) => existsSync(candidate));
109
+ const resolveCli = (candidates) => candidates.find((candidate) => existsSync(candidate));
57
110
  /**
58
111
  * The oldest extension release whose bundled language server actually starts.
59
112
  *
@@ -124,7 +177,8 @@ const extensionState = (editor, platform) => {
124
177
  entries = readdirSync(editor.extensionsDir(platform));
125
178
  }
126
179
  catch {
127
- return { present: false, current: false }; // No dir — nothing installed.
180
+ // No dir — nothing installed.
181
+ return { present: false, current: false, entries: [] };
128
182
  }
129
183
  const prefix = `${EXTENSION_ID}-`;
130
184
  const matching = entries.filter((entry) => entry.toLowerCase().startsWith(prefix));
@@ -134,29 +188,103 @@ const extensionState = (editor, platform) => {
134
188
  return false; // Unreadable: cannot vouch for it.
135
189
  return compareVersions(version, MINIMUM) >= 0;
136
190
  });
137
- return { present: matching.length > 0, current };
191
+ return { present: matching.length > 0, current, entries: matching };
138
192
  };
139
193
  /**
140
- * Probe every registry editor: CLI presence via PATH lookup, installed-state
141
- * via the extensions dir — no spawns (see the module docblock for why).
194
+ * WHICH of the three probes finds this editor, strongest first — or
195
+ * `undefined` when none does.
196
+ *
197
+ * A resolved CLI always wins, because a CLI is what an install RUNS. The
198
+ * per-user directory is last and yields no path: it proves the editor is on
199
+ * this machine and nothing more.
200
+ *
201
+ * @param editor - One registry row.
202
+ * @param host - The captured platform.
203
+ * @param paths - The harness path helpers.
204
+ * @returns The provenance and its evidence, or `undefined`.
205
+ * @note Impure — stats PATH entries, app bundles and the user directory.
206
+ */
207
+ const findEditorSource = (editor, host, paths) => {
208
+ const onPath = resolveCli(paths.executableCandidates(editor.cli, host));
209
+ if (onPath !== undefined)
210
+ return { foundBy: "path", cliPath: onPath };
211
+ const inBundle = resolveCli(paths.appBundleCandidates(editor.cli, host, editor.darwinBundles));
212
+ if (inBundle !== undefined)
213
+ return { foundBy: "bundle", cliPath: inBundle };
214
+ // The registry names the PRODUCT; `vscodeUserDir` owns the platform switch,
215
+ // so this probe, the harness rows' `homeConfigPath` and their detection
216
+ // signals cannot name different directories.
217
+ const userDir = editor.product === undefined
218
+ ? undefined
219
+ : paths.vscodeUserDir(editor.product, host);
220
+ if (userDir !== undefined && existsSync(userDir)) {
221
+ return { foundBy: "user-dir" };
222
+ }
223
+ return undefined;
224
+ };
225
+ /**
226
+ * One registry row as a {@link DetectedEditor} — or `undefined` when this
227
+ * machine has no trace of the editor at all.
228
+ *
229
+ * @param editor - One registry row.
230
+ * @param host - The captured platform.
231
+ * @param paths - The harness path helpers.
232
+ * @param probe - The writability filesystem seam; defaults to the real one.
233
+ * @returns The detection record, or `undefined`.
234
+ * @note Impure — reads PATH dirs, app bundles, the user directory and the
235
+ * extensions directory off the real fs.
236
+ */
237
+ const findEditor = (editor, host, paths, probe) => {
238
+ const source = findEditorSource(editor, host, paths);
239
+ if (source === undefined)
240
+ return undefined;
241
+ const { present, current, entries } = extensionState(editor, host);
242
+ const extensionsDir = editor.extensionsDir(host);
243
+ // Writability is asked only where there is a CLI to run. An editor found
244
+ // only by its user directory cannot be installed into whatever its folder
245
+ // permits, and the palette command is its remedy either way — so the probe
246
+ // would cost a stat to answer a question nothing reads.
247
+ const block = source.foundBy === "user-dir"
248
+ ? undefined
249
+ : probeWritable(extensionsDir, probe);
250
+ return {
251
+ editor,
252
+ ...source,
253
+ present,
254
+ installed: current,
255
+ extensionsDir,
256
+ presentEntries: entries,
257
+ ...(block === undefined ? {} : { block }),
258
+ };
259
+ };
260
+ /**
261
+ * Probe every registry editor: its CLI on PATH, then inside its macOS app
262
+ * bundle, then its per-user directory; its installed-state via the extensions
263
+ * dir; and whether that dir could be written. No spawns (see the module
264
+ * docblock for why).
142
265
  *
143
266
  * @param _cwd - Unused; kept so every `detectX` shares the (cwd) shape.
267
+ * @param platform - The captured host; defaults to the live one. Injected so a
268
+ * test can drive the darwin arm — the one this repo's CI host cannot run.
269
+ * @param probe - The writability filesystem seam; defaults to the real one.
144
270
  * @returns The detected {@link LspDetection}.
145
- * @note Impure — reads PATH dirs and editor extension dirs off the real fs.
271
+ * @note Impure — reads PATH dirs, app bundles and editor extension dirs off
272
+ * the real fs.
146
273
  */
147
- export async function detectLsp(_cwd) {
148
- const { editorClis, executableCandidates, readPlatformEnv, userDataBase } = await import("@canonical/harnesses");
149
- const platform = readPlatformEnv();
150
- const editors = editorClis
151
- .filter((editor) => cliOnPath(executableCandidates(editor.cli, platform)))
152
- .map((editor) => {
153
- const { present, current } = extensionState(editor, platform);
154
- return {
155
- editor,
156
- present,
157
- installed: current,
158
- extensionsDir: editor.extensionsDir(platform),
159
- };
274
+ export async function detectLsp(_cwd, platform, probe) {
275
+ const { appBundleCandidates, editorClis, executableCandidates, readPlatformEnv, userDataBase, vscodeUserDir, } = await import("@canonical/harnesses");
276
+ // Not a default parameter value: `readPlatformEnv` arrives through the
277
+ // dynamic import that keeps `@canonical/harnesses` off the fast path, so it
278
+ // cannot be named in the signature.
279
+ const host = platform ?? readPlatformEnv();
280
+ const paths = {
281
+ appBundleCandidates,
282
+ executableCandidates,
283
+ vscodeUserDir,
284
+ };
285
+ const editors = editorClis.flatMap((editor) => {
286
+ const found = findEditor(editor, host, paths, probe);
287
+ return found === undefined ? [] : [found];
160
288
  });
161
289
  const state = editors.length === 0
162
290
  ? "unknown"
@@ -168,7 +296,7 @@ export async function detectLsp(_cwd) {
168
296
  state,
169
297
  editors,
170
298
  probed: editorClis.map((editor) => editor.cli),
171
- stagingDir: join(userDataBase(platform), BIN_NAME, "lsp"),
299
+ stagingDir: join(userDataBase(host), BIN_NAME, "lsp"),
172
300
  };
173
301
  }
174
302
  /**
@@ -184,22 +312,149 @@ export async function detectLsp(_cwd) {
184
312
  * @returns The editors to install into.
185
313
  */
186
314
  export const selectedEditors = (d, chosen) => {
187
- const pending = d.editors.filter((e) => !e.installed);
315
+ // A BLOCKED editor is never pending. It is not a candidate the user declined
316
+ // — it is one this command cannot act on, and composing its sideload anyway
317
+ // is what produced the raw fs failure the block exists to replace.
318
+ const pending = d.editors.filter((e) => !e.installed && installable(e));
188
319
  return chosen === undefined
189
320
  ? pending
190
321
  : pending.filter((e) => chosen.includes(e.editor.cli));
191
322
  };
323
+ /**
324
+ * The editors an install could act on, ignoring the wizard's selection — the
325
+ * question both plan rows and doctor's row ask to decide whether there is any
326
+ * work here at all.
327
+ *
328
+ * @param d - The detection gathered up front.
329
+ * @returns The editors missing the extension that can be written to.
330
+ */
331
+ export const installableEditors = (d) => d.editors.filter((e) => !e.installed && installable(e));
192
332
  /** The editor names in a detection (for messages/results). */
193
333
  export const lspEditorNames = (d) => d.editors.map((e) => e.editor.name);
194
334
  /**
195
- * The named-skip reason for a machine with no VS Code-family CLI on PATH. It
196
- * names every CLI that was probed, because a skip the user cannot act on is
197
- * only honest if it says what would have counted.
335
+ * The named-skip reason for a machine with no VS Code-family editor at all. It
336
+ * names every CLI that was probed AND every place it was looked for, because a
337
+ * skip the user cannot act on is only honest if it says what would have
338
+ * counted — and "not on PATH" was a misleading half of the answer once the
339
+ * bundle and user-directory probes existed.
198
340
  *
199
341
  * @param d - The detection gathered up front.
200
342
  * @returns The reason line.
201
343
  */
202
- export const lspSkipReason = (d) => `no VS Code-family editor CLI on PATH (${d.probed.join(", ")})`;
344
+ export const lspSkipReason = (d) => `no VS Code-family editor found — looked for ${d.probed.join(", ")} on PATH, under /Applications or ~/Applications, or by its user directory`;
345
+ /**
346
+ * How one editor was found, as a phrase both surfaces print — the provenance a
347
+ * user needs to tell "pragma missed my editor" from "pragma found it and could
348
+ * not act". Authored once, because `setup`'s child row and `doctor`'s item are
349
+ * the same finding.
350
+ *
351
+ * The evidence path travels with it wherever there is one: the CLI file the
352
+ * probe resolved. An editor found only by its user directory has no CLI, and
353
+ * the phrase alone is the whole finding there.
354
+ *
355
+ * @param e - One detected editor.
356
+ * @param roots - The two roots every path renders relative to.
357
+ * @returns The phrase, e.g. `via PATH (/usr/bin/codium)`.
358
+ */
359
+ export const describeEditorSource = (e, roots) => {
360
+ if (e.foundBy === "user-dir")
361
+ return "via user directory";
362
+ const where = e.foundBy === "path" ? "PATH" : "app bundle";
363
+ return `via ${where} (${shortenPath(e.cliPath, roots)})`;
364
+ };
365
+ /**
366
+ * The home-manager declaration for a Nix-managed extensions folder.
367
+ *
368
+ * It does NOT name a marketplace id, because there is no listing — the module
369
+ * docblock above says so, and sideloading the bundled VSIX is the only install
370
+ * path that exists. So the line gives both halves a home-manager user needs:
371
+ * where to get the file, and the attribute that installs it.
372
+ *
373
+ * The expression is VALID NIX, which the shorter `{ src = <path>; }` sketch it
374
+ * replaces was not twice over: `buildVscodeExtension` has no defaults for
375
+ * `name`, `vscodeExtPublisher`, `vscodeExtName` or `vscodeExtUniqueId`
376
+ * (nixpkgs `pkgs/build-support/vscode/extensions`), and an unquoted Nix path
377
+ * literal cannot carry the `@` in `@canonical/…` — it is `builtins.path`
378
+ * around a quoted string here for that reason. `version` is the ONE attribute
379
+ * a user must fill in, so the line says so rather than guessing a number that
380
+ * would be wrong the next release.
381
+ */
382
+ const nixDeclarationRemedy = (d) => `fetch the VSIX with \`bun add ${LSP_PACKAGE}@latest\` in ${d.stagingDir}, then declare it yourself, filling in the version from the fetched package.json: programs.vscode.profiles.default.extensions = [ (pkgs.vscode-utils.buildVscodeExtension { name = "${EXTENSION_NAME}"; version = "<version>"; vscodeExtPublisher = "${EXTENSION_PUBLISHER}"; vscodeExtName = "${EXTENSION_NAME}"; vscodeExtUniqueId = "${EXTENSION_ID}"; src = builtins.path { path = "${lspVsixPath(d)}"; }; }) ];`;
383
+ /**
384
+ * Why nothing can be installed into a blocked editor, and the ONE action that
385
+ * settles it — both answers from one dispatch.
386
+ *
387
+ * Two `switch`es over the same three causes (one for the reason, one for the
388
+ * remedy) is how a fourth cause gets a reason and no remedy; a table whose row
389
+ * is a `{reason, remedy}` pair cannot drift that way. The remedy is a thunk
390
+ * because only it needs the detection (for the staging dir and the VSIX path),
391
+ * and the reason is read per child row where no detection is in hand.
392
+ *
393
+ * The reason does NOT name the editor. Every place it lands already does: the
394
+ * setup child row is labelled `<cli> — <name> · <found via>`, doctor's item is
395
+ * labelled with the name, and the row headline prefixes it
396
+ * ({@link firstLspBlock}). Including it here made doctor print "VS Code: via
397
+ * user directory · VS Code is installed but has no …" — the name twice in one
398
+ * line and three times in two.
399
+ *
400
+ * @param e - An editor nothing can be installed into.
401
+ * @returns Its reason, and a remedy awaiting the detection.
402
+ * @note Pure — composes strings from the detection record.
403
+ */
404
+ const describeBlock = (e) => {
405
+ // Keyed by PROVENANCE, not by a block: an editor found only by its user
406
+ // directory has no CLI whatever its folder permits, so "no launcher" is a
407
+ // fact about how it was found. Its folder is never probed (see `findEditor`).
408
+ if (e.foundBy === "user-dir") {
409
+ return {
410
+ reason: "no command-line launcher — found only its user directory",
411
+ remedy: () => `run "Shell Command: Install '${e.editor.cli}' command in PATH" from ${e.editor.name}'s command palette, then run \`${BIN_NAME} setup lsp\` again`,
412
+ };
413
+ }
414
+ switch (e.block.kind) {
415
+ case "nix-store":
416
+ return {
417
+ reason: `extensions folder managed by Nix (it resolves to ${e.block.resolved})`,
418
+ remedy: nixDeclarationRemedy,
419
+ };
420
+ case "read-only":
421
+ return {
422
+ // The folder the row names is the one a `chmod` has to reach, so the
423
+ // remedy can say "the extensions folder" instead of repeating it.
424
+ reason: `extensions folder is not writable (${e.block.path})`,
425
+ remedy: () => `make the extensions folder writable, then run \`${BIN_NAME} setup lsp\` again`,
426
+ };
427
+ }
428
+ };
429
+ /**
430
+ * Why nothing can be installed into one editor — one line, as the renderer
431
+ * prints one — or `undefined` when the install can act on it.
432
+ *
433
+ * @param e - One detected editor.
434
+ * @returns The reason, or `undefined` when the editor is actionable.
435
+ */
436
+ export const lspBlockReason = (e) => installable(e) ? undefined : describeBlock(e).reason;
437
+ /**
438
+ * The FIRST editor nothing can be installed into, with its row headline and
439
+ * its remedy already derived — or `undefined` when every detected editor is
440
+ * actionable.
441
+ *
442
+ * It hands back the derived strings rather than the editor, because the
443
+ * blockedness is what makes the reason and the remedy exist: a caller that
444
+ * took the editor and asked for them separately had to assert that both were
445
+ * there, twice, on both surfaces. The headline names the editor, since nothing
446
+ * else on a ROW has.
447
+ *
448
+ * @param d - The detection gathered up front.
449
+ * @returns The first block's headline and remedy, or `undefined`.
450
+ */
451
+ export const firstLspBlock = (d) => {
452
+ const first = blockedEditors(d).at(0);
453
+ if (first === undefined)
454
+ return undefined;
455
+ const { reason, remedy } = describeBlock(first);
456
+ return { headline: `${first.editor.name}: ${reason}`, remedy: remedy(d) };
457
+ };
203
458
  /**
204
459
  * The remedy beneath that skip. It states plainly that nothing is possible here
205
460
  * yet rather than offering a command for a binary this machine lacks — the rule
@@ -219,7 +474,7 @@ export const LSP_SKIP_REMEDY = "no action is possible on this machine yet — in
219
474
  * @returns A Task installing the extension into each editor missing it.
220
475
  */
221
476
  export function composeLsp(d, chosen) {
222
- // Nothing to install: no editor CLI on PATH (a named skip the plan row
477
+ // Nothing to install: no editor found at all (a named skip the plan row
223
478
  // carries) or every detected editor already has it. Both compose NOTHING —
224
479
  // what the run SAYS about this target is the plan row's business.
225
480
  if (d.state !== "absent")
@@ -242,11 +497,16 @@ export function composeLsp(d, chosen) {
242
497
  `\`${BIN_NAME} setup lsp\` again.`,
243
498
  })),
244
499
  ]));
245
- const sideloads = pending.map(({ editor }) => {
246
- const command = `${editor.cli} --install-extension ${vsixPath}`;
247
- return guardMissingBinary(editor.cli, {
248
- message: `The \`${editor.cli}\` CLI disappeared from PATH mid-run — restore it, then run \`${BIN_NAME} setup lsp\` again.`,
249
- }, flatMap(exec(editor.cli, ["--install-extension", vsixPath], d.stagingDir), (result) => checkExecOk(command, result, {
500
+ const sideloads = pending.map(({ editor, cliPath }) => {
501
+ // The CLI FILE detection resolved, which is the only thing a pending
502
+ // editor HAS: an editor found in its macOS app bundle has nothing on PATH
503
+ // to spawn, and even a PATH hit is better spawned as the file this run
504
+ // verified.
505
+ const bin = cliPath;
506
+ const command = `${bin} --install-extension ${vsixPath}`;
507
+ return guardMissingBinary(bin, {
508
+ message: `${editor.name}'s CLI disappeared mid-run — restore it, then run \`${BIN_NAME} setup lsp\` again.`,
509
+ }, flatMap(exec(bin, ["--install-extension", vsixPath], d.stagingDir), (result) => checkExecOk(command, result, {
250
510
  message: `${editor.name} refused the VSIX (its output is above). The file is kept at ${vsixPath} — retry by hand with ` +
251
511
  `\`${command}\`, or update ${editor.name} first.`,
252
512
  })));
@@ -265,10 +525,16 @@ export function composeLsp(d, chosen) {
265
525
  * @param d - The detection gathered up front.
266
526
  * @returns The editors carrying a copy.
267
527
  */
268
- export const ownedLspEditors = (d) => d.editors.filter((e) => e.present);
528
+ export const ownedLspEditors = (d) =>
529
+ // A blocked editor is excluded even when it carries a copy: the uninstall
530
+ // would need a CLI this machine has not got, or a write into a directory
531
+ // pragma must not touch. The row says so rather than composing a reversal
532
+ // that cannot run.
533
+ d.editors.filter((e) => e.present && installable(e));
269
534
  /**
270
535
  * Compose the removal: one `<editor cli> --uninstall-extension <id>` per owned
271
- * editor, carried as the `undo` of a forward no-op.
536
+ * editor, carried as the `undo` of a forward no-op — and each uninstall
537
+ * asserts its own GOAL, not just its exit code.
272
538
  *
273
539
  * The docblock this replaces claimed "an `exec` carries no reversal". That was
274
540
  * factually wrong about the effect model — `Exec` has an `undo` slot and `exec`
@@ -282,24 +548,68 @@ export const ownedLspEditors = (d) => d.editors.filter((e) => e.present);
282
548
  * `present` proves already exists — reads nothing and is a genuine no-op. Phase
283
549
  * two then runs the uninstall against the real editor.
284
550
  *
551
+ * THE POSTCONDITION is the removal's real success criterion. The exec's exit
552
+ * code and the extensions DIRECTORY are two different judges — detection
553
+ * deliberately reads the directory (probing via the CLI can launch an
554
+ * editor), and VS Code-family CLIs are known to exit 0 while deferring or
555
+ * skipping the deletion — so after `checkExecOk` the undo probes the exact
556
+ * entries detection said this command owns, and FAILS (with the manual
557
+ * deletion as the remedy — never the command that just claimed success) when
558
+ * any survived. An in-task failure here is safe precisely because
559
+ * `runCollectedUndos` executes each undo isolated: it used to abort every
560
+ * reversal still pending, which is why no removal could afford to assert its
561
+ * own goal.
562
+ *
285
563
  * @param d - The detection gathered up front.
286
- * @returns A Task whose undo uninstalls the extension from each owned editor.
564
+ * @param undoKey - Correlation key stamped on each reversal, echoed on its
565
+ * `UndoOutcome` so the caller can read the outcomes back per row.
566
+ * @returns A Task whose undo uninstalls the extension from each owned editor
567
+ * and verifies the copy is gone.
287
568
  */
288
- export function composeLspRemoval(d) {
569
+ export function composeLspRemoval(d, undoKey) {
289
570
  const owned = ownedLspEditors(d);
290
571
  // Nothing on this machine carries a copy — there is no honest work to model,
291
572
  // and the plan row says so. Same shape as the other rows' empty removals.
292
573
  if (owned.length === 0)
293
574
  return sequence_([]);
294
- return sequence_(owned.map(({ editor, extensionsDir }) => {
295
- const command = `${editor.cli} --uninstall-extension ${EXTENSION_ID}`;
575
+ return sequence_(owned.map(({ editor, cliPath, extensionsDir, presentEntries }) => {
576
+ // The resolved CLI file, for the reason `composeLsp` spells out.
577
+ const bin = cliPath;
578
+ const command = `${bin} --uninstall-extension ${EXTENSION_ID}`;
579
+ const ownedPaths = presentEntries.map((entry) => join(extensionsDir, entry));
580
+ const uninstall = flatMap(exec(bin, ["--uninstall-extension", EXTENSION_ID], extensionsDir), (result) => checkExecOk(command, result, {
581
+ message: `${editor.name} refused the uninstall (its output is above). ` +
582
+ `Remove it by hand with \`${command}\`.`,
583
+ }));
584
+ // The probe must apply DETECTION'S presence criterion, or the check can
585
+ // quietly stop checking: `extensionState` calls an entry present when
586
+ // `readdirSync` lists it, and a default `exists` (`fs.access`) follows
587
+ // symlinks — so a dangling matching symlink would be "installed" to
588
+ // detection and "absent" here, and an editor that exits 0 without
589
+ // removing it would report `undone` while the next detection finds it
590
+ // again. `followSymlinks: false` is `lstat` semantics: the entry
591
+ // itself, exactly what the directory listing answers.
592
+ const verified = flatMap(uninstall, () => flatMap(sequence(ownedPaths.map((p) => exists(p, { followSymlinks: false }))), (stillThere) => {
593
+ const survivors = ownedPaths.filter((_, i) => stillThere[i]);
594
+ if (survivors.length === 0)
595
+ return pure(undefined);
596
+ // The remedy presents the surviving paths as DATA, never as a
597
+ // synthesized shell line: the names come from `readdirSync`, so
598
+ // no quoting is trustworthy, and one command cannot be right for
599
+ // every platform the editor registry supports.
600
+ return failPragma(new PragmaError({
601
+ code: "UNSUPPORTED",
602
+ message: `\`${command}\` exited 0, but the extension is still present after the undo ran.`,
603
+ recovery: {
604
+ message: `Delete ${survivors.length === 1 ? "this entry" : "these entries"} from ${editor.name}'s extensions folder by hand, then restart it: ${survivors.join(" · ")}`,
605
+ },
606
+ }));
607
+ }));
296
608
  return mkdir(extensionsDir, true, {
297
- undo: guardMissingBinary(editor.cli, {
298
- message: `The \`${editor.cli}\` CLI disappeared from PATH mid-run — restore it, then run \`${BIN_NAME} setup lsp --undo\` again.`,
299
- }, flatMap(exec(editor.cli, ["--uninstall-extension", EXTENSION_ID], extensionsDir), (result) => checkExecOk(command, result, {
300
- message: `${editor.name} refused the uninstall (its output is above). ` +
301
- `Remove it by hand with \`${command}\`.`,
302
- }))),
609
+ undo: guardMissingBinary(bin, {
610
+ message: `${editor.name}'s CLI disappeared mid-run — restore it, then run \`${BIN_NAME} setup lsp --undo\` again.`,
611
+ }, verified),
612
+ undoKey,
303
613
  });
304
614
  }));
305
615
  }
@@ -317,10 +627,10 @@ export function composeLspRemoval(d) {
317
627
  * @returns The uninstall command, or undefined.
318
628
  */
319
629
  export function lspUninstallRemedy(d) {
320
- const cli = ownedLspEditors(d).at(0)?.editor.cli;
321
- return cli === undefined
630
+ const owner = ownedLspEditors(d).at(0);
631
+ return owner === undefined
322
632
  ? undefined
323
- : `${cli} --uninstall-extension ${EXTENSION_ID}`;
633
+ : `${owner.cliPath} --uninstall-extension ${EXTENSION_ID}`;
324
634
  }
325
635
  /** The VSIX path a failed sideload leaves behind for a manual retry. */
326
636
  export function lspVsixPath(d) {
@@ -1 +1 @@
1
- {"version":3,"file":"setupLsp.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupLsp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAEL,IAAI,EACJ,OAAO,EACP,KAAK,EACL,SAAS,GAEV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGxE,uEAAuE;AACvE,MAAM,YAAY,GAAG,kCAAkC,CAAC;AAExD,sDAAsD;AACtD,MAAM,WAAW,GAAG,mCAAmC,CAAC;AAgDxD;;;;;;;;;;;;;;GAcG;AACH,MAAM,SAAS,GAAG,CAAC,UAA6B,EAAW,EAAE,CAC3D,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,MAAM,qBAAqB,GAAG,OAAO,CAAC;AAEtC,kDAAkD;AAClD,MAAM,OAAO,GAAa,qBAAqB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAEvE;;;GAGG;AACH,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,MAAM,YAAY,GAAG,CAAC,KAAa,EAAwB,EAAE,CAC3D,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,SAAS,CAAC;AAEhB,gFAAgF;AAChF,MAAM,eAAe,GAAG,CAAC,IAAc,EAAE,KAAe,EAAU,EAAE;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IAC9B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,cAAc,GAAG,CACrB,MAA2B,EAC3B,QAAqB,EACmB,EAAE;IAC1C,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,8BAA8B;IAC3E,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,YAAY,GAAG,CAAC;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CACxC,KAAK,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CACvC,CAAC;IACF,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACtC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACvE,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,CAAC,mCAAmC;QAC5E,OAAO,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,MAAM,EAAE,UAAU,EAAE,oBAAoB,EAAE,eAAe,EAAE,YAAY,EAAE,GACvE,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,MAAM,OAAO,GAAqB,UAAU;SACzC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,oBAAoB,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;SACzE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC9D,OAAO;YACL,MAAM;YACN,OAAO;YACP,SAAS,EAAE,OAAO;YAClB,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC;SAC9C,CAAC;IACJ,CAAC,CAAC,CAAC;IACL,MAAM,KAAK,GACT,OAAO,CAAC,MAAM,KAAK,CAAC;QAClB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YACjC,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,QAAQ,CAAC;IACjB,OAAO;QACL,SAAS,EAAE,IAAI;QACf,KAAK;QACL,OAAO;QACP,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;QAC9C,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,CAAe,EACf,MAA0B,EACC,EAAE;IAC7B,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACtD,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAe,EAAY,EAAE,CAC1D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAe,EAAU,EAAE,CACvD,yCAAyC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAElE;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAC1B,8FAA8F,CAAC;AAEjG;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CACxB,CAAe,EACf,MAA0B;IAE1B,uEAAuE;IACvE,2EAA2E;IAC3E,kEAAkE;IAClE,IAAI,CAAC,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3C,wEAAwE;IACxE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAEhC,2EAA2E;IAC3E,2EAA2E;IAC3E,uDAAuD;IACvD,MAAM,YAAY,GAAG,WAAW,WAAW,SAAS,CAAC;IACrD,MAAM,SAAS,GAAG,kBAAkB,CAClC,KAAK,EACL;QACE,OAAO,EAAE,4CAA4C,QAAQ,qBAAqB;KACnF,EACD,SAAS,CAAC;QACR,KAAK,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC;QACzB,OAAO,CACL,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,WAAW,SAAS,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAC3D,CAAC,MAAM,EAAE,EAAE,CACT,WAAW,CAAC,YAAY,EAAE,MAAoB,EAAE;YAC9C,OAAO,EACL,yHAAyH;gBACzH,KAAK,QAAQ,qBAAqB;SACrC,CAAC,CACL;KACF,CAAC,CACH,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,GAAG,wBAAwB,QAAQ,EAAE,CAAC;QAChE,OAAO,kBAAkB,CACvB,MAAM,CAAC,GAAG,EACV;YACE,OAAO,EAAE,SAAS,MAAM,CAAC,GAAG,iEAAiE,QAAQ,qBAAqB;SAC3H,EACD,OAAO,CACL,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EACjE,CAAC,MAAM,EAAE,EAAE,CACT,WAAW,CAAC,OAAO,EAAE,MAAoB,EAAE;YACzC,OAAO,EACL,GAAG,MAAM,CAAC,IAAI,gEAAgE,QAAQ,wBAAwB;gBAC9G,KAAK,OAAO,iBAAiB,MAAM,CAAC,IAAI,SAAS;SACpD,CAAC,CACL,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,CAAC,SAAS,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAe,EAA6B,EAAE,CAC5E,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAErC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAe;IAC/C,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACjC,6EAA6E;IAC7E,0EAA0E;IAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IAC7C,OAAO,SAAS,CACd,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE;QACtC,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,GAAG,0BAA0B,YAAY,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE;YAChC,IAAI,EAAE,kBAAkB,CACtB,MAAM,CAAC,GAAG,EACV;gBACE,OAAO,EAAE,SAAS,MAAM,CAAC,GAAG,iEAAiE,QAAQ,4BAA4B;aAClI,EACD,OAAO,CACL,IAAI,CACF,MAAM,CAAC,GAAG,EACV,CAAC,uBAAuB,EAAE,YAAY,CAAC,EACvC,aAAa,CACd,EACD,CAAC,MAAM,EAAE,EAAE,CACT,WAAW,CAAC,OAAO,EAAE,MAAoB,EAAE;gBACzC,OAAO,EACL,GAAG,MAAM,CAAC,IAAI,gDAAgD;oBAC9D,4BAA4B,OAAO,KAAK;aAC3C,CAAC,CACL,CACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAe;IAChD,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC;IACjD,OAAO,GAAG,KAAK,SAAS;QACtB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,GAAG,0BAA0B,YAAY,EAAE,CAAC;AACrD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,WAAW,CAAC,CAAe;IACzC,OAAO,IAAI,CACT,CAAC,CAAC,UAAU,EACZ,cAAc,EACd,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EACzB,mBAAmB,CACpB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"setupLsp.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupLsp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAEL,IAAI,EACJ,MAAM,EACN,OAAO,EACP,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,SAAS,GAEV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EACL,WAAW,EACX,UAAU,EACV,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAc,WAAW,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,EAAgB,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,WAAW,CAAC;AACxC,MAAM,cAAc,GAAG,wBAAwB,CAAC;AAEhD,uEAAuE;AACvE,MAAM,YAAY,GAAG,GAAG,mBAAmB,IAAI,cAAc,EAAE,CAAC;AAEhE,sDAAsD;AACtD,MAAM,WAAW,GAAG,mCAAmC,CAAC;AA6GxD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,GAAG,CAAC,CAAiB,EAAuB,EAAE,CAC7D,CAAC,CAAC,OAAO,KAAK,UAAU,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC;AAEpD,oEAAoE;AACpE,MAAM,cAAc,GAAG,CAAC,CAAe,EAA4B,EAAE,CACnE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAsB,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAoB/D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,GAAG,CAAC,UAA6B,EAAsB,EAAE,CACvE,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,MAAM,qBAAqB,GAAG,OAAO,CAAC;AAEtC,kDAAkD;AAClD,MAAM,OAAO,GAAa,qBAAqB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAEvE;;;GAGG;AACH,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,MAAM,YAAY,GAAG,CAAC,KAAa,EAAwB,EAAE,CAC3D,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,SAAS,CAAC;AAEhB,gFAAgF;AAChF,MAAM,eAAe,GAAG,CAAC,IAAc,EAAE,KAAe,EAAU,EAAE;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IAC9B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,cAAc,GAAG,CACrB,MAA2B,EAC3B,QAAqB,EACsC,EAAE;IAC7D,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;QAC9B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACzD,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,YAAY,GAAG,CAAC;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CACxC,KAAK,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CACvC,CAAC;IACF,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACtC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACvE,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,CAAC,mCAAmC;QAC5E,OAAO,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtE,CAAC,CAAC;AAYF;;;;;;;;;;;;;GAaG;AACH,MAAM,gBAAgB,GAAG,CACvB,MAA2B,EAC3B,IAAiB,EACjB,KAAkB,EACQ,EAAE;IAC5B,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACxE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACtE,MAAM,QAAQ,GAAG,UAAU,CACzB,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC,CAClE,CAAC;IACF,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC5E,4EAA4E;IAC5E,wEAAwE;IACxE,6CAA6C;IAC7C,MAAM,OAAO,GACX,MAAM,CAAC,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChD,IAAI,OAAO,KAAK,SAAS,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,GAAG,CACjB,MAA2B,EAC3B,IAAiB,EACjB,KAAkB,EAClB,KAAe,EACa,EAAE;IAC9B,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACrD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACjD,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,wDAAwD;IACxD,MAAM,KAAK,GACT,MAAM,CAAC,OAAO,KAAK,UAAU;QAC3B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,aAAa,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO;QACL,MAAM;QACN,GAAG,MAAM;QACT,OAAO;QACP,SAAS,EAAE,OAAO;QAClB,aAAa;QACb,cAAc,EAAE,OAAO;QACvB,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;KAC1C,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAY,EACZ,QAAsB,EACtB,KAAe;IAEf,MAAM,EACJ,mBAAmB,EACnB,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,aAAa,GACd,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACzC,uEAAuE;IACvE,4EAA4E;IAC5E,oCAAoC;IACpC,MAAM,IAAI,GAAG,QAAQ,IAAI,eAAe,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAgB;QACzB,mBAAmB;QACnB,oBAAoB;QACpB,aAAa;KACd,CAAC;IACF,MAAM,OAAO,GAAqB,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACrD,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GACT,OAAO,CAAC,MAAM,KAAK,CAAC;QAClB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YACjC,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,QAAQ,CAAC;IACjB,OAAO;QACL,SAAS,EAAE,IAAI;QACf,KAAK;QACL,OAAO;QACP,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;QAC9C,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,CAAe,EACf,MAA0B,EACC,EAAE;IAC7B,6EAA6E;IAC7E,4EAA4E;IAC5E,mEAAmE;IACnE,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAC9B,CAAC,CAAC,EAAuB,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,WAAW,CAAC,CAAC,CAAC,CAC3D,CAAC;IACF,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,CAAe,EACY,EAAE,CAC7B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAuB,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/E,8DAA8D;AAC9D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAe,EAAY,EAAE,CAC1D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAEtC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAe,EAAU,EAAE,CACvD,+CAA+C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,2EAA2E,CAAC;AAEhJ;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,CAAiB,EACjB,KAAY,EACJ,EAAE;IACV,IAAI,CAAC,CAAC,OAAO,KAAK,UAAU;QAAE,OAAO,oBAAoB,CAAC;IAC1D,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;IAC3D,OAAO,OAAO,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC;AAC3D,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,oBAAoB,GAAG,CAAC,CAAe,EAAU,EAAE,CACvD,iCAAiC,WAAW,gBAAgB,CAAC,CAAC,UAAU,uLAAuL,cAAc,mDAAmD,mBAAmB,uBAAuB,cAAc,2BAA2B,YAAY,oCAAoC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;AAEje;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,aAAa,GAAG,CACpB,CAAgB,EACyC,EAAE;IAC3D,wEAAwE;IACxE,0EAA0E;IAC1E,8EAA8E;IAC9E,IAAI,CAAC,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,0DAA0D;YAClE,MAAM,EAAE,GAAG,EAAE,CACX,gCAAgC,CAAC,CAAC,MAAM,CAAC,GAAG,2BAA2B,CAAC,CAAC,MAAM,CAAC,IAAI,kCAAkC,QAAQ,oBAAoB;SACrJ,CAAC;IACJ,CAAC;IACD,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,WAAW;YACd,OAAO;gBACL,MAAM,EAAE,oDAAoD,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG;gBAC/E,MAAM,EAAE,oBAAoB;aAC7B,CAAC;QACJ,KAAK,WAAW;YACd,OAAO;gBACL,qEAAqE;gBACrE,kEAAkE;gBAClE,MAAM,EAAE,sCAAsC,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG;gBAC7D,MAAM,EAAE,GAAG,EAAE,CACX,mDAAmD,QAAQ,oBAAoB;aAClF,CAAC;IACN,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAiB,EAAsB,EAAE,CACtE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,CAAe,EACqD,EAAE;IACtE,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACtC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAChD,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5E,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAC1B,8FAA8F,CAAC;AAEjG;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CACxB,CAAe,EACf,MAA0B;IAE1B,wEAAwE;IACxE,2EAA2E;IAC3E,kEAAkE;IAClE,IAAI,CAAC,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3C,wEAAwE;IACxE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAEhC,2EAA2E;IAC3E,2EAA2E;IAC3E,uDAAuD;IACvD,MAAM,YAAY,GAAG,WAAW,WAAW,SAAS,CAAC;IACrD,MAAM,SAAS,GAAG,kBAAkB,CAClC,KAAK,EACL;QACE,OAAO,EAAE,4CAA4C,QAAQ,qBAAqB;KACnF,EACD,SAAS,CAAC;QACR,KAAK,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC;QACzB,OAAO,CACL,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,WAAW,SAAS,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAC3D,CAAC,MAAM,EAAE,EAAE,CACT,WAAW,CAAC,YAAY,EAAE,MAAoB,EAAE;YAC9C,OAAO,EACL,yHAAyH;gBACzH,KAAK,QAAQ,qBAAqB;SACrC,CAAC,CACL;KACF,CAAC,CACH,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACpD,qEAAqE;QACrE,0EAA0E;QAC1E,uEAAuE;QACvE,YAAY;QACZ,MAAM,GAAG,GAAG,OAAO,CAAC;QACpB,MAAM,OAAO,GAAG,GAAG,GAAG,wBAAwB,QAAQ,EAAE,CAAC;QACzD,OAAO,kBAAkB,CACvB,GAAG,EACH;YACE,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,uDAAuD,QAAQ,qBAAqB;SAC5G,EACD,OAAO,CACL,IAAI,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAC1D,CAAC,MAAM,EAAE,EAAE,CACT,WAAW,CAAC,OAAO,EAAE,MAAoB,EAAE;YACzC,OAAO,EACL,GAAG,MAAM,CAAC,IAAI,gEAAgE,QAAQ,wBAAwB;gBAC9G,KAAK,OAAO,iBAAiB,MAAM,CAAC,IAAI,SAAS;SACpD,CAAC,CACL,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,CAAC,SAAS,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAe,EAA6B,EAAE;AAC5E,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,mBAAmB;AACnB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAuB,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,iBAAiB,CAC/B,CAAe,EACf,OAAgB;IAEhB,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACjC,6EAA6E;IAC7E,0EAA0E;IAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IAC7C,OAAO,SAAS,CACd,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,EAAE,EAAE;QAC/D,iEAAiE;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC;QACpB,MAAM,OAAO,GAAG,GAAG,GAAG,0BAA0B,YAAY,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC9C,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAC3B,CAAC;QACF,MAAM,SAAS,GAAG,OAAO,CACvB,IAAI,CAAC,GAAG,EAAE,CAAC,uBAAuB,EAAE,YAAY,CAAC,EAAE,aAAa,CAAC,EACjE,CAAC,MAAM,EAAE,EAAE,CACT,WAAW,CAAC,OAAO,EAAE,MAAoB,EAAE;YACzC,OAAO,EACL,GAAG,MAAM,CAAC,IAAI,gDAAgD;gBAC9D,4BAA4B,OAAO,KAAK;SAC3C,CAAC,CACL,CAAC;QACF,wEAAwE;QACxE,sEAAsE;QACtE,uEAAuE;QACvE,oEAAoE;QACpE,kEAAkE;QAClE,sEAAsE;QACtE,iEAAiE;QACjE,sDAAsD;QACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,EAAE,CACvC,OAAO,CACL,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EACrE,CAAC,UAAU,EAAE,EAAE;YACb,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;YACnD,8DAA8D;YAC9D,gEAAgE;YAChE,iEAAiE;YACjE,+CAA+C;YAC/C,OAAO,UAAU,CACf,IAAI,WAAW,CAAC;gBACd,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,KAAK,OAAO,qEAAqE;gBAC1F,QAAQ,EAAE;oBACR,OAAO,EAAE,UAAU,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,IAAI,kDAAkD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;iBACxK;aACF,CAAC,CACH,CAAC;QACJ,CAAC,CACF,CACF,CAAC;QACF,OAAO,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE;YAChC,IAAI,EAAE,kBAAkB,CACtB,GAAG,EACH;gBACE,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,uDAAuD,QAAQ,4BAA4B;aACnH,EACD,QAAQ,CACT;YACD,OAAO;SACR,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAe;IAChD,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,KAAK,KAAK,SAAS;QACxB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,0BAA0B,YAAY,EAAE,CAAC;AAC/D,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,WAAW,CAAC,CAAe;IACzC,OAAO,IAAI,CACT,CAAC,CAAC,UAAU,EACZ,cAAc,EACd,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EACzB,mBAAmB,CACpB,CAAC;AACJ,CAAC"}