@12ui/design 0.2.56 → 0.2.58

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 (429) hide show
  1. package/SKILL.md +1 -1
  2. package/dist/artifact-materializer.d.ts.map +1 -1
  3. package/dist/artifact-materializer.js +4 -1
  4. package/dist/artifact-materializer.js.map +1 -1
  5. package/dist/branch-client.d.ts +86 -2
  6. package/dist/branch-client.d.ts.map +1 -1
  7. package/dist/branch-client.js +31 -0
  8. package/dist/branch-client.js.map +1 -1
  9. package/dist/cli-arguments.d.ts.map +1 -1
  10. package/dist/cli-arguments.js +3 -1
  11. package/dist/cli-arguments.js.map +1 -1
  12. package/dist/cli-capabilities.d.ts +1 -1
  13. package/dist/cli-conversion-derivation.js +2 -2
  14. package/dist/cli-conversion-derivation.js.map +1 -1
  15. package/dist/cli-convert-command.d.ts +2 -0
  16. package/dist/cli-convert-command.d.ts.map +1 -1
  17. package/dist/cli-convert-command.js +176 -38
  18. package/dist/cli-convert-command.js.map +1 -1
  19. package/dist/cli-corpus-command.js +2 -2
  20. package/dist/cli-corpus-command.js.map +1 -1
  21. package/dist/cli-corpus-evidence.d.ts.map +1 -1
  22. package/dist/cli-corpus-evidence.js +2 -1
  23. package/dist/cli-corpus-evidence.js.map +1 -1
  24. package/dist/cli-corpus-reference-downloads.d.ts +1 -0
  25. package/dist/cli-corpus-reference-downloads.d.ts.map +1 -1
  26. package/dist/cli-corpus-reference-downloads.js +13 -3
  27. package/dist/cli-corpus-reference-downloads.js.map +1 -1
  28. package/dist/cli-corpus-types.d.ts +2 -0
  29. package/dist/cli-corpus-types.d.ts.map +1 -1
  30. package/dist/cli-draft-command.d.ts +9 -0
  31. package/dist/cli-draft-command.d.ts.map +1 -1
  32. package/dist/cli-draft-command.js +26 -1
  33. package/dist/cli-draft-command.js.map +1 -1
  34. package/dist/cli-help/design.d.ts +7 -4
  35. package/dist/cli-help/design.d.ts.map +1 -1
  36. package/dist/cli-help/design.js +23 -6
  37. package/dist/cli-help/design.js.map +1 -1
  38. package/dist/cli-help/index.d.ts +9 -6
  39. package/dist/cli-help/index.d.ts.map +1 -1
  40. package/dist/cli-help/meta.d.ts +2 -2
  41. package/dist/cli-help/meta.d.ts.map +1 -1
  42. package/dist/cli-help/meta.js +4 -1
  43. package/dist/cli-help/meta.js.map +1 -1
  44. package/dist/cli-improve-command.d.ts.map +1 -1
  45. package/dist/cli-improve-command.js +273 -28
  46. package/dist/cli-improve-command.js.map +1 -1
  47. package/dist/cli-redesign-command.d.ts.map +1 -1
  48. package/dist/cli-redesign-command.js +97 -24
  49. package/dist/cli-redesign-command.js.map +1 -1
  50. package/dist/cli-run.d.ts.map +1 -1
  51. package/dist/cli-run.js +13 -3
  52. package/dist/cli-run.js.map +1 -1
  53. package/dist/cli-spend-command.d.ts +12 -1
  54. package/dist/cli-spend-command.d.ts.map +1 -1
  55. package/dist/cli-spend-command.js +94 -2
  56. package/dist/cli-spend-command.js.map +1 -1
  57. package/dist/cli-usage.js +5 -5
  58. package/dist/cli-usage.js.map +1 -1
  59. package/dist/concept-input.d.ts +6 -56
  60. package/dist/concept-input.d.ts.map +1 -1
  61. package/dist/concept-input.js +6 -65
  62. package/dist/concept-input.js.map +1 -1
  63. package/dist/conversion-client.d.ts +92 -3
  64. package/dist/conversion-client.d.ts.map +1 -1
  65. package/dist/conversion-client.js +317 -23
  66. package/dist/conversion-client.js.map +1 -1
  67. package/dist/corpus-client.d.ts +7 -1
  68. package/dist/corpus-client.d.ts.map +1 -1
  69. package/dist/corpus-client.js +3 -2
  70. package/dist/corpus-client.js.map +1 -1
  71. package/dist/corpus-reference-download-retry.d.ts +68 -0
  72. package/dist/corpus-reference-download-retry.d.ts.map +1 -0
  73. package/dist/corpus-reference-download-retry.js +123 -0
  74. package/dist/corpus-reference-download-retry.js.map +1 -0
  75. package/dist/corpus-request-error.d.ts +17 -0
  76. package/dist/corpus-request-error.d.ts.map +1 -0
  77. package/dist/corpus-request-error.js +21 -0
  78. package/dist/corpus-request-error.js.map +1 -0
  79. package/dist/draft-run.d.ts +15 -0
  80. package/dist/draft-run.d.ts.map +1 -1
  81. package/dist/draft-run.js +32 -5
  82. package/dist/draft-run.js.map +1 -1
  83. package/dist/draft-workspace.d.ts +2 -1
  84. package/dist/draft-workspace.d.ts.map +1 -1
  85. package/dist/draft-workspace.js.map +1 -1
  86. package/dist/hosted-draft-identity.d.ts +9 -0
  87. package/dist/hosted-draft-identity.d.ts.map +1 -1
  88. package/dist/hosted-draft-identity.js +2 -0
  89. package/dist/hosted-draft-identity.js.map +1 -1
  90. package/dist/improve-added-specs.d.ts +12 -31
  91. package/dist/improve-added-specs.d.ts.map +1 -1
  92. package/dist/improve-added-specs.js +64 -152
  93. package/dist/improve-added-specs.js.map +1 -1
  94. package/dist/improve-artifact-writer.d.ts +13 -0
  95. package/dist/improve-artifact-writer.d.ts.map +1 -0
  96. package/dist/improve-artifact-writer.js +27 -0
  97. package/dist/improve-artifact-writer.js.map +1 -0
  98. package/dist/improve-bootstrap-history.d.ts +21 -0
  99. package/dist/improve-bootstrap-history.d.ts.map +1 -0
  100. package/dist/improve-bootstrap-history.js +43 -0
  101. package/dist/improve-bootstrap-history.js.map +1 -0
  102. package/dist/improve-bootstrap-secret.d.ts +35 -0
  103. package/dist/improve-bootstrap-secret.d.ts.map +1 -0
  104. package/dist/improve-bootstrap-secret.js +61 -0
  105. package/dist/improve-bootstrap-secret.js.map +1 -0
  106. package/dist/improve-branch-stage.d.ts +10 -0
  107. package/dist/improve-branch-stage.d.ts.map +1 -0
  108. package/dist/improve-branch-stage.js +325 -0
  109. package/dist/improve-branch-stage.js.map +1 -0
  110. package/dist/improve-capture-redirect.d.ts +65 -0
  111. package/dist/improve-capture-redirect.d.ts.map +1 -0
  112. package/dist/improve-capture-redirect.js +85 -0
  113. package/dist/improve-capture-redirect.js.map +1 -0
  114. package/dist/improve-capture-words.d.ts +43 -0
  115. package/dist/improve-capture-words.d.ts.map +1 -0
  116. package/dist/improve-capture-words.js +25 -0
  117. package/dist/improve-capture-words.js.map +1 -0
  118. package/dist/improve-concept.d.ts +6 -7
  119. package/dist/improve-concept.d.ts.map +1 -1
  120. package/dist/improve-concept.js +12 -38
  121. package/dist/improve-concept.js.map +1 -1
  122. package/dist/improve-conversion-attempts.d.ts +21 -9
  123. package/dist/improve-conversion-attempts.d.ts.map +1 -1
  124. package/dist/improve-conversion-attempts.js +6 -1
  125. package/dist/improve-conversion-attempts.js.map +1 -1
  126. package/dist/improve-conversion-stage.d.ts +20 -2
  127. package/dist/improve-conversion-stage.d.ts.map +1 -1
  128. package/dist/improve-conversion-stage.js +386 -178
  129. package/dist/improve-conversion-stage.js.map +1 -1
  130. package/dist/improve-convert-progress.d.ts +44 -0
  131. package/dist/improve-convert-progress.d.ts.map +1 -0
  132. package/dist/improve-convert-progress.js +47 -0
  133. package/dist/improve-convert-progress.js.map +1 -0
  134. package/dist/improve-convert-resilience.d.ts +96 -58
  135. package/dist/improve-convert-resilience.d.ts.map +1 -1
  136. package/dist/improve-convert-resilience.js +128 -72
  137. package/dist/improve-convert-resilience.js.map +1 -1
  138. package/dist/improve-core/concept-input.d.ts +80 -0
  139. package/dist/improve-core/concept-input.d.ts.map +1 -0
  140. package/dist/improve-core/concept-input.js +92 -0
  141. package/dist/improve-core/concept-input.js.map +1 -0
  142. package/dist/improve-core/improve-added-specs.d.ts +62 -0
  143. package/dist/improve-core/improve-added-specs.d.ts.map +1 -0
  144. package/dist/improve-core/improve-added-specs.js +160 -0
  145. package/dist/improve-core/improve-added-specs.js.map +1 -0
  146. package/dist/improve-core/improve-artifacts.d.ts +18 -0
  147. package/dist/improve-core/improve-artifacts.d.ts.map +1 -0
  148. package/dist/improve-core/improve-artifacts.js +4 -0
  149. package/dist/improve-core/improve-artifacts.js.map +1 -0
  150. package/dist/improve-core/improve-concept.d.ts +7 -0
  151. package/dist/improve-core/improve-concept.d.ts.map +1 -0
  152. package/dist/improve-core/improve-concept.js +185 -0
  153. package/dist/improve-core/improve-concept.js.map +1 -0
  154. package/dist/improve-core/improve-discovery.d.ts +84 -0
  155. package/dist/improve-core/improve-discovery.d.ts.map +1 -0
  156. package/dist/improve-core/improve-discovery.js +154 -0
  157. package/dist/improve-core/improve-discovery.js.map +1 -0
  158. package/dist/improve-core/improve-dom-anchor.d.ts.map +1 -0
  159. package/dist/{improve-dom-anchor.js → improve-core/improve-dom-anchor.js} +2 -0
  160. package/dist/improve-core/improve-dom-anchor.js.map +1 -0
  161. package/dist/improve-core/improve-dom-diff.d.ts +59 -0
  162. package/dist/improve-core/improve-dom-diff.d.ts.map +1 -0
  163. package/dist/improve-core/improve-dom-diff.js +151 -0
  164. package/dist/improve-core/improve-dom-diff.js.map +1 -0
  165. package/dist/improve-core/improve-dom-extract.d.ts.map +1 -0
  166. package/dist/{improve-dom-extract.js → improve-core/improve-dom-extract.js} +2 -0
  167. package/dist/improve-core/improve-dom-extract.js.map +1 -0
  168. package/dist/improve-core/improve-dom-gate.d.ts +49 -0
  169. package/dist/improve-core/improve-dom-gate.d.ts.map +1 -0
  170. package/dist/improve-core/improve-dom-gate.js +99 -0
  171. package/dist/improve-core/improve-dom-gate.js.map +1 -0
  172. package/dist/improve-core/improve-dom-neighbour.d.ts.map +1 -0
  173. package/dist/{improve-dom-neighbour.js → improve-core/improve-dom-neighbour.js} +2 -0
  174. package/dist/improve-core/improve-dom-neighbour.js.map +1 -0
  175. package/dist/improve-core/improve-dom-scale.d.ts.map +1 -0
  176. package/dist/{improve-dom-scale.js → improve-core/improve-dom-scale.js} +2 -0
  177. package/dist/improve-core/improve-dom-scale.js.map +1 -0
  178. package/dist/improve-core/improve-icon-svg.d.ts +29 -0
  179. package/dist/improve-core/improve-icon-svg.d.ts.map +1 -0
  180. package/dist/improve-core/improve-icon-svg.js +85 -0
  181. package/dist/improve-core/improve-icon-svg.js.map +1 -0
  182. package/dist/improve-core/improve-kit-asset-model.d.ts +177 -0
  183. package/dist/improve-core/improve-kit-asset-model.d.ts.map +1 -0
  184. package/dist/improve-core/improve-kit-asset-model.js +269 -0
  185. package/dist/improve-core/improve-kit-asset-model.js.map +1 -0
  186. package/dist/improve-core/improve-layerdoc-diff.d.ts.map +1 -0
  187. package/dist/{improve-layerdoc-diff.js → improve-core/improve-layerdoc-diff.js} +2 -0
  188. package/dist/improve-core/improve-layerdoc-diff.js.map +1 -0
  189. package/dist/{improve-layerdoc-types.d.ts → improve-core/improve-layerdoc-types.d.ts} +9 -0
  190. package/dist/improve-core/improve-layerdoc-types.d.ts.map +1 -0
  191. package/dist/improve-core/improve-layerdoc-types.js +4 -0
  192. package/dist/improve-core/improve-layerdoc-types.js.map +1 -0
  193. package/dist/improve-core/improve-page-words.d.ts +180 -0
  194. package/dist/improve-core/improve-page-words.d.ts.map +1 -0
  195. package/dist/improve-core/improve-page-words.js +303 -0
  196. package/dist/improve-core/improve-page-words.js.map +1 -0
  197. package/dist/{improve-plan-annotated-render.d.ts → improve-core/improve-plan-annotated-render.d.ts} +19 -2
  198. package/dist/improve-core/improve-plan-annotated-render.d.ts.map +1 -0
  199. package/dist/{improve-plan-annotated-render.js → improve-core/improve-plan-annotated-render.js} +77 -28
  200. package/dist/improve-core/improve-plan-annotated-render.js.map +1 -0
  201. package/dist/improve-core/improve-plan-annotator.d.ts +34 -0
  202. package/dist/improve-core/improve-plan-annotator.d.ts.map +1 -0
  203. package/dist/improve-core/improve-plan-annotator.js +52 -0
  204. package/dist/improve-core/improve-plan-annotator.js.map +1 -0
  205. package/dist/{improve-plan-render.d.ts → improve-core/improve-plan-render.d.ts} +2 -1
  206. package/dist/improve-core/improve-plan-render.d.ts.map +1 -0
  207. package/dist/{improve-plan-render.js → improve-core/improve-plan-render.js} +7 -1
  208. package/dist/improve-core/improve-plan-render.js.map +1 -0
  209. package/dist/improve-core/improve-plan-vector-keep.d.ts +29 -0
  210. package/dist/improve-core/improve-plan-vector-keep.d.ts.map +1 -0
  211. package/dist/improve-core/improve-plan-vector-keep.js +68 -0
  212. package/dist/improve-core/improve-plan-vector-keep.js.map +1 -0
  213. package/dist/{improve-raster-layers-section.d.ts → improve-core/improve-raster-layers-section.d.ts} +9 -1
  214. package/dist/improve-core/improve-raster-layers-section.d.ts.map +1 -0
  215. package/dist/{improve-raster-layers-section.js → improve-core/improve-raster-layers-section.js} +5 -2
  216. package/dist/improve-core/improve-raster-layers-section.js.map +1 -0
  217. package/dist/improve-core/improve-refusal.d.ts +6 -0
  218. package/dist/improve-core/improve-refusal.d.ts.map +1 -0
  219. package/dist/improve-core/improve-refusal.js +27 -0
  220. package/dist/improve-core/improve-refusal.js.map +1 -0
  221. package/dist/improve-core/improve-retain.d.ts +121 -0
  222. package/dist/improve-core/improve-retain.d.ts.map +1 -0
  223. package/dist/improve-core/improve-retain.js +115 -0
  224. package/dist/improve-core/improve-retain.js.map +1 -0
  225. package/dist/improve-core/improve-site-plan.d.ts +75 -0
  226. package/dist/improve-core/improve-site-plan.d.ts.map +1 -0
  227. package/dist/improve-core/improve-site-plan.js +135 -0
  228. package/dist/improve-core/improve-site-plan.js.map +1 -0
  229. package/dist/improve-core/improve-site-shell.d.ts +56 -0
  230. package/dist/improve-core/improve-site-shell.d.ts.map +1 -0
  231. package/dist/improve-core/improve-site-shell.js +152 -0
  232. package/dist/improve-core/improve-site-shell.js.map +1 -0
  233. package/dist/improve-core/improve-site-tokens.d.ts +44 -0
  234. package/dist/improve-core/improve-site-tokens.d.ts.map +1 -0
  235. package/dist/improve-core/improve-site-tokens.js +87 -0
  236. package/dist/improve-core/improve-site-tokens.js.map +1 -0
  237. package/dist/improve-core/improve-source-hints.d.ts +25 -0
  238. package/dist/improve-core/improve-source-hints.d.ts.map +1 -0
  239. package/dist/improve-core/improve-source-hints.js +17 -0
  240. package/dist/improve-core/improve-source-hints.js.map +1 -0
  241. package/dist/{improve-token-patch.d.ts → improve-core/improve-token-patch.d.ts} +2 -0
  242. package/dist/improve-core/improve-token-patch.d.ts.map +1 -0
  243. package/dist/{improve-token-patch.js → improve-core/improve-token-patch.js} +25 -5
  244. package/dist/improve-core/improve-token-patch.js.map +1 -0
  245. package/dist/improve-core/index.d.ts +47 -0
  246. package/dist/improve-core/index.d.ts.map +1 -0
  247. package/dist/improve-core/index.js +49 -0
  248. package/dist/improve-core/index.js.map +1 -0
  249. package/dist/improve-delivery-stages.d.ts +6 -0
  250. package/dist/improve-delivery-stages.d.ts.map +1 -1
  251. package/dist/improve-delivery-stages.js +91 -6
  252. package/dist/improve-delivery-stages.js.map +1 -1
  253. package/dist/improve-dom-diff.d.ts +8 -24
  254. package/dist/improve-dom-diff.d.ts.map +1 -1
  255. package/dist/improve-dom-diff.js +23 -123
  256. package/dist/improve-dom-diff.js.map +1 -1
  257. package/dist/improve-dom-gate.d.ts +1 -18
  258. package/dist/improve-dom-gate.d.ts.map +1 -1
  259. package/dist/improve-dom-gate.js +1 -46
  260. package/dist/improve-dom-gate.js.map +1 -1
  261. package/dist/improve-generation-stages.d.ts +0 -2
  262. package/dist/improve-generation-stages.d.ts.map +1 -1
  263. package/dist/improve-generation-stages.js +191 -15
  264. package/dist/improve-generation-stages.js.map +1 -1
  265. package/dist/improve-kit-assets.d.ts +8 -116
  266. package/dist/improve-kit-assets.d.ts.map +1 -1
  267. package/dist/improve-kit-assets.js +9 -229
  268. package/dist/improve-kit-assets.js.map +1 -1
  269. package/dist/improve-kit-ignore.d.ts +32 -0
  270. package/dist/improve-kit-ignore.d.ts.map +1 -0
  271. package/dist/improve-kit-ignore.js +111 -0
  272. package/dist/improve-kit-ignore.js.map +1 -0
  273. package/dist/improve-kit-readme.d.ts +4 -0
  274. package/dist/improve-kit-readme.d.ts.map +1 -1
  275. package/dist/improve-kit-readme.js +155 -24
  276. package/dist/improve-kit-readme.js.map +1 -1
  277. package/dist/improve-kit-stall.d.ts +51 -3
  278. package/dist/improve-kit-stall.d.ts.map +1 -1
  279. package/dist/improve-kit-stall.js +205 -21
  280. package/dist/improve-kit-stall.js.map +1 -1
  281. package/dist/improve-kit-status.d.ts +36 -0
  282. package/dist/improve-kit-status.d.ts.map +1 -1
  283. package/dist/improve-kit-status.js +82 -7
  284. package/dist/improve-kit-status.js.map +1 -1
  285. package/dist/improve-options.d.ts +14 -0
  286. package/dist/improve-options.d.ts.map +1 -1
  287. package/dist/improve-options.js +95 -12
  288. package/dist/improve-options.js.map +1 -1
  289. package/dist/improve-passthrough-flags.d.ts +8 -0
  290. package/dist/improve-passthrough-flags.d.ts.map +1 -0
  291. package/dist/improve-passthrough-flags.js +11 -0
  292. package/dist/improve-passthrough-flags.js.map +1 -0
  293. package/dist/improve-plan-annotator.d.ts +13 -2
  294. package/dist/improve-plan-annotator.d.ts.map +1 -1
  295. package/dist/improve-plan-annotator.js +35 -37
  296. package/dist/improve-plan-annotator.js.map +1 -1
  297. package/dist/improve-pricing-plan.d.ts +3 -0
  298. package/dist/improve-pricing-plan.d.ts.map +1 -1
  299. package/dist/improve-pricing-plan.js +33 -5
  300. package/dist/improve-pricing-plan.js.map +1 -1
  301. package/dist/improve-recheck.d.ts +9 -0
  302. package/dist/improve-recheck.d.ts.map +1 -0
  303. package/dist/improve-recheck.js +200 -0
  304. package/dist/improve-recheck.js.map +1 -0
  305. package/dist/improve-reset.d.ts.map +1 -1
  306. package/dist/improve-reset.js +11 -0
  307. package/dist/improve-reset.js.map +1 -1
  308. package/dist/improve-run-summary.d.ts +6 -0
  309. package/dist/improve-run-summary.d.ts.map +1 -1
  310. package/dist/improve-run-summary.js +77 -7
  311. package/dist/improve-run-summary.js.map +1 -1
  312. package/dist/improve-site-plan.d.ts +57 -0
  313. package/dist/improve-site-plan.d.ts.map +1 -0
  314. package/dist/improve-site-plan.js +79 -0
  315. package/dist/improve-site-plan.js.map +1 -0
  316. package/dist/improve-site-shell.d.ts +11 -0
  317. package/dist/improve-site-shell.d.ts.map +1 -0
  318. package/dist/improve-site-shell.js +24 -0
  319. package/dist/improve-site-shell.js.map +1 -0
  320. package/dist/improve-site-stage.d.ts +10 -0
  321. package/dist/improve-site-stage.d.ts.map +1 -0
  322. package/dist/improve-site-stage.js +84 -0
  323. package/dist/improve-site-stage.js.map +1 -0
  324. package/dist/improve-site-tokens.d.ts +9 -0
  325. package/dist/improve-site-tokens.d.ts.map +1 -0
  326. package/dist/improve-site-tokens.js +17 -0
  327. package/dist/improve-site-tokens.js.map +1 -0
  328. package/dist/improve-source-hints.d.ts +3 -12
  329. package/dist/improve-source-hints.d.ts.map +1 -1
  330. package/dist/improve-source-hints.js +4 -5
  331. package/dist/improve-source-hints.js.map +1 -1
  332. package/dist/improve-spend-ledger.d.ts +69 -0
  333. package/dist/improve-spend-ledger.d.ts.map +1 -0
  334. package/dist/improve-spend-ledger.js +118 -0
  335. package/dist/improve-spend-ledger.js.map +1 -0
  336. package/dist/improve-stage-runners.d.ts +5 -2
  337. package/dist/improve-stage-runners.d.ts.map +1 -1
  338. package/dist/improve-stage-runners.js +5 -2
  339. package/dist/improve-stage-runners.js.map +1 -1
  340. package/dist/improve-stage-shared.d.ts +49 -2
  341. package/dist/improve-stage-shared.d.ts.map +1 -1
  342. package/dist/improve-stage-shared.js +80 -3
  343. package/dist/improve-stage-shared.js.map +1 -1
  344. package/dist/improve-stop-handler.d.ts +15 -0
  345. package/dist/improve-stop-handler.d.ts.map +1 -1
  346. package/dist/improve-stop-handler.js +74 -3
  347. package/dist/improve-stop-handler.js.map +1 -1
  348. package/dist/improve-terminal-event.d.ts.map +1 -1
  349. package/dist/improve-terminal-event.js +13 -4
  350. package/dist/improve-terminal-event.js.map +1 -1
  351. package/dist/improve-workspace.d.ts +282 -9
  352. package/dist/improve-workspace.d.ts.map +1 -1
  353. package/dist/improve-workspace.js +250 -78
  354. package/dist/improve-workspace.js.map +1 -1
  355. package/dist/index.d.ts +2 -1
  356. package/dist/index.d.ts.map +1 -1
  357. package/dist/index.js +1 -0
  358. package/dist/index.js.map +1 -1
  359. package/dist/legacy-skill-catalog.d.ts.map +1 -1
  360. package/dist/legacy-skill-catalog.js +202 -0
  361. package/dist/legacy-skill-catalog.js.map +1 -1
  362. package/dist/mcp-convert.js +1 -1
  363. package/dist/mcp-convert.js.map +1 -1
  364. package/dist/redesign-capture.d.ts +146 -15
  365. package/dist/redesign-capture.d.ts.map +1 -1
  366. package/dist/redesign-capture.js +182 -65
  367. package/dist/redesign-capture.js.map +1 -1
  368. package/dist/redesign-workspace.d.ts +13 -0
  369. package/dist/redesign-workspace.d.ts.map +1 -1
  370. package/dist/redesign-workspace.js +14 -0
  371. package/dist/redesign-workspace.js.map +1 -1
  372. package/dist/responsive-alternative-materializer.d.ts +24 -0
  373. package/dist/responsive-alternative-materializer.d.ts.map +1 -0
  374. package/dist/responsive-alternative-materializer.js +93 -0
  375. package/dist/responsive-alternative-materializer.js.map +1 -0
  376. package/dist/result-integrity.d.ts +38 -0
  377. package/dist/result-integrity.d.ts.map +1 -0
  378. package/dist/result-integrity.js +46 -0
  379. package/dist/result-integrity.js.map +1 -0
  380. package/dist/review-edit-source.d.ts.map +1 -1
  381. package/dist/review-edit-source.js +6 -2
  382. package/dist/review-edit-source.js.map +1 -1
  383. package/dist/review-edit.js +2 -2
  384. package/dist/review-edit.js.map +1 -1
  385. package/dist/review-prototype-gap.js +1 -1
  386. package/dist/review-prototype-gap.js.map +1 -1
  387. package/dist/spend-run-filter.d.ts +21 -0
  388. package/dist/spend-run-filter.d.ts.map +1 -0
  389. package/dist/spend-run-filter.js +65 -0
  390. package/dist/spend-run-filter.js.map +1 -0
  391. package/dist/spend-scoped-report-lines.d.ts +4 -0
  392. package/dist/spend-scoped-report-lines.d.ts.map +1 -0
  393. package/dist/spend-scoped-report-lines.js +46 -0
  394. package/dist/spend-scoped-report-lines.js.map +1 -0
  395. package/dist/spend-scoped-report.d.ts +28 -0
  396. package/dist/spend-scoped-report.d.ts.map +1 -0
  397. package/dist/spend-scoped-report.js +45 -0
  398. package/dist/spend-scoped-report.js.map +1 -0
  399. package/open-design.json +2 -2
  400. package/package.json +5 -5
  401. package/skills/12ui-design/SKILL.md +14 -4
  402. package/skills/12ui-design/improve.md +67 -5
  403. package/skills/12ui-design/inspire.md +1 -1
  404. package/dist/improve-dom-anchor.d.ts.map +0 -1
  405. package/dist/improve-dom-anchor.js.map +0 -1
  406. package/dist/improve-dom-extract.d.ts.map +0 -1
  407. package/dist/improve-dom-extract.js.map +0 -1
  408. package/dist/improve-dom-neighbour.d.ts.map +0 -1
  409. package/dist/improve-dom-neighbour.js.map +0 -1
  410. package/dist/improve-dom-scale.d.ts.map +0 -1
  411. package/dist/improve-dom-scale.js.map +0 -1
  412. package/dist/improve-layerdoc-diff.d.ts.map +0 -1
  413. package/dist/improve-layerdoc-diff.js.map +0 -1
  414. package/dist/improve-layerdoc-types.d.ts.map +0 -1
  415. package/dist/improve-layerdoc-types.js +0 -2
  416. package/dist/improve-layerdoc-types.js.map +0 -1
  417. package/dist/improve-plan-annotated-render.d.ts.map +0 -1
  418. package/dist/improve-plan-annotated-render.js.map +0 -1
  419. package/dist/improve-plan-render.d.ts.map +0 -1
  420. package/dist/improve-plan-render.js.map +0 -1
  421. package/dist/improve-raster-layers-section.d.ts.map +0 -1
  422. package/dist/improve-raster-layers-section.js.map +0 -1
  423. package/dist/improve-token-patch.d.ts.map +0 -1
  424. package/dist/improve-token-patch.js.map +0 -1
  425. /package/dist/{improve-dom-anchor.d.ts → improve-core/improve-dom-anchor.d.ts} +0 -0
  426. /package/dist/{improve-dom-extract.d.ts → improve-core/improve-dom-extract.d.ts} +0 -0
  427. /package/dist/{improve-dom-neighbour.d.ts → improve-core/improve-dom-neighbour.d.ts} +0 -0
  428. /package/dist/{improve-dom-scale.d.ts → improve-core/improve-dom-scale.d.ts} +0 -0
  429. /package/dist/{improve-layerdoc-diff.d.ts → improve-core/improve-layerdoc-diff.d.ts} +0 -0
@@ -1,14 +1,18 @@
1
1
  import { copyFile, cp, readFile, stat } from 'node:fs/promises';
2
2
  import sharp from 'sharp';
3
3
  import { runConversionCommand } from './cli-convert-command.js';
4
+ import { formatDuration } from './cli-progress.js';
5
+ import { createImproveConvertProgress, } from './improve-convert-progress.js';
4
6
  import { CliRefusal } from './cli-refusal.js';
5
7
  import { prepareOutputDirectory } from './cli-output-paths.js';
6
- import { fixedImproveHtml, improveConversionIdFromText, improveConvertRetryKey, improveConvertStallCount, improveConvertStallExhausted, improveConvertStallReason, improveConvertStallRetryAllowed, improveErrorText, improveStalled, IMPROVE_CONVERT_STALL_ATTEMPTS, IMPROVE_FRESH_ABANDON_REASON, prepareImproveTargetAttempt, resetImproveTargetAttempt, responsiveFallbackReason, } from './improve-convert-resilience.js';
8
+ import { fixedImproveHtml, improveConversionIdFromText, improveConvertRetryKey, improveConvertStallCount, improveConvertStallHalted, improveErrorText, improveStalled, IMPROVE_FRESH_ABANDON_REASON, prepareImproveTargetAttempt, responsiveFallbackReason, } from './improve-convert-resilience.js';
9
+ import { createConcurrencyLimiter } from './bounded-concurrency.js';
7
10
  import { improveFreshConversionKey, noteImproveConversionAttemptId, openImproveConversionAttempt, settleImproveConversionAttempt, startImproveConversionAttempt, } from './improve-conversion-attempts.js';
8
- import { canvasOfDoc } from './improve-layerdoc-diff.js';
9
- import { abandonImproveConversion, abandonImproveConversions, noteAbandonedAttempts, withoutImproveStages, } from './improve-reset.js';
10
- import { improveSha256, noteImproveStage, } from './improve-stage-shared.js';
11
- import { readImproveRecord, writeImproveRecord } from './improve-workspace.js';
11
+ import { canvasOfDoc } from './improve-core/index.js';
12
+ import { trackImproveDurableWrite } from './improve-stop-handler.js';
13
+ import { abandonImproveConversion, noteAbandonedAttempts, withoutImproveStages, } from './improve-reset.js';
14
+ import { improveSha256, noteImproveStage, noteImproveStageDispatched, } from './improve-stage-shared.js';
15
+ import { improvePagePaths, readImproveRecord, writeImproveRecord, } from './improve-workspace.js';
12
16
  export const runImproveConversion = async (args) => {
13
17
  const artifacts = [];
14
18
  const purchaseIds = [];
@@ -18,25 +22,33 @@ export const runImproveConversion = async (args) => {
18
22
  artifacts.push(...(facts.artifacts ?? []));
19
23
  purchaseIds.push(...(facts.purchased ?? []));
20
24
  if (facts.runId) {
21
- if (!runIds.includes(facts.runId))
25
+ if (!runIds.includes(facts.runId)) {
22
26
  args.onConversionId?.(facts.runId);
27
+ args.progress?.noteConversionId(facts.runId);
28
+ }
23
29
  runIds.push(facts.runId);
24
30
  }
25
31
  args.journal?.note(facts);
26
32
  },
27
- heartbeat: (progress) => { args.journal?.heartbeat(progress); },
33
+ heartbeat: (progress) => {
34
+ args.journal?.heartbeat(progress);
35
+ args.progress?.heartbeat(progress);
36
+ },
28
37
  };
29
38
  const flags = {
39
+ ...args.passthrough,
30
40
  output: args.output,
31
41
  ...(args.model ? { model: args.model } : {}),
32
42
  ...(args.responsiveQuality ? { 'responsive-quality': args.responsiveQuality } : {}),
33
- ...(args.timeoutMs === undefined ? {} : { 'timeout-ms': String(args.timeoutMs) }),
34
43
  'out-dir': args.outDir,
35
44
  'idempotency-key': args.key,
36
45
  quiet: true,
37
46
  };
38
47
  try {
39
- await args.runner(['convert', args.input], flags, collector, { writeResult: () => undefined });
48
+ await args.runner(['convert', args.input], flags, collector, {
49
+ writeResult: () => undefined,
50
+ ...(args.stallTimeoutMs === undefined ? {} : { stallTimeoutMs: args.stallTimeoutMs }),
51
+ });
40
52
  }
41
53
  catch (error) {
42
54
  throw new ImproveConvertAttemptError(error, {
@@ -71,7 +83,7 @@ const recordFreshConversion = async (args) => {
71
83
  reason: IMPROVE_FRESH_ABANDON_REASON,
72
84
  warn: args.dependencies.warn ?? ((line) => { console.warn(line); }),
73
85
  });
74
- const record = withoutImproveStages(abandoned.record, ['convert', 'plan']);
86
+ const record = withoutImproveStages(abandoned.record, ['convert', 'plan', 'site']);
75
87
  await writeImproveRecord(args.options.paths.record, record);
76
88
  return record;
77
89
  };
@@ -129,14 +141,14 @@ export const runImproveConvertStage = async (args) => {
129
141
  throw new Error('Improve has no design image to convert');
130
142
  const targetIdentity = improveSha256(Buffer.from(`${inputSha}:${args.record.conversionModel}:${args.options.responsiveQuality}`)).slice(0, 32);
131
143
  const baseKey = `improve-target:v2:${targetIdentity}`;
132
- // How many conversions of this winner the kit has already bought and
133
- // abandoned to a stall, and which of them to wait on now. A resume
134
- // re-attaches to the NEWEST one — it is bought, it is still running, and it
135
- // is the only way to get anything back for it — instead of rebuilding the
136
- // base key and waiting out the whole bound on the first, oldest, already
137
- // declared-dead conversion.
138
- let bought = args.options.fresh ? 0 : improveConvertStallCount(recordBeforeConvert);
139
- let index = Math.max(1, bought);
144
+ // How many conversions of this winner a PRE-F19 kit bought and abandoned to a
145
+ // stall, and which of them to wait on now. A resume re-attaches to the NEWEST
146
+ // one — it is bought, it is still running, and it is the only way to get
147
+ // anything back for it — instead of rebuilding the base key and waiting out
148
+ // the whole bound on the first, oldest conversion. Nothing adds to this count
149
+ // any more; a stall no longer abandons anything.
150
+ const bought = args.options.fresh ? 0 : improveConvertStallCount(recordBeforeConvert);
151
+ const index = Math.max(1, bought);
140
152
  // WHICH CONVERSION THIS INVOCATION IS ABOUT TO WAIT ON. The attempt ledger
141
153
  // decides, because it holds the exact key: a `--fresh` or retry attempt that
142
154
  // was stopped mid-flight is reachable only through the key it was dispatched
@@ -147,13 +159,15 @@ export const runImproveConvertStage = async (args) => {
147
159
  // kits written before the ledger.
148
160
  //
149
161
  // Only an attempt minted for THIS winner counts: every recorded key is the
150
- // base key plus a suffix, so the prefix is what says the conversion behind it
151
- // is of the design this run is converting. A redraw or a re-pick already
152
- // closes its attempts (`abandonImproveConversions`); this is the second lock
153
- // on that door, because re-attaching to a conversion of a discarded design
154
- // would deliver the wrong page and read as a replay.
162
+ // base key itself or the base key plus a suffix, so the prefix is what says
163
+ // the conversion behind it is of the design this run is converting. A redraw
164
+ // or a re-pick already closes its attempts (`abandonImproveConversions`);
165
+ // this is the second lock on that door, because re-attaching to a conversion
166
+ // of a discarded design would deliver the wrong page and read as a replay.
155
167
  const open = args.options.fresh ? undefined : openImproveConversionAttempt(recordBeforeConvert);
156
- const resumed = open?.key.startsWith(`${baseKey}:`) ? open : undefined;
168
+ const resumed = open && (open.key === baseKey || open.key.startsWith(`${baseKey}:`))
169
+ ? open
170
+ : undefined;
157
171
  const nonce = args.freshConversionNonce;
158
172
  if (args.options.fresh && !nonce) {
159
173
  throw new Error('improve --fresh needs a per-invocation conversion nonce, so the conversion it dispatches'
@@ -162,9 +176,9 @@ export const runImproveConvertStage = async (args) => {
162
176
  const key = args.options.fresh && nonce
163
177
  ? improveFreshConversionKey(baseKey, nonce)
164
178
  : resumed?.key ?? (index === 1 ? baseKey : improveConvertRetryKey(baseKey, index));
165
- // The transaction is taken ONCE, outside the retry: a second
166
- // `prepareImproveTargetAttempt` while the first backup exists would delete
167
- // the previous good target instead of preserving it.
179
+ // The transaction is taken ONCE: a second `prepareImproveTargetAttempt`
180
+ // while the first backup exists would delete the previous good target
181
+ // instead of preserving it.
168
182
  const transaction = await prepareImproveTargetAttempt(args.options.paths.targetDir);
169
183
  const warn = args.dependencies.warn ?? ((line) => { console.warn(line); });
170
184
  try {
@@ -174,6 +188,14 @@ export const runImproveConvertStage = async (args) => {
174
188
  // the ordinary base-key path writes nothing extra. The writes are chained
175
189
  // and drained before the stage writes the record itself: a stamp landing
176
190
  // after the settled record would write a record that has no convert block.
191
+ //
192
+ // The id arrives on a callback that cannot be awaited, so the write is the
193
+ // one durable fact of this stage that is NOT on disk before it is needed.
194
+ // Both ends of the stage therefore drain it — the ordinary end below, and
195
+ // the signal path, which is why each link is also handed to
196
+ // `trackImproveDurableWrite`. A SIGTERM used to exit with this write still
197
+ // in flight, leaving a kit that had paid for a conversion, was still being
198
+ // billed for it, and could not name it.
177
199
  let pendingLedgerWrite = Promise.resolve();
178
200
  const rememberConversionId = (attemptKey, id) => {
179
201
  const noted = noteImproveConversionAttemptId(recordBeforeConvert, {
@@ -189,165 +211,171 @@ export const runImproveConvertStage = async (args) => {
189
211
  warn(`[ledger] convert: could not record conversion ${id} against its key:`
190
212
  + ` ${improveErrorText(error)}`);
191
213
  });
214
+ trackImproveDurableWrite(pendingLedgerWrite);
192
215
  };
193
- const attemptConversion = async (attemptKey) => runImproveConversion({
194
- input,
195
- outDir: args.options.paths.targetDir,
196
- output: 'html',
197
- model: args.record.conversionModel,
198
- responsiveQuality: args.options.responsiveQuality,
199
- timeoutMs: args.options.convertStallSeconds * 1_000,
200
- key: attemptKey,
201
- runner: args.dependencies.runConvert ?? runConversionCommand,
202
- journal: args.dependencies.journal,
203
- onConversionId: (id) => { rememberConversionId(attemptKey, id); },
204
- }).catch(async (error) => {
205
- const attempt = error instanceof ImproveConvertAttemptError
206
- ? error.attempt
207
- : { artifacts: [], purchaseIds: [], runIds: [] };
208
- const warning = responsiveFallbackReason(error);
209
- const sourceConversionId = attempt.runIds[0]
210
- ?? improveConversionIdFromText(improveErrorText(error));
211
- const layerDocPresent = (await stat(args.options.paths.targetLayerDoc).catch(() => undefined))?.isFile();
212
- const assetsPresent = (await stat(`${args.options.paths.targetLayerDoc}.assets`).catch(() => undefined))?.isDirectory();
213
- if (!warning || !sourceConversionId || !layerDocPresent || !assetsPresent)
214
- throw error;
215
- (args.dependencies.warn ?? console.warn)(`Responsive HTML was unavailable; deriving fixed-layout HTML free from ${sourceConversionId}`);
216
- // The derivation is free, not unbounded. Passing no timeout dropped it
217
- // through to waitForOperation's twenty-minute default while the docs
218
- // promised `--convert-stall-seconds` bounds the conversion wait, so a
219
- // wedged derivation hung the run for twenty minutes with no STALL.md —
220
- // the pipedrive shape, on the one path the reader was told was bounded.
221
- const fixed = await runImproveConversion({
222
- input: sourceConversionId,
216
+ const bound = args.options.convertStallSeconds;
217
+ // Progress goes where every other 12ui progress stream goes — stderr, via
218
+ // the same channel the fallback line uses — so stdout stays the record.
219
+ const tick = args.dependencies.warn ?? ((line) => { console.warn(line); });
220
+ const attemptConversion = async (attemptKey) => {
221
+ // The wait a lane actually sits through, ticked once a minute so the
222
+ // terminal never goes silent (F8). The client applies `bound` only to a
223
+ // stretch with no newly observed live stage or active lane; a healthy
224
+ // tall conversion remains attached to this exact idempotent purchase.
225
+ const startedAt = Date.now();
226
+ const progress = createImproveConvertProgress({
227
+ label: 'responsive export',
228
+ boundSeconds: bound,
229
+ write: tick,
230
+ });
231
+ return runImproveConversion({
232
+ input,
223
233
  outDir: args.options.paths.targetDir,
224
- output: 'html_fixed',
225
- timeoutMs: args.options.convertStallSeconds * 1_000,
226
- key: `improve-fixed:v1:${sourceConversionId}`,
234
+ output: 'html',
235
+ model: args.record.conversionModel,
236
+ responsiveQuality: args.options.responsiveQuality,
237
+ stallTimeoutMs: args.options.convertStallSeconds * 1_000,
238
+ key: attemptKey,
239
+ passthrough: args.options.passthrough,
227
240
  runner: args.dependencies.runConvert ?? runConversionCommand,
228
241
  journal: args.dependencies.journal,
242
+ onConversionId: (id) => { rememberConversionId(attemptKey, id); },
243
+ progress,
244
+ }).catch(async (error) => {
245
+ const attempt = error instanceof ImproveConvertAttemptError
246
+ ? error.attempt
247
+ : { artifacts: [], purchaseIds: [], runIds: [] };
248
+ // The stage the SERVICE declared decides the sentence, not the shape of
249
+ // the error text (F34).
250
+ const fallbackReason = responsiveFallbackReason(error, {
251
+ ...(progress.serviceStage() ? { serviceStage: progress.serviceStage() } : {}),
252
+ });
253
+ const sourceConversionId = attempt.runIds[0]
254
+ ?? improveConversionIdFromText(improveErrorText(error));
255
+ const layerDocPresent = (await stat(args.options.paths.targetLayerDoc).catch(() => undefined))?.isFile();
256
+ const assetsPresent = (await stat(`${args.options.paths.targetLayerDoc}.assets`).catch(() => undefined))?.isDirectory();
257
+ if (!fallbackReason || !sourceConversionId || !layerDocPresent || !assetsPresent)
258
+ throw error;
259
+ const waitedSeconds = Math.round(progress.waitedSeconds() ?? (Date.now() - startedAt) / 1_000);
260
+ (args.dependencies.warn ?? console.warn)(`${fallbackReason.warning} After ${formatDuration(waitedSeconds)}`
261
+ + ` (bound ${formatDuration(bound)});`
262
+ + ` deriving fixed-layout HTML free from ${sourceConversionId}`);
263
+ // The derivation is free, but it still stops after the same period
264
+ // without a newly observed live service fact. It therefore cannot
265
+ // quietly use the conversion client's generic twenty-minute wall.
266
+ const fixed = await runImproveConversion({
267
+ input: sourceConversionId,
268
+ outDir: args.options.paths.targetDir,
269
+ output: 'html_fixed',
270
+ stallTimeoutMs: args.options.convertStallSeconds * 1_000,
271
+ key: `improve-fixed:v1:${sourceConversionId}`,
272
+ passthrough: args.options.passthrough,
273
+ runner: args.dependencies.runConvert ?? runConversionCommand,
274
+ journal: args.dependencies.journal,
275
+ progress: createImproveConvertProgress({
276
+ label: 'fixed-layout derivation',
277
+ boundSeconds: bound,
278
+ write: tick,
279
+ }),
280
+ });
281
+ const fixedOutput = await fixedImproveHtml(args.options.paths.targetDir);
282
+ args.dependencies.journal?.note({ degradations: ['improve_fixed_layout_fallback'] });
283
+ return {
284
+ artifacts: [...new Set([
285
+ ...attempt.artifacts,
286
+ ...fixed.artifacts,
287
+ args.options.paths.targetLayerDoc,
288
+ `${args.options.paths.targetLayerDoc}.assets`,
289
+ fixedOutput.html,
290
+ fixedOutput.assets,
291
+ ])],
292
+ purchaseIds: [...new Set([...attempt.purchaseIds, ...fixed.purchaseIds])],
293
+ runIds: [...new Set([sourceConversionId, ...attempt.runIds, ...fixed.runIds])],
294
+ fallback: {
295
+ html: fixedOutput.html,
296
+ warning: fallbackReason.warning,
297
+ outcome: fallbackReason.outcome,
298
+ waitedSeconds,
299
+ },
300
+ };
229
301
  });
230
- const fixedOutput = await fixedImproveHtml(args.options.paths.targetDir);
231
- args.dependencies.journal?.note({ degradations: ['improve_fixed_layout_fallback'] });
232
- return {
233
- artifacts: [...new Set([
234
- ...attempt.artifacts,
235
- ...fixed.artifacts,
236
- args.options.paths.targetLayerDoc,
237
- `${args.options.paths.targetLayerDoc}.assets`,
238
- fixedOutput.html,
239
- fixedOutput.assets,
240
- ])],
241
- purchaseIds: [...new Set([...attempt.purchaseIds, ...fixed.purchaseIds])],
242
- runIds: [...new Set([sourceConversionId, ...attempt.runIds, ...fixed.runIds])],
243
- fallback: { html: fixedOutput.html, warning },
244
- };
245
- });
246
- // ONE retry, and only for the stall with nothing to derive: the wait ended,
247
- // no LayerDoc reached disk, so no fixed-layout fallback is possible and the
248
- // stage has nothing at all. The guard is the LayerDoc on disk rather than
249
- // the error text — if the conversion delivered, re-dispatching is pure
250
- // waste of a second paid conversion.
302
+ };
303
+ // ONE DISPATCH PER INVOCATION, ALWAYS (F19, CLAUDE.md item 3).
251
304
  //
252
- // What is actually guaranteed, stated exactly: the default bound is twice
253
- // the model's typical wall (see improveConvertStallDefaultSeconds), and an
254
- // explicit --convert-stall-seconds is refused below one typical wall. So
255
- // the retry sits outside the median by construction and inside no measured
256
- // healthy population — nobody has measured P(convert half > bound | healthy)
257
- // on the fused population, so it is a bound, not a proof.
305
+ // A stall used to buy a second parent conversion of the same winner. The
306
+ // justification was that the bound sits outside the model's typical window,
307
+ // so it could not fire on healthy work — a bound, never a measurement. What
308
+ // it produced on pipedrive was one operator command, two parent conversions,
309
+ // four conversion ids, and an abandoned-conversion list the CLI wrote
310
+ // against itself while the first conversion kept running and kept billing.
311
+ //
312
+ // So there is no retry, no abandonment, and no second key. A stall that left
313
+ // a LayerDoc derives the free fixed-layout fallback from the conversion that
314
+ // is already running (inside `attemptConversion`); a stall that left nothing
315
+ // ends the invocation with the conversion still open in the ledger, so
316
+ // `plan/STALL.md` and `--from convert` both re-attach to it.
258
317
  //
259
- // The budget belongs to the KIT, not to this process. Both the retry's
260
- // identity and its count come from the durable ledgers, so a resume
261
- // attaches to the conversion the retry actually dispatched instead of to
262
- // the first, known-stalled one, and a kit that has already retried refuses
263
- // to buy a third rather than dispatching one per resume forever.
264
- let converted;
265
- let convertedKey;
266
- const retries = bought === 0 && improveConvertStallRetryAllowed(args.record.conversionModel)
267
- ? IMPROVE_CONVERT_STALL_ATTEMPTS - 1
268
- : 0;
269
318
  // Why an attempt is being dispatched, which is what the ledger records it
270
319
  // as. A resume of a recorded attempt re-declares the reason it was opened
271
- // with and dedupes to a no-op; the plain base key is not recorded at all.
272
- const dispatchReason = (attempt) => {
273
- if (attempt > 0)
274
- return 'stall-retry';
275
- if (args.options.fresh)
276
- return 'fresh';
277
- return resumed?.reason ?? (index === 1 ? undefined : 'stall-retry');
278
- };
279
- for (let attempt = 0; attempt <= retries; attempt += 1) {
280
- const attemptKey = attempt === 0 ? key : improveConvertRetryKey(key, index);
281
- // BEFORE THE DISPATCH, because a conversion nothing wrote down before it
282
- // started is a conversion a stop cannot leave resumable. `--fresh` also
283
- // walks away here from whatever attempt this kit still had open: it is
284
- // buying a replacement for it, and an attempt left open would send the
285
- // next resume back to the run this one supersedes.
286
- const reason = dispatchReason(attempt);
287
- if (reason) {
288
- const started = startImproveConversionAttempt(recordBeforeConvert, {
289
- key: attemptKey,
290
- reason,
291
- ...(args.options.fresh ? { supersedes: IMPROVE_FRESH_ABANDON_REASON } : {}),
292
- });
293
- if (started.record !== recordBeforeConvert) {
294
- recordBeforeConvert = noteAbandonedAttempts({
295
- record: started.record,
296
- attempts: started.superseded,
297
- reason: IMPROVE_FRESH_ABANDON_REASON,
298
- warn,
299
- });
300
- await writeImproveRecord(args.options.paths.record, recordBeforeConvert);
301
- }
302
- }
303
- try {
304
- converted = await attemptConversion(attemptKey);
305
- convertedKey = attemptKey;
306
- await pendingLedgerWrite;
307
- break;
308
- }
309
- catch (error) {
310
- await pendingLedgerWrite;
311
- const layerDocPresent = (await stat(args.options.paths.targetLayerDoc)
312
- .catch(() => undefined))?.isFile();
313
- if (layerDocPresent || !improveStalled(error))
314
- throw error;
315
- // The stalled attempt knows its own id even when the record does not:
316
- // nothing settled, so `recordedImproveConversionId` has nowhere to look.
317
- const stalledId = (error instanceof ImproveConvertAttemptError
318
- ? error.attempt.runIds[0]
319
- : undefined) ?? improveConversionIdFromText(improveErrorText(error));
320
- // The attempt ledger closes with the conversion, by key: the run this
321
- // key reaches is dead, and a later resume must not rebuild it.
322
- const abandoned = await abandonImproveConversions({
323
- record: recordBeforeConvert,
324
- reason: improveConvertStallReason(args.options.convertStallSeconds),
325
- ...(stalledId ? { id: stalledId } : {}),
326
- warn,
327
- });
328
- recordBeforeConvert = abandoned.record;
329
- await writeImproveRecord(args.options.paths.record, recordBeforeConvert);
330
- // The ledger is the source of truth, and it cannot record a stall whose
331
- // id nothing reported. Taking the larger of the two keeps the next key
332
- // distinct in that case without ever going backwards.
333
- bought = Math.max(bought + 1, improveConvertStallCount(recordBeforeConvert));
334
- index = bought + 1;
335
- if (attempt >= retries) {
336
- throw improveConvertStallExhausted({
337
- seconds: args.options.convertStallSeconds,
338
- bought,
339
- model: args.record.conversionModel,
340
- cause: error,
341
- });
342
- }
343
- args.dependencies.journal?.note({ degradations: ['improve_convert_stall_retry'] });
344
- warn(`[stall] convert: nothing materialized in ${args.options.convertStallSeconds}s;`
345
- + ' dispatching one fresh conversion of the same winner');
346
- await resetImproveTargetAttempt(args.options.paths.targetDir);
347
- }
320
+ // with and dedupes to a no-op.
321
+ const reason = args.options.fresh
322
+ ? 'fresh'
323
+ : resumed?.reason ?? (index === 1 ? 'primary' : 'stall-retry');
324
+ // BEFORE THE DISPATCH, because a conversion nothing wrote down before it
325
+ // started is a conversion a stop cannot leave resumable — and because a
326
+ // price nobody wrote down is a paid call with no receipt. `--fresh` also
327
+ // walks away here from whatever attempt this kit still had open: it is
328
+ // buying a replacement for it, and an attempt left open would send the
329
+ // next resume back to the run this one supersedes.
330
+ const started = startImproveConversionAttempt(recordBeforeConvert, {
331
+ key,
332
+ reason,
333
+ priceCeilingUsd: args.price,
334
+ ...(args.options.fresh ? { supersedes: IMPROVE_FRESH_ABANDON_REASON } : {}),
335
+ });
336
+ if (started.record !== recordBeforeConvert) {
337
+ recordBeforeConvert = noteAbandonedAttempts({
338
+ record: started.record,
339
+ attempts: started.superseded,
340
+ reason: IMPROVE_FRESH_ABANDON_REASON,
341
+ warn,
342
+ });
343
+ }
344
+ // The stage's own priced entry, written now rather than on settlement: a
345
+ // kit that stalled had no `convert` entry at all, so its recorded ceiling
346
+ // was the draft's and a lane converting a page twice could not say so.
347
+ recordBeforeConvert = noteImproveStageDispatched({
348
+ record: recordBeforeConvert, stage: 'convert', priceCeilingUsd: args.price,
349
+ });
350
+ await writeImproveRecord(args.options.paths.record, recordBeforeConvert);
351
+ let converted;
352
+ try {
353
+ converted = await attemptConversion(key);
354
+ await pendingLedgerWrite;
348
355
  }
349
- if (!converted)
350
- throw new Error('Improve conversion ended without a result');
356
+ catch (error) {
357
+ await pendingLedgerWrite;
358
+ if (!improveStalled(error))
359
+ throw error;
360
+ // The stalled attempt knows its own id even when the record does not:
361
+ // nothing settled, so `recordedImproveConversionId` has nowhere to look.
362
+ // It stays OPEN in the ledger — it is running, it is paid for, and the
363
+ // resume this error prints is the only way to get anything back for it.
364
+ const stalledId = (error instanceof ImproveConvertAttemptError
365
+ ? error.attempt.runIds[0]
366
+ : undefined) ?? improveConversionIdFromText(improveErrorText(error));
367
+ warn(`[stall] convert: nothing settled in ${args.options.convertStallSeconds}s;`
368
+ + `${stalledId ? ` conversion ${stalledId}` : ' the conversion'} is still running,`
369
+ + ' and improve is not buying another');
370
+ throw improveConvertStallHalted({
371
+ seconds: args.options.convertStallSeconds,
372
+ ...(stalledId ? { conversionId: stalledId } : {}),
373
+ input: args.record.input.value,
374
+ runDir: args.options.paths.runDir,
375
+ cause: error,
376
+ });
377
+ }
378
+ const convertedKey = key;
351
379
  const html = converted.fallback ? converted.fallback.html : args.options.paths.targetHtml;
352
380
  for (const expected of [args.options.paths.targetLayerDoc, html]) {
353
381
  if (!(await stat(expected).catch(() => undefined))?.isFile()) {
@@ -361,11 +389,28 @@ export const runImproveConvertStage = async (args) => {
361
389
  html,
362
390
  layout: converted.fallback ? 'fixed' : 'responsive',
363
391
  ...(converted.runIds[0] ? { sourceConversionId: converted.runIds[0] } : {}),
364
- ...(converted.fallback ? { responsiveWarning: converted.fallback.warning } : {}),
392
+ ...(converted.fallback
393
+ ? {
394
+ responsiveWarning: converted.fallback.warning,
395
+ responsiveOutcome: converted.fallback.outcome,
396
+ }
397
+ : {}),
398
+ // What the responsive half did before the derivation replaced it, kept
399
+ // durably so `plan/STALL.md`, the README and the run summary all read
400
+ // one account of the same wait rather than three (F8).
401
+ ...(converted.fallback && converted.runIds[0]
402
+ ? {
403
+ responsiveStall: {
404
+ conversionId: converted.runIds[0],
405
+ waitedSeconds: converted.fallback.waitedSeconds,
406
+ boundSeconds: bound,
407
+ },
408
+ }
409
+ : {}),
365
410
  artifacts: converted.artifacts,
366
411
  purchaseIds: converted.purchaseIds,
367
412
  },
368
- }, { ...(convertedKey === undefined ? {} : { key: convertedKey }) });
413
+ }, { key: convertedKey });
369
414
  record = await noteImproveStage({
370
415
  record, stage: 'convert', priceCeilingUsd: args.price, replayed: false, write: false,
371
416
  });
@@ -378,4 +423,167 @@ export const runImproveConvertStage = async (args) => {
378
423
  throw error;
379
424
  }
380
425
  };
426
+ const fileExists = async (file) => ((await stat(file).catch(() => undefined))?.isFile() ?? false);
427
+ const directoryExists = async (directory) => ((await stat(directory).catch(() => undefined))?.isDirectory() ?? false);
428
+ const mergeConvertAttempts = (...attempts) => ({
429
+ artifacts: [...new Set(attempts.flatMap((attempt) => attempt.artifacts))],
430
+ purchaseIds: [...new Set(attempts.flatMap((attempt) => attempt.purchaseIds))],
431
+ runIds: [...new Set(attempts.flatMap((attempt) => attempt.runIds))],
432
+ });
433
+ const convertImproveTarget = async (args) => {
434
+ const transaction = await prepareImproveTargetAttempt(args.outDir);
435
+ try {
436
+ let attempt;
437
+ let responsiveWarning;
438
+ let responsiveOutcome;
439
+ try {
440
+ attempt = await runImproveConversion({
441
+ input: args.input,
442
+ outDir: args.outDir,
443
+ output: 'html',
444
+ model: args.model,
445
+ responsiveQuality: args.responsiveQuality,
446
+ stallTimeoutMs: args.stallTimeoutMs,
447
+ key: args.key,
448
+ passthrough: args.passthrough,
449
+ runner: args.runner,
450
+ journal: args.journal,
451
+ });
452
+ }
453
+ catch (error) {
454
+ const layerDocPresent = await fileExists(args.targetLayerDoc);
455
+ const fallback = responsiveFallbackReason(error);
456
+ if (!fallback || !layerDocPresent)
457
+ throw error;
458
+ responsiveWarning = fallback.warning;
459
+ responsiveOutcome = fallback.outcome;
460
+ attempt = error instanceof ImproveConvertAttemptError
461
+ ? error.attempt
462
+ : { artifacts: [], purchaseIds: [], runIds: [] };
463
+ const conversionId = attempt.runIds[0]
464
+ ?? improveConversionIdFromText(improveErrorText(error));
465
+ if (conversionId) {
466
+ attempt = mergeConvertAttempts(attempt, {
467
+ artifacts: [], purchaseIds: [], runIds: [conversionId],
468
+ });
469
+ }
470
+ }
471
+ if (!(await fileExists(args.targetLayerDoc))) {
472
+ throw new Error(`Improve conversion completed without ${args.targetLayerDoc}`);
473
+ }
474
+ const responsiveHtmlPresent = await fileExists(args.targetHtml);
475
+ if (!responsiveHtmlPresent && !responsiveWarning) {
476
+ responsiveWarning = 'Responsive HTML was not generated; the LayerDoc remains available for planning.';
477
+ }
478
+ let html = responsiveHtmlPresent ? args.targetHtml : '';
479
+ let layout = responsiveHtmlPresent ? 'responsive' : 'document';
480
+ const sourceConversionId = attempt.runIds[0];
481
+ if (!responsiveHtmlPresent && sourceConversionId) {
482
+ (args.warn ?? console.warn)(`Responsive HTML was unavailable; deriving fixed-layout HTML free from ${sourceConversionId}`);
483
+ try {
484
+ const fixedAttempt = await runImproveConversion({
485
+ input: sourceConversionId,
486
+ outDir: args.outDir,
487
+ output: 'html_fixed',
488
+ stallTimeoutMs: args.stallTimeoutMs,
489
+ key: `improve-fixed:v1:${sourceConversionId}`,
490
+ passthrough: args.passthrough,
491
+ runner: args.runner,
492
+ journal: args.journal,
493
+ });
494
+ attempt = mergeConvertAttempts(attempt, fixedAttempt);
495
+ const fixed = await fixedImproveHtml(args.outDir);
496
+ attempt = mergeConvertAttempts(attempt, {
497
+ artifacts: [args.targetLayerDoc, fixed.html, fixed.assets],
498
+ purchaseIds: [],
499
+ runIds: [],
500
+ });
501
+ html = fixed.html;
502
+ layout = 'fixed';
503
+ args.journal?.note({ degradations: ['improve_fixed_layout_fallback'] });
504
+ }
505
+ catch (error) {
506
+ if (error instanceof ImproveConvertAttemptError) {
507
+ attempt = mergeConvertAttempts(attempt, error.attempt);
508
+ }
509
+ (args.warn ?? console.warn)(`Fixed-layout derivation was unavailable; retaining the LayerDoc only: ${improveErrorText(error)}`);
510
+ }
511
+ }
512
+ if (!responsiveHtmlPresent) {
513
+ const layerDocAssets = `${args.targetLayerDoc}.assets`;
514
+ attempt = mergeConvertAttempts(attempt, {
515
+ artifacts: [
516
+ args.targetLayerDoc,
517
+ ...((await directoryExists(layerDocAssets)) ? [layerDocAssets] : []),
518
+ ],
519
+ purchaseIds: [],
520
+ runIds: [],
521
+ });
522
+ args.journal?.note({ degradations: ['improve_responsive_html_unavailable'] });
523
+ }
524
+ const converted = {
525
+ layerDoc: args.targetLayerDoc,
526
+ html,
527
+ layout,
528
+ ...(sourceConversionId ? { sourceConversionId } : {}),
529
+ ...(responsiveWarning ? { responsiveWarning } : {}),
530
+ ...(responsiveOutcome ? { responsiveOutcome } : {}),
531
+ artifacts: attempt.artifacts,
532
+ purchaseIds: attempt.purchaseIds,
533
+ };
534
+ await transaction.commit();
535
+ return converted;
536
+ }
537
+ catch (error) {
538
+ await transaction.restore();
539
+ throw error;
540
+ }
541
+ };
542
+ export const runImproveSiteConvertStage = async (args) => {
543
+ const complete = !args.options.fresh
544
+ && Boolean(args.record.convert)
545
+ && args.record.pages.length > 0
546
+ && args.record.pages.every((page) => page.branch?.status === 'failed' || page.convert);
547
+ if (complete)
548
+ return noteImproveStage({
549
+ record: args.record, stage: 'convert', priceCeilingUsd: args.price, replayed: true, write: true,
550
+ });
551
+ let record = args.record.convert && !args.options.fresh
552
+ ? args.record
553
+ : await runImproveConvertStage(args);
554
+ const limiter = createConcurrencyLimiter(args.options.pageConcurrency);
555
+ const convertedPages = await Promise.all(record.pages.map((page) => limiter(async () => {
556
+ if (page.branch?.status === 'failed')
557
+ return page;
558
+ if (page.convert)
559
+ return page;
560
+ if (page.branch?.status !== 'succeeded' || !page.branch.sha256 || !page.branch.imagePath) {
561
+ throw new Error(`Cannot convert site page ${page.id} before branch succeeds`);
562
+ }
563
+ const paths = improvePagePaths(record.runDir, page.id);
564
+ const targetIdentity = improveSha256(Buffer.from(`${page.branch.sha256}:${record.conversionModel}:${args.options.responsiveQuality}`)).slice(0, 32);
565
+ const baseKey = `improve-page-target:v2:${targetIdentity}`;
566
+ const key = args.options.fresh
567
+ ? `${baseKey}:fresh:${args.freshConversionNonce}`
568
+ : baseKey;
569
+ const converted = await convertImproveTarget({
570
+ input: page.branch.imagePath,
571
+ outDir: paths.targetDir,
572
+ targetLayerDoc: paths.targetLayerDoc,
573
+ targetHtml: paths.targetHtml,
574
+ model: record.conversionModel,
575
+ responsiveQuality: args.options.responsiveQuality,
576
+ key,
577
+ stallTimeoutMs: args.options.convertStallSeconds * 1_000,
578
+ passthrough: args.options.passthrough,
579
+ runner: args.dependencies.runConvert ?? runConversionCommand,
580
+ journal: args.dependencies.journal,
581
+ warn: args.dependencies.warn,
582
+ });
583
+ return { ...page, convert: converted };
584
+ })));
585
+ record = { ...record, pages: convertedPages };
586
+ await writeImproveRecord(args.options.paths.record, record);
587
+ return record;
588
+ };
381
589
  //# sourceMappingURL=improve-conversion-stage.js.map