@lesliechan721/aw 0.1.0-beta.4 → 0.1.0-beta.41

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 (571) hide show
  1. package/dist/authoring/assets/aw-config.mjs +100 -501
  2. package/dist/authoring/assets/aw-config.mjs.map +1 -1
  3. package/dist/authoring/assets/aw-runtime-config.d.mts +13 -0
  4. package/dist/authoring/assets/aw-runtime-config.mjs +199 -0
  5. package/dist/authoring/assets/aw-runtime-config.mjs.map +1 -0
  6. package/dist/authoring/scripts/add-skill.mjs +4 -4
  7. package/dist/authoring/scripts/add-skill.mjs.map +1 -1
  8. package/dist/authoring/scripts/init-plugin.mjs +67 -97
  9. package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
  10. package/dist/authoring/scripts/lib/plugin-version-check.d.mts +15 -0
  11. package/dist/authoring/scripts/lib/plugin-version-check.mjs +239 -232
  12. package/dist/authoring/scripts/lib/plugin-version-check.mjs.map +1 -1
  13. package/dist/authoring/scripts/lib/skill-scaffold.d.mts +77 -90
  14. package/dist/authoring/scripts/lib/skill-scaffold.mjs +99 -120
  15. package/dist/authoring/scripts/lib/skill-scaffold.mjs.map +1 -1
  16. package/dist/authoring/scripts/plugin-status.mjs +8 -11
  17. package/dist/authoring/scripts/plugin-status.mjs.map +1 -1
  18. package/dist/authoring/scripts/remove-plugin.mjs +367 -0
  19. package/dist/authoring/scripts/remove-plugin.mjs.map +1 -0
  20. package/dist/authoring/scripts/validate-plugin.mjs +353 -1175
  21. package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
  22. package/dist/scripts/aw-skill-eval-materializer.d.ts +26 -0
  23. package/dist/scripts/aw-skill-eval-materializer.js +306 -0
  24. package/dist/scripts/aw-skill-eval-materializer.js.map +1 -0
  25. package/dist/scripts/bundle-plugins.d.ts +1 -2
  26. package/dist/scripts/bundle-plugins.js +24 -7
  27. package/dist/scripts/bundle-plugins.js.map +1 -1
  28. package/dist/scripts/plugin-staging.d.ts +7 -24
  29. package/dist/scripts/plugin-staging.js +22 -142
  30. package/dist/scripts/plugin-staging.js.map +1 -1
  31. package/dist/scripts/test-plugin-scripts.d.ts +2 -0
  32. package/dist/scripts/test-plugin-scripts.js +30 -75
  33. package/dist/scripts/test-plugin-scripts.js.map +1 -1
  34. package/dist/src/adapters/helpers.js +2 -2
  35. package/dist/src/adapters/helpers.js.map +1 -1
  36. package/dist/src/authoring/workspace-commands.d.ts +26 -2
  37. package/dist/src/authoring/workspace-commands.js +44 -19
  38. package/dist/src/authoring/workspace-commands.js.map +1 -1
  39. package/dist/src/commands/aw-capabilities.d.ts +78 -0
  40. package/dist/src/commands/aw-capabilities.js +263 -0
  41. package/dist/src/commands/aw-capabilities.js.map +1 -0
  42. package/dist/src/commands/catalog-dev-source.d.ts +154 -0
  43. package/dist/src/commands/catalog-dev-source.js +655 -0
  44. package/dist/src/commands/catalog-dev-source.js.map +1 -0
  45. package/dist/src/commands/catalog-generation.d.ts +21 -0
  46. package/dist/src/commands/catalog-generation.js +9 -0
  47. package/dist/src/commands/catalog-generation.js.map +1 -0
  48. package/dist/src/commands/catalog-publication-inspection.d.ts +138 -0
  49. package/dist/src/commands/catalog-publication-inspection.js +757 -0
  50. package/dist/src/commands/catalog-publication-inspection.js.map +1 -0
  51. package/dist/src/commands/catalog-publication-journal.d.ts +68 -0
  52. package/dist/src/commands/catalog-publication-journal.js +292 -0
  53. package/dist/src/commands/catalog-publication-journal.js.map +1 -0
  54. package/dist/src/commands/catalog-publication-target.d.ts +18 -0
  55. package/dist/src/commands/catalog-publication-target.js +95 -0
  56. package/dist/src/commands/catalog-publication-target.js.map +1 -0
  57. package/dist/src/commands/catalog-publish.d.ts +77 -7
  58. package/dist/src/commands/catalog-publish.js +746 -316
  59. package/dist/src/commands/catalog-publish.js.map +1 -1
  60. package/dist/src/commands/catalog-source.d.ts +60 -22
  61. package/dist/src/commands/catalog-source.js +311 -91
  62. package/dist/src/commands/catalog-source.js.map +1 -1
  63. package/dist/src/commands/catalog-status.d.ts +56 -0
  64. package/dist/src/commands/catalog-status.js +217 -0
  65. package/dist/src/commands/catalog-status.js.map +1 -0
  66. package/dist/src/commands/catalog-store.d.ts +104 -0
  67. package/dist/src/commands/catalog-store.js +685 -0
  68. package/dist/src/commands/catalog-store.js.map +1 -0
  69. package/dist/src/commands/catalog-workspace-resolution.d.ts +13 -0
  70. package/dist/src/commands/catalog-workspace-resolution.js +42 -0
  71. package/dist/src/commands/catalog-workspace-resolution.js.map +1 -0
  72. package/dist/src/commands/console.js +28 -17
  73. package/dist/src/commands/console.js.map +1 -1
  74. package/dist/src/commands/dependency-operation-plan.d.ts +52 -15
  75. package/dist/src/commands/dependency-operation-plan.js +289 -7
  76. package/dist/src/commands/dependency-operation-plan.js.map +1 -1
  77. package/dist/src/commands/init.d.ts +5 -11
  78. package/dist/src/commands/init.js +30 -51
  79. package/dist/src/commands/init.js.map +1 -1
  80. package/dist/src/commands/offline-cleanup-evidence.d.ts +67 -0
  81. package/dist/src/commands/offline-cleanup-evidence.js +181 -0
  82. package/dist/src/commands/offline-cleanup-evidence.js.map +1 -0
  83. package/dist/src/commands/operation-plan.d.ts +146 -0
  84. package/dist/src/commands/operation-plan.js +71 -0
  85. package/dist/src/commands/operation-plan.js.map +1 -0
  86. package/dist/src/commands/operation-planner.d.ts +46 -0
  87. package/dist/src/commands/operation-planner.js +141 -0
  88. package/dist/src/commands/operation-planner.js.map +1 -0
  89. package/dist/src/commands/options.d.ts +9 -7
  90. package/dist/src/commands/options.js +83 -21
  91. package/dist/src/commands/options.js.map +1 -1
  92. package/dist/src/commands/plugin-capabilities.d.ts +22 -0
  93. package/dist/src/commands/plugin-capabilities.js +163 -0
  94. package/dist/src/commands/plugin-capabilities.js.map +1 -0
  95. package/dist/src/commands/rebuild-command.d.ts +78 -30
  96. package/dist/src/commands/rebuild-command.js +4877 -713
  97. package/dist/src/commands/rebuild-command.js.map +1 -1
  98. package/dist/src/commands/rebuild-integration.d.ts +132 -21
  99. package/dist/src/commands/rebuild-integration.js +2853 -1327
  100. package/dist/src/commands/rebuild-integration.js.map +1 -1
  101. package/dist/src/commands/rebuild-operations.d.ts +58 -30
  102. package/dist/src/commands/rebuild-operations.js +260 -319
  103. package/dist/src/commands/rebuild-operations.js.map +1 -1
  104. package/dist/src/commands/reconcile-operation-plan.d.ts +28 -0
  105. package/dist/src/commands/reconcile-operation-plan.js +47 -0
  106. package/dist/src/commands/reconcile-operation-plan.js.map +1 -0
  107. package/dist/src/commands/review-inspection.d.ts +228 -0
  108. package/dist/src/commands/review-inspection.js +1341 -0
  109. package/dist/src/commands/review-inspection.js.map +1 -0
  110. package/dist/src/commands/review-preparation.d.ts +49 -0
  111. package/dist/src/commands/review-preparation.js +427 -0
  112. package/dist/src/commands/review-preparation.js.map +1 -0
  113. package/dist/src/commands/runtime.d.ts +1 -5
  114. package/dist/src/commands/runtime.js +24 -50
  115. package/dist/src/commands/runtime.js.map +1 -1
  116. package/dist/src/commands/skill-eval.d.ts +39 -0
  117. package/dist/src/commands/skill-eval.js +400 -0
  118. package/dist/src/commands/skill-eval.js.map +1 -0
  119. package/dist/src/commands/status-v6.d.ts +279 -0
  120. package/dist/src/commands/status-v6.js +2787 -0
  121. package/dist/src/commands/status-v6.js.map +1 -0
  122. package/dist/src/commands/sync-command.d.ts +40 -0
  123. package/dist/src/commands/sync-command.js +250 -0
  124. package/dist/src/commands/sync-command.js.map +1 -0
  125. package/dist/src/commands/wizard.d.ts +8 -5
  126. package/dist/src/commands/wizard.js +6 -4
  127. package/dist/src/commands/wizard.js.map +1 -1
  128. package/dist/src/commands/write-commands.d.ts +9 -3
  129. package/dist/src/commands/write-commands.js +127 -31
  130. package/dist/src/commands/write-commands.js.map +1 -1
  131. package/dist/src/constants.d.ts +7 -1
  132. package/dist/src/constants.js +7 -1
  133. package/dist/src/constants.js.map +1 -1
  134. package/dist/src/eval/manifest-v1.d.ts +71 -0
  135. package/dist/src/eval/manifest-v1.js +370 -0
  136. package/dist/src/eval/manifest-v1.js.map +1 -0
  137. package/dist/src/generators/local-plugin.d.ts +5 -1
  138. package/dist/src/generators/local-plugin.js +228 -104
  139. package/dist/src/generators/local-plugin.js.map +1 -1
  140. package/dist/src/index.d.ts +10 -4
  141. package/dist/src/index.js +1835 -469
  142. package/dist/src/index.js.map +1 -1
  143. package/dist/src/output/command-receipt.d.ts +43 -46
  144. package/dist/src/output/command-receipt.js +256 -80
  145. package/dist/src/output/command-receipt.js.map +1 -1
  146. package/dist/src/output/model.d.ts +3 -44
  147. package/dist/src/output/model.js +1 -144
  148. package/dist/src/output/model.js.map +1 -1
  149. package/dist/src/output/rebuild-progress.js +1 -13
  150. package/dist/src/output/rebuild-progress.js.map +1 -1
  151. package/dist/src/portable/commands.d.ts +46 -7
  152. package/dist/src/portable/commands.js +349 -37
  153. package/dist/src/portable/commands.js.map +1 -1
  154. package/dist/src/portable/materializer.d.ts +17 -4
  155. package/dist/src/portable/materializer.js +179 -41
  156. package/dist/src/portable/materializer.js.map +1 -1
  157. package/dist/src/portable/skills-cli.d.ts +15 -7
  158. package/dist/src/portable/skills-cli.js +66 -19
  159. package/dist/src/portable/skills-cli.js.map +1 -1
  160. package/dist/src/review/eval-source-input.d.ts +43 -0
  161. package/dist/src/review/eval-source-input.js +207 -0
  162. package/dist/src/review/eval-source-input.js.map +1 -0
  163. package/dist/src/review/review-profile.d.ts +17 -0
  164. package/dist/src/review/review-profile.js +234 -0
  165. package/dist/src/review/review-profile.js.map +1 -0
  166. package/dist/src/review/review-selection.d.ts +30 -0
  167. package/dist/src/review/review-selection.js +527 -0
  168. package/dist/src/review/review-selection.js.map +1 -0
  169. package/dist/src/review/review-types.d.ts +68 -0
  170. package/dist/src/review/review-types.js +16 -0
  171. package/dist/src/review/review-types.js.map +1 -0
  172. package/dist/src/review/skill-materialization.d.ts +13 -0
  173. package/dist/src/review/skill-materialization.js +75 -0
  174. package/dist/src/review/skill-materialization.js.map +1 -0
  175. package/dist/src/review/source-binding.d.ts +183 -0
  176. package/dist/src/review/source-binding.js +708 -0
  177. package/dist/src/review/source-binding.js.map +1 -0
  178. package/dist/src/tui/catalog-freshness.d.ts +1 -0
  179. package/dist/src/tui/catalog-freshness.js +2 -0
  180. package/dist/src/tui/catalog-freshness.js.map +1 -0
  181. package/dist/src/tui/catalog-generation.d.ts +21 -0
  182. package/dist/src/tui/catalog-generation.js +156 -0
  183. package/dist/src/tui/catalog-generation.js.map +1 -0
  184. package/dist/src/tui/catalog-sources/projection.d.ts +4 -0
  185. package/dist/src/tui/catalog-sources/projection.js +17 -0
  186. package/dist/src/tui/catalog-sources/projection.js.map +1 -0
  187. package/dist/src/tui/catalog-sources/review.d.ts +3 -0
  188. package/dist/src/tui/catalog-sources/review.js +13 -0
  189. package/dist/src/tui/catalog-sources/review.js.map +1 -0
  190. package/dist/src/tui/catalog-sources/screens.d.ts +12 -0
  191. package/dist/src/tui/catalog-sources/screens.js +40 -0
  192. package/dist/src/tui/catalog-sources/screens.js.map +1 -0
  193. package/dist/src/tui/catalog-sources/session.d.ts +32 -0
  194. package/dist/src/tui/catalog-sources/session.js +300 -0
  195. package/dist/src/tui/catalog-sources/session.js.map +1 -0
  196. package/dist/src/tui/catalog-sources/types.d.ts +54 -0
  197. package/dist/src/tui/catalog-sources/types.js +2 -0
  198. package/dist/src/tui/catalog-sources/types.js.map +1 -0
  199. package/dist/src/tui/catalog-store-task.d.ts +16 -0
  200. package/dist/src/tui/catalog-store-task.js +19 -0
  201. package/dist/src/tui/catalog-store-task.js.map +1 -0
  202. package/dist/src/tui/clipboard.d.ts +13 -0
  203. package/dist/src/tui/clipboard.js +95 -0
  204. package/dist/src/tui/clipboard.js.map +1 -0
  205. package/dist/src/tui/components.d.ts +177 -0
  206. package/dist/src/tui/components.js +297 -7
  207. package/dist/src/tui/components.js.map +1 -1
  208. package/dist/src/tui/config-array-draft.d.ts +29 -0
  209. package/dist/src/tui/config-array-draft.js +48 -0
  210. package/dist/src/tui/config-array-draft.js.map +1 -0
  211. package/dist/src/tui/config-leaf-editor.d.ts +16 -0
  212. package/dist/src/tui/config-leaf-editor.js +206 -0
  213. package/dist/src/tui/config-leaf-editor.js.map +1 -0
  214. package/dist/src/tui/config-value-presentation.d.ts +20 -0
  215. package/dist/src/tui/config-value-presentation.js +104 -0
  216. package/dist/src/tui/config-value-presentation.js.map +1 -0
  217. package/dist/src/tui/console-app-v4.d.ts +14 -4
  218. package/dist/src/tui/console-app-v4.js +9659 -1558
  219. package/dist/src/tui/console-app-v4.js.map +1 -1
  220. package/dist/src/tui/content-item-card.d.ts +13 -0
  221. package/dist/src/tui/content-item-card.js +51 -0
  222. package/dist/src/tui/content-item-card.js.map +1 -0
  223. package/dist/src/tui/controller-runtime.d.ts +13 -1
  224. package/dist/src/tui/controller-runtime.js +3323 -349
  225. package/dist/src/tui/controller-runtime.js.map +1 -1
  226. package/dist/src/tui/controller.d.ts +643 -40
  227. package/dist/src/tui/controller.js +3756 -705
  228. package/dist/src/tui/controller.js.map +1 -1
  229. package/dist/src/tui/dependency-graph-view.d.ts +39 -0
  230. package/dist/src/tui/dependency-graph-view.js +121 -0
  231. package/dist/src/tui/dependency-graph-view.js.map +1 -0
  232. package/dist/src/tui/dependency-graph.d.ts +81 -0
  233. package/dist/src/tui/dependency-graph.js +452 -0
  234. package/dist/src/tui/dependency-graph.js.map +1 -0
  235. package/dist/src/tui/diagnostic-projection.d.ts +23 -0
  236. package/dist/src/tui/diagnostic-projection.js +567 -0
  237. package/dist/src/tui/diagnostic-projection.js.map +1 -0
  238. package/dist/src/tui/diagnostics.d.ts +31 -0
  239. package/dist/src/tui/diagnostics.js +83 -0
  240. package/dist/src/tui/diagnostics.js.map +1 -0
  241. package/dist/src/tui/entity-cards.d.ts +55 -0
  242. package/dist/src/tui/entity-cards.js +220 -0
  243. package/dist/src/tui/entity-cards.js.map +1 -0
  244. package/dist/src/tui/glossary.d.ts +23 -0
  245. package/dist/src/tui/glossary.js +42 -0
  246. package/dist/src/tui/glossary.js.map +1 -0
  247. package/dist/src/tui/index.d.ts +11 -4
  248. package/dist/src/tui/index.js +8 -2
  249. package/dist/src/tui/index.js.map +1 -1
  250. package/dist/src/tui/input-display.d.ts +9 -0
  251. package/dist/src/tui/input-display.js +58 -0
  252. package/dist/src/tui/input-display.js.map +1 -0
  253. package/dist/src/tui/keys.d.ts +44 -0
  254. package/dist/src/tui/keys.js +43 -15
  255. package/dist/src/tui/keys.js.map +1 -1
  256. package/dist/src/tui/lifecycle-action-view.d.ts +6 -0
  257. package/dist/src/tui/lifecycle-action-view.js +36 -0
  258. package/dist/src/tui/lifecycle-action-view.js.map +1 -0
  259. package/dist/src/tui/model.d.ts +248 -27
  260. package/dist/src/tui/model.js +1662 -314
  261. package/dist/src/tui/model.js.map +1 -1
  262. package/dist/src/tui/operation-diagnostic-screens.d.ts +8 -0
  263. package/dist/src/tui/operation-diagnostic-screens.js +71 -0
  264. package/dist/src/tui/operation-diagnostic-screens.js.map +1 -0
  265. package/dist/src/tui/operation-history.d.ts +81 -0
  266. package/dist/src/tui/operation-history.js +136 -0
  267. package/dist/src/tui/operation-history.js.map +1 -0
  268. package/dist/src/tui/operation-review-planner.d.ts +21 -0
  269. package/dist/src/tui/operation-review-planner.js +1295 -0
  270. package/dist/src/tui/operation-review-planner.js.map +1 -0
  271. package/dist/src/tui/plugin-content.d.ts +31 -0
  272. package/dist/src/tui/plugin-content.js +680 -0
  273. package/dist/src/tui/plugin-content.js.map +1 -0
  274. package/dist/src/tui/plugin-detail.d.ts +52 -0
  275. package/dist/src/tui/plugin-detail.js +165 -0
  276. package/dist/src/tui/plugin-detail.js.map +1 -0
  277. package/dist/src/tui/plugin-write-task.d.ts +69 -0
  278. package/dist/src/tui/plugin-write-task.js +286 -0
  279. package/dist/src/tui/plugin-write-task.js.map +1 -0
  280. package/dist/src/tui/project-inventory.d.ts +68 -0
  281. package/dist/src/tui/project-inventory.js +203 -0
  282. package/dist/src/tui/project-inventory.js.map +1 -0
  283. package/dist/src/tui/prompt.js +4 -15
  284. package/dist/src/tui/prompt.js.map +1 -1
  285. package/dist/src/tui/query-header.d.ts +30 -0
  286. package/dist/src/tui/query-header.js +40 -0
  287. package/dist/src/tui/query-header.js.map +1 -0
  288. package/dist/src/tui/reader.d.ts +37 -0
  289. package/dist/src/tui/reader.js +47 -0
  290. package/dist/src/tui/reader.js.map +1 -0
  291. package/dist/src/tui/router.d.ts +207 -14
  292. package/dist/src/tui/router.js +352 -29
  293. package/dist/src/tui/router.js.map +1 -1
  294. package/dist/src/tui/screen-registry.d.ts +701 -0
  295. package/dist/src/tui/screen-registry.js +230 -0
  296. package/dist/src/tui/screen-registry.js.map +1 -0
  297. package/dist/src/tui/session-console-app.d.ts +6 -0
  298. package/dist/src/tui/session-console-app.js +13 -0
  299. package/dist/src/tui/session-console-app.js.map +1 -0
  300. package/dist/src/tui/session-host.d.ts +45 -0
  301. package/dist/src/tui/session-host.js +209 -0
  302. package/dist/src/tui/session-host.js.map +1 -0
  303. package/dist/src/tui/source-detail-card.d.ts +29 -0
  304. package/dist/src/tui/source-detail-card.js +45 -0
  305. package/dist/src/tui/source-detail-card.js.map +1 -0
  306. package/dist/src/tui/source-ref-presets.d.ts +3 -0
  307. package/dist/src/tui/source-ref-presets.js +11 -0
  308. package/dist/src/tui/source-ref-presets.js.map +1 -0
  309. package/dist/src/tui/theme.d.ts +30 -10
  310. package/dist/src/tui/theme.js +30 -10
  311. package/dist/src/tui/theme.js.map +1 -1
  312. package/dist/src/tui/viewport.d.ts +21 -0
  313. package/dist/src/tui/viewport.js +52 -0
  314. package/dist/src/tui/viewport.js.map +1 -0
  315. package/dist/src/tui/views.js +31 -3
  316. package/dist/src/tui/views.js.map +1 -1
  317. package/dist/src/tui/wizard.js +37 -13
  318. package/dist/src/tui/wizard.js.map +1 -1
  319. package/dist/src/types.d.ts +244 -20
  320. package/dist/src/types.js +1 -0
  321. package/dist/src/types.js.map +1 -1
  322. package/dist/src/utils/agent-version.d.ts +7 -1
  323. package/dist/src/utils/agent-version.js +41 -8
  324. package/dist/src/utils/agent-version.js.map +1 -1
  325. package/dist/src/utils/artifact-plan.d.ts +5 -4
  326. package/dist/src/utils/artifact-plan.js +18 -7
  327. package/dist/src/utils/artifact-plan.js.map +1 -1
  328. package/dist/src/utils/artifact-renderer.d.ts +17 -7
  329. package/dist/src/utils/artifact-renderer.js +214 -216
  330. package/dist/src/utils/artifact-renderer.js.map +1 -1
  331. package/dist/src/utils/artifact-request.d.ts +21 -0
  332. package/dist/src/utils/artifact-request.js +78 -0
  333. package/dist/src/utils/artifact-request.js.map +1 -0
  334. package/dist/src/utils/aw-home-mutation-lock.d.ts +1 -0
  335. package/dist/src/utils/aw-home-mutation-lock.js +32 -4
  336. package/dist/src/utils/aw-home-mutation-lock.js.map +1 -1
  337. package/dist/src/utils/bundle-integrity.d.ts +0 -1
  338. package/dist/src/utils/bundle-integrity.js +0 -25
  339. package/dist/src/utils/bundle-integrity.js.map +1 -1
  340. package/dist/src/utils/bundle-layout.js +22 -29
  341. package/dist/src/utils/bundle-layout.js.map +1 -1
  342. package/dist/src/utils/catalog-capability-projection.d.ts +8 -0
  343. package/dist/src/utils/catalog-capability-projection.js +14 -0
  344. package/dist/src/utils/catalog-capability-projection.js.map +1 -0
  345. package/dist/src/utils/catalog-digests.d.ts +10 -0
  346. package/dist/src/utils/catalog-digests.js +50 -2
  347. package/dist/src/utils/catalog-digests.js.map +1 -1
  348. package/dist/src/utils/catalog-generation-control-snapshot.d.ts +11 -0
  349. package/dist/src/utils/catalog-generation-control-snapshot.js +45 -0
  350. package/dist/src/utils/catalog-generation-control-snapshot.js.map +1 -0
  351. package/dist/src/utils/catalog-generation-error.d.ts +16 -0
  352. package/dist/src/utils/catalog-generation-error.js +30 -0
  353. package/dist/src/utils/catalog-generation-error.js.map +1 -0
  354. package/dist/src/utils/catalog-generation-resolver.d.ts +44 -0
  355. package/dist/src/utils/catalog-generation-resolver.js +273 -0
  356. package/dist/src/utils/catalog-generation-resolver.js.map +1 -0
  357. package/dist/src/utils/catalog-generation-service.d.ts +172 -0
  358. package/dist/src/utils/catalog-generation-service.js +1271 -0
  359. package/dist/src/utils/catalog-generation-service.js.map +1 -0
  360. package/dist/src/utils/catalog-generation-state.d.ts +22 -0
  361. package/dist/src/utils/catalog-generation-state.js +192 -0
  362. package/dist/src/utils/catalog-generation-state.js.map +1 -0
  363. package/dist/src/utils/catalog-generation-store.d.ts +58 -0
  364. package/dist/src/utils/catalog-generation-store.js +452 -0
  365. package/dist/src/utils/catalog-generation-store.js.map +1 -0
  366. package/dist/src/utils/catalog-manifest-v7.d.ts +5 -0
  367. package/dist/src/utils/{catalog-manifest-v4.js → catalog-manifest-v7.js} +35 -43
  368. package/dist/src/utils/catalog-manifest-v7.js.map +1 -0
  369. package/dist/src/utils/catalog-operation-context.d.ts +20 -0
  370. package/dist/src/utils/catalog-operation-context.js +142 -0
  371. package/dist/src/utils/catalog-operation-context.js.map +1 -0
  372. package/dist/src/utils/catalog-public-error.d.ts +7 -3
  373. package/dist/src/utils/catalog-public-error.js +28 -8
  374. package/dist/src/utils/catalog-public-error.js.map +1 -1
  375. package/dist/src/utils/catalog-runtime-projection.d.ts +4 -7
  376. package/dist/src/utils/catalog-runtime-projection.js +7 -102
  377. package/dist/src/utils/catalog-runtime-projection.js.map +1 -1
  378. package/dist/src/utils/catalog-snapshot.d.ts +5 -3
  379. package/dist/src/utils/catalog-snapshot.js +11 -3
  380. package/dist/src/utils/catalog-snapshot.js.map +1 -1
  381. package/dist/src/utils/catalog-source-identity.d.ts +1 -0
  382. package/dist/src/utils/catalog-source-identity.js +21 -2
  383. package/dist/src/utils/catalog-source-identity.js.map +1 -1
  384. package/dist/src/utils/catalog-source-impact.d.ts +21 -0
  385. package/dist/src/utils/catalog-source-impact.js +344 -0
  386. package/dist/src/utils/catalog-source-impact.js.map +1 -0
  387. package/dist/src/utils/catalog-source-references.d.ts +3 -2
  388. package/dist/src/utils/catalog-source-references.js +195 -347
  389. package/dist/src/utils/catalog-source-references.js.map +1 -1
  390. package/dist/src/utils/catalog-sources.d.ts +15 -1
  391. package/dist/src/utils/catalog-sources.js +206 -27
  392. package/dist/src/utils/catalog-sources.js.map +1 -1
  393. package/dist/src/utils/codex-config.d.ts +2 -0
  394. package/dist/src/utils/codex-config.js +26 -5
  395. package/dist/src/utils/codex-config.js.map +1 -1
  396. package/dist/src/utils/codex-manager.d.ts +79 -0
  397. package/dist/src/utils/codex-manager.js +745 -0
  398. package/dist/src/utils/codex-manager.js.map +1 -0
  399. package/dist/src/utils/codex-marketplace-path.d.ts +5 -0
  400. package/dist/src/utils/codex-marketplace-path.js +45 -0
  401. package/dist/src/utils/codex-marketplace-path.js.map +1 -0
  402. package/dist/src/utils/codex-native-observation.d.ts +49 -0
  403. package/dist/src/utils/codex-native-observation.js +154 -0
  404. package/dist/src/utils/codex-native-observation.js.map +1 -0
  405. package/dist/src/utils/codex-native-render-receipt.d.ts +40 -0
  406. package/dist/src/utils/codex-native-render-receipt.js +205 -0
  407. package/dist/src/utils/codex-native-render-receipt.js.map +1 -0
  408. package/dist/src/utils/codex-reconciler.d.ts +126 -0
  409. package/dist/src/utils/codex-reconciler.js +298 -0
  410. package/dist/src/utils/codex-reconciler.js.map +1 -0
  411. package/dist/src/utils/codex-shared-native.d.ts +43 -0
  412. package/dist/src/utils/codex-shared-native.js +81 -0
  413. package/dist/src/utils/codex-shared-native.js.map +1 -0
  414. package/dist/src/utils/codex-skill-staging.d.ts +2 -0
  415. package/dist/src/utils/codex-skill-staging.js.map +1 -1
  416. package/dist/src/utils/codex-surface-analysis.d.ts +46 -0
  417. package/dist/src/utils/codex-surface-analysis.js +247 -0
  418. package/dist/src/utils/codex-surface-analysis.js.map +1 -0
  419. package/dist/src/utils/dynamic-skill-tree.d.ts +4 -0
  420. package/dist/src/utils/dynamic-skill-tree.js +36 -6
  421. package/dist/src/utils/dynamic-skill-tree.js.map +1 -1
  422. package/dist/src/utils/git-catalog-provider.d.ts +16 -0
  423. package/dist/src/utils/git-catalog-provider.js +169 -144
  424. package/dist/src/utils/git-catalog-provider.js.map +1 -1
  425. package/dist/src/utils/local-marketplace.d.ts +17 -1
  426. package/dist/src/utils/local-marketplace.js +301 -84
  427. package/dist/src/utils/local-marketplace.js.map +1 -1
  428. package/dist/src/utils/manifest.d.ts +1 -4
  429. package/dist/src/utils/manifest.js +1 -4
  430. package/dist/src/utils/manifest.js.map +1 -1
  431. package/dist/src/utils/multi-source-catalog.d.ts +3 -9
  432. package/dist/src/utils/multi-source-catalog.js +54 -110
  433. package/dist/src/utils/multi-source-catalog.js.map +1 -1
  434. package/dist/src/utils/native-cli.d.ts +55 -7
  435. package/dist/src/utils/native-cli.js +386 -57
  436. package/dist/src/utils/native-cli.js.map +1 -1
  437. package/dist/src/utils/orphan-marketplace-cleanup.js +0 -4
  438. package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
  439. package/dist/src/utils/ownership.d.ts +84 -20
  440. package/dist/src/utils/ownership.js +179 -222
  441. package/dist/src/utils/ownership.js.map +1 -1
  442. package/dist/src/utils/path-catalog-provider.d.ts +1 -1
  443. package/dist/src/utils/path-catalog-provider.js +54 -65
  444. package/dist/src/utils/path-catalog-provider.js.map +1 -1
  445. package/dist/src/utils/paths.d.ts +0 -1
  446. package/dist/src/utils/paths.js +0 -1
  447. package/dist/src/utils/paths.js.map +1 -1
  448. package/dist/src/utils/plugin-config-impact.d.ts +33 -0
  449. package/dist/src/utils/plugin-config-impact.js +298 -0
  450. package/dist/src/utils/plugin-config-impact.js.map +1 -0
  451. package/dist/src/utils/plugin-config-write.d.ts +52 -27
  452. package/dist/src/utils/plugin-config-write.js +1000 -296
  453. package/dist/src/utils/plugin-config-write.js.map +1 -1
  454. package/dist/src/utils/plugin-config.d.ts +153 -93
  455. package/dist/src/utils/plugin-config.js +1163 -1017
  456. package/dist/src/utils/plugin-config.js.map +1 -1
  457. package/dist/src/utils/plugin-intent-state.d.ts +49 -0
  458. package/dist/src/utils/plugin-intent-state.js +320 -0
  459. package/dist/src/utils/plugin-intent-state.js.map +1 -0
  460. package/dist/src/utils/plugin-scripts.d.ts +65 -125
  461. package/dist/src/utils/plugin-scripts.js +482 -524
  462. package/dist/src/utils/plugin-scripts.js.map +1 -1
  463. package/dist/src/utils/process-tree.d.ts +2 -2
  464. package/dist/src/utils/process-tree.js +1 -1
  465. package/dist/src/utils/process-tree.js.map +1 -1
  466. package/dist/src/utils/project-boundary.d.ts +11 -13
  467. package/dist/src/utils/project-boundary.js +28 -34
  468. package/dist/src/utils/project-boundary.js.map +1 -1
  469. package/dist/src/utils/runtime-config.d.ts +20 -0
  470. package/dist/src/utils/runtime-config.js +75 -0
  471. package/dist/src/utils/runtime-config.js.map +1 -0
  472. package/dist/src/utils/safe-fs.d.ts +21 -0
  473. package/dist/src/utils/safe-fs.js +111 -0
  474. package/dist/src/utils/safe-fs.js.map +1 -0
  475. package/dist/src/utils/safe-operation-diagnostic.d.ts +15 -0
  476. package/dist/src/utils/safe-operation-diagnostic.js +33 -0
  477. package/dist/src/utils/safe-operation-diagnostic.js.map +1 -0
  478. package/dist/src/utils/sensitive-content.d.ts +4 -0
  479. package/dist/src/utils/sensitive-content.js +36 -0
  480. package/dist/src/utils/sensitive-content.js.map +1 -0
  481. package/dist/src/utils/skill-validation.d.ts +1 -1
  482. package/dist/src/utils/skill-validation.js +1 -1
  483. package/dist/src/utils/skill-validation.js.map +1 -1
  484. package/dist/src/utils/state-paths.d.ts +1 -0
  485. package/dist/src/utils/state-paths.js +12 -2
  486. package/dist/src/utils/state-paths.js.map +1 -1
  487. package/dist/src/utils/target-eligibility.d.ts +8 -2
  488. package/dist/src/utils/target-eligibility.js +17 -8
  489. package/dist/src/utils/target-eligibility.js.map +1 -1
  490. package/dist/src/utils/windows-claude-shim.d.ts +9 -0
  491. package/dist/src/utils/windows-claude-shim.js +141 -0
  492. package/dist/src/utils/windows-claude-shim.js.map +1 -0
  493. package/dist/vitest.config.js +91 -10
  494. package/dist/vitest.config.js.map +1 -1
  495. package/package.json +22 -19
  496. package/dist/authoring/scripts/check-plugin-versions.mjs +0 -5
  497. package/dist/authoring/scripts/check-plugin-versions.mjs.map +0 -1
  498. package/dist/scripts/aw-skill-eval-engine.d.ts +0 -13
  499. package/dist/scripts/aw-skill-eval-engine.js +0 -31
  500. package/dist/scripts/aw-skill-eval-engine.js.map +0 -1
  501. package/dist/scripts/codex-eval-app-server.d.ts +0 -89
  502. package/dist/scripts/codex-eval-app-server.js +0 -1228
  503. package/dist/scripts/codex-eval-app-server.js.map +0 -1
  504. package/dist/scripts/codex-eval-isolation.d.ts +0 -61
  505. package/dist/scripts/codex-eval-isolation.js +0 -318
  506. package/dist/scripts/codex-eval-isolation.js.map +0 -1
  507. package/dist/scripts/codex-eval-process-management.d.ts +0 -8
  508. package/dist/scripts/codex-eval-process-management.js +0 -69
  509. package/dist/scripts/codex-eval-process-management.js.map +0 -1
  510. package/dist/scripts/codex-eval-process-tree.d.ts +0 -38
  511. package/dist/scripts/codex-eval-process-tree.js +0 -803
  512. package/dist/scripts/codex-eval-process-tree.js.map +0 -1
  513. package/dist/scripts/codex-eval-runtime-config.d.ts +0 -62
  514. package/dist/scripts/codex-eval-runtime-config.js +0 -843
  515. package/dist/scripts/codex-eval-runtime-config.js.map +0 -1
  516. package/dist/scripts/codex-trigger-eval.d.ts +0 -84
  517. package/dist/scripts/codex-trigger-eval.js +0 -968
  518. package/dist/scripts/codex-trigger-eval.js.map +0 -1
  519. package/dist/scripts/eval-plugin-skills-audited.d.ts +0 -6
  520. package/dist/scripts/eval-plugin-skills-audited.js +0 -261
  521. package/dist/scripts/eval-plugin-skills-audited.js.map +0 -1
  522. package/dist/scripts/eval-plugin-skills.d.ts +0 -45
  523. package/dist/scripts/eval-plugin-skills.js +0 -1586
  524. package/dist/scripts/eval-plugin-skills.js.map +0 -1
  525. package/dist/scripts/eval-run-layout.d.ts +0 -17
  526. package/dist/scripts/eval-run-layout.js +0 -26
  527. package/dist/scripts/eval-run-layout.js.map +0 -1
  528. package/dist/scripts/plugin-eval-contract.d.ts +0 -185
  529. package/dist/scripts/plugin-eval-contract.js +0 -695
  530. package/dist/scripts/plugin-eval-contract.js.map +0 -1
  531. package/dist/scripts/plugin-eval-materializer.d.ts +0 -13
  532. package/dist/scripts/plugin-eval-materializer.js +0 -421
  533. package/dist/scripts/plugin-eval-materializer.js.map +0 -1
  534. package/dist/scripts/skill-reporting.d.ts +0 -212
  535. package/dist/scripts/skill-reporting.js +0 -922
  536. package/dist/scripts/skill-reporting.js.map +0 -1
  537. package/dist/src/commands/status-v4.d.ts +0 -102
  538. package/dist/src/commands/status-v4.js +0 -844
  539. package/dist/src/commands/status-v4.js.map +0 -1
  540. package/dist/src/commands/status.d.ts +0 -93
  541. package/dist/src/commands/status.js +0 -442
  542. package/dist/src/commands/status.js.map +0 -1
  543. package/dist/src/utils/active-marketplace-runtime-lock.d.ts +0 -12
  544. package/dist/src/utils/active-marketplace-runtime-lock.js +0 -133
  545. package/dist/src/utils/active-marketplace-runtime-lock.js.map +0 -1
  546. package/dist/src/utils/catalog-manifest-v3.d.ts +0 -2
  547. package/dist/src/utils/catalog-manifest-v3.js +0 -3
  548. package/dist/src/utils/catalog-manifest-v3.js.map +0 -1
  549. package/dist/src/utils/catalog-manifest-v4.d.ts +0 -5
  550. package/dist/src/utils/catalog-manifest-v4.js.map +0 -1
  551. package/dist/src/utils/catalog-source-cache.d.ts +0 -61
  552. package/dist/src/utils/catalog-source-cache.js +0 -276
  553. package/dist/src/utils/catalog-source-cache.js.map +0 -1
  554. package/dist/src/utils/codex-project-surface.d.ts +0 -3
  555. package/dist/src/utils/codex-project-surface.js +0 -49
  556. package/dist/src/utils/codex-project-surface.js.map +0 -1
  557. package/dist/src/utils/lifecycle-active-store.d.ts +0 -175
  558. package/dist/src/utils/lifecycle-active-store.js +0 -1276
  559. package/dist/src/utils/lifecycle-active-store.js.map +0 -1
  560. package/dist/src/utils/plugin-authoring-capabilities.d.ts +0 -23
  561. package/dist/src/utils/plugin-authoring-capabilities.js +0 -37
  562. package/dist/src/utils/plugin-authoring-capabilities.js.map +0 -1
  563. package/dist/src/utils/plugin-authoring-capabilities.json +0 -92
  564. package/dist/src/utils/plugin-release.d.ts +0 -2
  565. package/dist/src/utils/plugin-release.js +0 -2
  566. package/dist/src/utils/plugin-release.js.map +0 -1
  567. package/dist/src/utils/skill-frontmatter-capabilities.d.ts +0 -201
  568. package/dist/src/utils/skill-frontmatter-capabilities.js +0 -5
  569. package/dist/src/utils/skill-frontmatter-capabilities.js.map +0 -1
  570. package/dist/src/utils/skill-frontmatter-capabilities.json +0 -200
  571. /package/dist/authoring/scripts/{check-plugin-versions.d.mts → remove-plugin.d.mts} +0 -0
@@ -1,374 +1,804 @@
1
1
  import crypto from 'node:crypto';
2
- import { execFile } from 'node:child_process';
3
2
  import os from 'node:os';
4
3
  import path from 'node:path';
5
- import { promisify } from 'node:util';
6
4
  import fs from 'fs-extra';
7
- import { assertStrictSemVer, preparePublishedWorkspaceCatalog, readPluginWorkspace, validatePublishedCatalogSnapshot, } from '@lesliechan721/aw-plugin-core';
8
- import { bundleLocalPlugin, createCatalogRuntimeImportResolver } from '../../scripts/plugin-staging.js';
9
- import { CLI_RESERVED_IMPORTS } from '../utils/manifest.js';
10
- import { resolveCliPackageRoot } from '../utils/paths.js';
11
- const execFileAsync = promisify(execFile);
12
- const LEGACY_ATTEMPTED_MARKER = path.join('.aw', 'publish', 'attempted.json');
13
- const INHERITED_GIT_AUTH_ENV = new Set([
14
- 'GIT_ASKPASS',
15
- 'GIT_HTTP_USER_AGENT',
16
- 'GIT_SSH',
17
- 'GIT_SSH_COMMAND',
18
- 'GIT_SSH_VARIANT',
19
- 'GIT_SSL_CAINFO',
20
- 'GIT_SSL_NO_VERIFY',
21
- 'GIT_TERMINAL_PROMPT',
22
- ]);
23
- function digest(value) {
24
- return `sha256:${crypto.createHash('sha256').update(value).digest('hex')}`;
5
+ import { GENERATED_OUTPUT_MARKER_FILENAME, validatePublishedCatalogSnapshot, } from '@lesliechan721/aw-plugin-core';
6
+ import { disposeCatalogPublicationInspection, inspectCatalogPublicationApplyContext, inspectCatalogPublicationLiveContext, parseRemoteRefs, prepareCatalogPublicationInspection, publicationGit, publicationGitExit, readCatalogPublicationBranchState, } from './catalog-publication-inspection.js';
7
+ import { catalogPublicationDirectoryPath, catalogPublicationJournalPath, catalogPublicationPlanDigest, catalogPublicationRepositoryName, catalogPublicationRepositoryPath, findCatalogPublicationJournalByPlanDigest, readCatalogPublicationJournal, writeCatalogPublicationJournalAtomic, } from './catalog-publication-journal.js';
8
+ import { resolveCatalogPublicationTarget, } from './catalog-publication-target.js';
9
+ import { resolveCatalogWorkspaceRoot, } from './catalog-workspace-resolution.js';
10
+ export { catalogPublicationPlanDigest, parseCatalogPublicationJournal, } from './catalog-publication-journal.js';
11
+ export { safeRemoteIdentity, sanitizedGitEnvironment } from './catalog-publication-inspection.js';
12
+ export const CATALOG_PUBLICATION_CLEANUP_WARNING = 'Catalog publication succeeded, but local repository cleanup did not complete. Retry apply with the same plan digest.';
13
+ async function assertPublicationStatePathSafe(workspaceRoot) {
14
+ for (const candidate of [
15
+ path.join(workspaceRoot, '.aw'),
16
+ path.join(workspaceRoot, '.aw', 'publish'),
17
+ ]) {
18
+ if (!(await fs.pathExists(candidate)))
19
+ continue;
20
+ const stats = await fs.lstat(candidate);
21
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
22
+ throw new Error('Catalog publication state path must contain only regular local directories.');
23
+ }
24
+ }
25
25
  }
26
- export function sanitizedGitEnvironment(source) {
27
- return Object.fromEntries(Object.entries(source).filter(([key]) => !key.startsWith('GIT_') || INHERITED_GIT_AUTH_ENV.has(key)));
26
+ async function assertPublicationDirectorySafe(directoryPath, catalogVersion) {
27
+ let stats;
28
+ try {
29
+ stats = await fs.lstat(directoryPath);
30
+ }
31
+ catch (error) {
32
+ if (error.code === 'ENOENT')
33
+ return false;
34
+ throw error;
35
+ }
36
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
37
+ throw new Error(`Catalog ${catalogVersion} publication state directory is damaged. Increase the Catalog version.`);
38
+ }
39
+ return true;
28
40
  }
29
- export function safeRemoteIdentity(value) {
30
- if (/^[a-z][a-z\d+.-]*:\/\//iu.test(value)) {
31
- try {
32
- const url = new URL(value);
33
- url.username = '';
34
- url.password = '';
35
- url.search = '';
36
- url.hash = '';
37
- return url.toString();
38
- }
39
- catch {
40
- // Fall through to conservative display sanitization for malformed URLs.
41
+ function sameDescriptor(left, right) {
42
+ const comparisonCommit = '0'.repeat(40);
43
+ return catalogPublicationPlanDigest(left, comparisonCommit)
44
+ === catalogPublicationPlanDigest(right, comparisonCommit);
45
+ }
46
+ async function clearWorktree(repositoryRoot) {
47
+ for (const name of await fs.readdir(repositoryRoot)) {
48
+ if (name !== '.git')
49
+ await fs.remove(path.join(repositoryRoot, name));
50
+ }
51
+ }
52
+ async function assertNoGitAttributes(root, relative = '') {
53
+ for (const entry of await fs.readdir(path.join(root, relative), { withFileTypes: true })) {
54
+ const child = relative ? path.posix.join(relative, entry.name) : entry.name;
55
+ if (entry.name === '.gitattributes') {
56
+ throw new Error(`Catalog publication snapshot must not contain .gitattributes (${child}).`);
41
57
  }
58
+ if (entry.isDirectory())
59
+ await assertNoGitAttributes(root, child);
60
+ }
61
+ }
62
+ async function assertSnapshotBinding(snapshotRoot, descriptor, display) {
63
+ const markerPath = path.join(snapshotRoot, GENERATED_OUTPUT_MARKER_FILENAME);
64
+ const [stats, markerStats] = await Promise.all([
65
+ fs.lstat(snapshotRoot),
66
+ fs.lstat(markerPath),
67
+ ]);
68
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
69
+ throw new Error('Prepared Catalog snapshot must be a regular local directory.');
70
+ }
71
+ if (!markerStats.isFile() || markerStats.isSymbolicLink()) {
72
+ throw new Error('Prepared Catalog snapshot marker must be a regular local file.');
42
73
  }
43
- const withoutQuery = value.split(/[?#]/u, 1)[0];
44
- return withoutQuery
45
- .replace(/^([^/@\s:]+):([^/@\s]+)@/u, '')
46
- .replace(/^[^@\s]+@(?=[^:/\s]+[/:])/u, '');
74
+ const [marker, validation] = await Promise.all([
75
+ fs.readJson(markerPath),
76
+ validatePublishedCatalogSnapshot(snapshotRoot),
77
+ ]);
78
+ const release = validation.manifest.release;
79
+ if (marker.workspaceIdentity !== descriptor.workspaceIdentity
80
+ || validation.manifest.catalogVersion !== display.catalogVersion
81
+ || validation.manifest.channel !== display.channel
82
+ || validation.manifest.entries.length !== display.pluginCount
83
+ || validation.snapshotDigest !== descriptor.snapshotDigest
84
+ || release.state !== 'published'
85
+ || release.sourceHead !== descriptor.sourceHead) {
86
+ throw new Error('Prepared Catalog descriptor, snapshot, or plan identity changed.');
87
+ }
88
+ await assertNoGitAttributes(snapshotRoot);
47
89
  }
48
- function attemptPath(workspaceRoot, catalogVersion) {
49
- return path.join(workspaceRoot, '.aw', 'publish', 'attempts', `${catalogVersion}.json`);
90
+ function displayFromPreparation(preparation) {
91
+ return {
92
+ catalogVersion: preparation.prepared.catalogVersion,
93
+ channel: preparation.prepared.channel,
94
+ pluginCount: preparation.prepared.pluginNames.length,
95
+ };
50
96
  }
51
- async function migrateLegacyAttempt(workspaceRoot, catalogVersion) {
52
- const legacyPath = path.join(workspaceRoot, LEGACY_ATTEMPTED_MARKER);
53
- if (!(await fs.pathExists(legacyPath)))
54
- return;
55
- let recordedVersion = catalogVersion;
56
- try {
57
- const legacy = await fs.readJson(legacyPath);
58
- if (legacy.schemaVersion === 1 && typeof legacy.catalogVersion === 'string') {
59
- recordedVersion = assertStrictSemVer(legacy.catalogVersion, 'legacy attempted Catalog version');
60
- }
97
+ function assertLiveContextMatchesDescriptor(context, descriptor) {
98
+ if (context.workspaceIdentity !== descriptor.workspaceIdentity
99
+ || context.sourceHead !== descriptor.sourceHead
100
+ || context.remoteName !== descriptor.remote.name
101
+ || context.remoteIdentityDigest !== descriptor.remote.identityDigest
102
+ || context.branch !== descriptor.branch
103
+ || context.tag !== descriptor.tag) {
104
+ throw new Error('Catalog publication identity changed. Increase the Catalog version and create a new plan.');
61
105
  }
62
- catch {
63
- // Bind an unreadable legacy marker to the current version. A later version uses a new file.
106
+ }
107
+ function assertApplyContextMatchesDescriptor(context, descriptor) {
108
+ if (context.workspaceIdentity !== descriptor.workspaceIdentity
109
+ || context.remoteIdentityDigest !== descriptor.remote.identityDigest
110
+ || context.branch !== descriptor.branch) {
111
+ throw new Error('Catalog publication identity changed. Increase the Catalog version and create a new plan.');
64
112
  }
65
- const destination = attemptPath(workspaceRoot, recordedVersion);
66
- await fs.ensureDir(path.dirname(destination));
67
- if (await fs.pathExists(destination))
68
- return;
69
- await fs.rename(legacyPath, destination);
70
113
  }
71
- async function git(cwd, args, env, label) {
72
- try {
73
- const result = await execFileAsync('git', [...args], {
74
- cwd,
75
- env,
76
- encoding: 'utf8',
77
- maxBuffer: 16 * 1024 * 1024,
78
- });
79
- return result.stdout.trim();
114
+ async function createPublicationCommit(preparation, descriptor, snapshotRoot, display) {
115
+ const { repositoryRoot, parent, tag, env } = preparation;
116
+ await assertSnapshotBinding(snapshotRoot, descriptor, display);
117
+ if (parent) {
118
+ await publicationGit(repositoryRoot, [
119
+ 'checkout', '--quiet', '--detach', 'refs/aw/catalog-parent',
120
+ ], env, 'publicationCommitFailed', 'Could not select the publication parent.');
80
121
  }
81
- catch (error) {
82
- throw new Error(label, { cause: error });
122
+ else {
123
+ await publicationGit(repositoryRoot, [
124
+ 'checkout', '--quiet', '--orphan', 'catalog-publication',
125
+ ], env, 'publicationCommitFailed', 'Could not create the initial Catalog publication.');
83
126
  }
127
+ await clearWorktree(repositoryRoot);
128
+ await fs.copy(snapshotRoot, repositoryRoot, { dereference: false });
129
+ await publicationGit(repositoryRoot, [
130
+ 'add', '--force', '--all',
131
+ ], env, 'publicationCommitFailed', 'Could not stage the Catalog publication tree.');
132
+ await publicationGit(repositoryRoot, [
133
+ '-c', 'user.name=AW Catalog Publisher',
134
+ '-c', 'user.email=catalog-publisher@agent-workflows.invalid',
135
+ 'commit', '--quiet', '-m', `Catalog ${display.catalogVersion}`,
136
+ ], env, 'publicationCommitFailed', 'Could not create the Catalog publication commit.');
137
+ const commit = await publicationGit(repositoryRoot, [
138
+ 'rev-parse', 'HEAD',
139
+ ], env, 'publicationCommitFailed', 'Could not resolve the Catalog publication commit.');
140
+ const parents = (await publicationGit(repositoryRoot, [
141
+ 'show', '-s', '--format=%P', commit,
142
+ ], env, 'publicationCommitFailed', 'Could not verify the Catalog publication parent.'))
143
+ .split(/\s+/u)
144
+ .filter(Boolean);
145
+ if ((parent && (parents.length !== 1 || parents[0] !== parent)) || (!parent && parents.length !== 0)) {
146
+ throw new Error('Catalog publication commit has an invalid parent.');
147
+ }
148
+ const verificationRoot = path.join(preparation.temporaryRoot, 'verification');
149
+ await fs.ensureDir(verificationRoot);
150
+ await publicationGit(repositoryRoot, [
151
+ '--work-tree', verificationRoot, 'checkout', '--quiet', commit, '--', '.',
152
+ ], env, 'publicationCommitFailed', 'Could not verify the Catalog publication commit tree.');
153
+ await assertSnapshotBinding(verificationRoot, descriptor, display);
154
+ await publicationGit(repositoryRoot, [
155
+ '-c', 'user.name=AW Catalog Publisher',
156
+ '-c', 'user.email=catalog-publisher@agent-workflows.invalid',
157
+ 'tag', '--annotate', tag, '--message', `Catalog ${display.catalogVersion}`,
158
+ ], env, 'publicationCommitFailed', 'Could not create the annotated Catalog tag.');
159
+ return commit;
84
160
  }
85
- async function gitExit(cwd, args, env) {
86
- try {
87
- await execFileAsync('git', [...args], { cwd, env, encoding: 'utf8' });
88
- return true;
161
+ async function remoteRefState(cwd, remote, branchRef, tagRef, env) {
162
+ const refs = parseRemoteRefs(await publicationGit(cwd, [
163
+ 'ls-remote', remote, branchRef, tagRef, `${tagRef}^{}`,
164
+ ], env, 'remoteReadFailed', 'Could not inspect the Catalog publication remote.'));
165
+ const tagPresent = refs.has(tagRef) || refs.has(`${tagRef}^{}`);
166
+ return {
167
+ branchCommit: refs.get(branchRef) ?? null,
168
+ tagCommit: refs.get(`${tagRef}^{}`) ?? null,
169
+ tagPresent,
170
+ tagAnnotated: refs.has(tagRef) && refs.has(`${tagRef}^{}`),
171
+ };
172
+ }
173
+ function assertReconciliableRemoteState(state, journal) {
174
+ const branchAtExpected = state.branchCommit === journal.expectedCommit;
175
+ const branchAtParent = state.branchCommit === journal.descriptor.parent;
176
+ const tagAtExpected = state.tagAnnotated && state.tagCommit === journal.expectedCommit;
177
+ const tagAbsent = !state.tagPresent;
178
+ if ((branchAtExpected && tagAtExpected)
179
+ || (branchAtParent && tagAbsent)
180
+ || (branchAtExpected && tagAbsent)
181
+ || (branchAtParent && tagAtExpected))
182
+ return;
183
+ throw new Error(`Catalog ${journal.display.catalogVersion} remote refs conflict with the prepared plan. Increase the Catalog version.`);
184
+ }
185
+ const PERSISTED_REPOSITORY_CONFIG = new Map([
186
+ ['core.repositoryformatversion', new Set(['0'])],
187
+ ['core.filemode', new Set(['true', 'false'])],
188
+ ['core.bare', new Set(['false'])],
189
+ ['core.logallrefupdates', new Set(['true'])],
190
+ ['core.ignorecase', new Set(['true'])],
191
+ ['core.precomposeunicode', new Set(['true'])],
192
+ ['core.hookspath', new Set([os.devNull])],
193
+ ['core.symlinks', new Set(['true'])],
194
+ ]);
195
+ const REQUIRED_PERSISTED_REPOSITORY_CONFIG = [
196
+ 'core.repositoryformatversion',
197
+ 'core.filemode',
198
+ 'core.bare',
199
+ 'core.logallrefupdates',
200
+ 'core.hookspath',
201
+ 'core.symlinks',
202
+ ];
203
+ async function assertRegularGitDirectory(root) {
204
+ const stats = await fs.lstat(root);
205
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
206
+ throw new Error('Pending Catalog publication Git directory is unsafe.');
89
207
  }
90
- catch {
91
- return false;
208
+ }
209
+ async function assertRegularGitFile(filePath) {
210
+ const stats = await fs.lstat(filePath);
211
+ if (!stats.isFile() || stats.isSymbolicLink()) {
212
+ throw new Error('Pending Catalog publication Git control file is unsafe.');
92
213
  }
93
214
  }
94
- function parseRemoteRefs(output) {
95
- return new Map(output.split('\n').filter(Boolean).map((line) => {
96
- const [objectId, ref] = line.split(/\s+/u);
97
- return [ref, objectId];
98
- }));
215
+ async function assertGitTreeContainsOnlyLocalFiles(root) {
216
+ for (const entry of await fs.readdir(root, { withFileTypes: true })) {
217
+ const child = path.join(root, entry.name);
218
+ const stats = await fs.lstat(child);
219
+ if (stats.isSymbolicLink()) {
220
+ throw new Error('Pending Catalog publication Git data must not contain symbolic links.');
221
+ }
222
+ if (stats.isDirectory()) {
223
+ await assertGitTreeContainsOnlyLocalFiles(child);
224
+ }
225
+ else if (!stats.isFile()) {
226
+ throw new Error('Pending Catalog publication Git data must contain only regular local files.');
227
+ }
228
+ }
99
229
  }
100
- async function writeJsonAtomic(filePath, value) {
101
- await fs.ensureDir(path.dirname(filePath));
102
- const temporary = path.join(path.dirname(filePath), `.${path.basename(filePath)}.${crypto.randomUUID()}.tmp`);
103
- await fs.writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
230
+ async function assertPathMissing(filePath) {
104
231
  try {
105
- await fs.rename(temporary, filePath);
232
+ await fs.lstat(filePath);
106
233
  }
107
234
  catch (error) {
108
- await fs.remove(temporary);
235
+ if (error.code === 'ENOENT')
236
+ return;
109
237
  throw error;
110
238
  }
239
+ throw new Error('Pending Catalog publication repository must not use alternate object stores.');
111
240
  }
112
- async function clearWorktree(repositoryRoot) {
113
- for (const name of await fs.readdir(repositoryRoot)) {
114
- if (name !== '.git')
115
- await fs.remove(path.join(repositoryRoot, name));
241
+ async function validatePersistentRepositoryControlState(repositoryRoot, env) {
242
+ const gitRoot = path.join(repositoryRoot, '.git');
243
+ const configPath = path.join(gitRoot, 'config');
244
+ await assertRegularGitDirectory(gitRoot);
245
+ await assertRegularGitFile(configPath);
246
+ await assertRegularGitFile(path.join(gitRoot, 'HEAD'));
247
+ await assertRegularGitFile(path.join(gitRoot, 'index'));
248
+ await assertRegularGitDirectory(path.join(gitRoot, 'objects'));
249
+ await assertRegularGitDirectory(path.join(gitRoot, 'refs'));
250
+ await assertPathMissing(path.join(gitRoot, 'objects', 'info', 'alternates'));
251
+ await assertPathMissing(path.join(gitRoot, 'objects', 'info', 'http-alternates'));
252
+ await assertGitTreeContainsOnlyLocalFiles(gitRoot);
253
+ const entries = (await publicationGit(repositoryRoot, [
254
+ 'config', '--file', configPath, '--no-includes', '--null', '--list',
255
+ ], env, 'pendingRepositoryInvalid', 'Pending Catalog publication config is damaged.'))
256
+ .split('\0')
257
+ .filter(Boolean);
258
+ const seen = new Set();
259
+ for (const entry of entries) {
260
+ const separator = entry.indexOf('\n');
261
+ if (separator <= 0)
262
+ throw new Error('Pending Catalog publication config is damaged.');
263
+ const key = entry.slice(0, separator).toLowerCase();
264
+ const value = entry.slice(separator + 1);
265
+ if (seen.has(key) || !PERSISTED_REPOSITORY_CONFIG.get(key)?.has(value)) {
266
+ throw new Error('Pending Catalog publication config contains unsafe local settings.');
267
+ }
268
+ seen.add(key);
269
+ }
270
+ if (REQUIRED_PERSISTED_REPOSITORY_CONFIG.some((key) => !seen.has(key))) {
271
+ throw new Error('Pending Catalog publication config is incomplete.');
116
272
  }
117
273
  }
118
- async function materializeSourceHead(options) {
119
- const archivePath = path.join(options.temporaryRoot, 'source-head.tar');
120
- await fs.ensureDir(options.outputRoot);
121
- await git(options.repoRoot, [
122
- 'archive', '--format=tar', `--output=${archivePath}`, options.sourceHead,
123
- ], options.env, 'Could not archive the committed source HEAD.');
124
- const tarEnv = { ...options.env };
125
- delete tarEnv.TAR_OPTIONS;
274
+ async function validatePersistentRepository(repositoryRoot, journal, env) {
275
+ const version = journal.display.catalogVersion;
276
+ let stats;
126
277
  try {
127
- await execFileAsync('tar', ['-xf', archivePath, '-C', options.outputRoot], {
128
- env: tarEnv,
129
- encoding: 'utf8',
130
- maxBuffer: 16 * 1024 * 1024,
131
- });
278
+ stats = await fs.lstat(repositoryRoot);
132
279
  }
133
280
  catch (error) {
134
- throw new Error('Could not materialize the committed source HEAD.', { cause: error });
281
+ throw new Error(`Catalog ${version} pending publication repository is missing or damaged. Increase the Catalog version.`, { cause: error });
135
282
  }
136
- finally {
137
- await fs.remove(archivePath);
283
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
284
+ throw new Error(`Catalog ${version} pending publication repository is missing or damaged. Increase the Catalog version.`);
138
285
  }
139
- }
140
- async function validatePublishedSourceWorkspace(workspace, env) {
141
- const validator = path.join(resolveCliPackageRoot(), 'dist', 'authoring', 'scripts', 'validate-plugin.mjs');
142
- for (const plugin of workspace.plugins) {
286
+ try {
287
+ await validatePersistentRepositoryControlState(repositoryRoot, env);
288
+ const [head, tagCommit, tagType, remotes, parents] = await Promise.all([
289
+ publicationGit(repositoryRoot, ['rev-parse', '--verify', 'HEAD'], env, 'pendingRepositoryInvalid', 'Pending Catalog publication repository is damaged.'),
290
+ publicationGit(repositoryRoot, ['rev-parse', `${journal.descriptor.tag}^{commit}`], env, 'pendingRepositoryInvalid', 'Pending Catalog publication tag is damaged.'),
291
+ publicationGit(repositoryRoot, ['cat-file', '-t', `refs/tags/${journal.descriptor.tag}`], env, 'pendingRepositoryInvalid', 'Pending Catalog publication tag is damaged.'),
292
+ publicationGit(repositoryRoot, ['remote'], env, 'pendingRepositoryInvalid', 'Pending Catalog publication repository is damaged.'),
293
+ publicationGit(repositoryRoot, ['show', '-s', '--format=%P', journal.expectedCommit], env, 'pendingRepositoryInvalid', 'Pending Catalog publication commit is damaged.'),
294
+ ]);
295
+ const parentList = parents.split(/\s+/u).filter(Boolean);
296
+ if (head !== journal.expectedCommit
297
+ || tagCommit !== journal.expectedCommit
298
+ || tagType !== 'tag'
299
+ || remotes !== ''
300
+ || (journal.descriptor.parent === null
301
+ ? parentList.length !== 0
302
+ : parentList.length !== 1 || parentList[0] !== journal.descriptor.parent))
303
+ throw new Error('Pending Catalog publication repository identity changed.');
304
+ const verificationRoot = path.join(path.dirname(repositoryRoot), `.${path.basename(repositoryRoot)}.${crypto.randomUUID()}.verify`);
143
305
  try {
144
- await execFileAsync(process.execPath, [
145
- validator,
146
- plugin.rootDir,
147
- '--workspace-root', workspace.workspaceRoot,
148
- '--json',
149
- ], {
150
- cwd: workspace.workspaceRoot,
151
- env,
152
- encoding: 'utf8',
153
- maxBuffer: 16 * 1024 * 1024,
154
- });
306
+ await fs.ensureDir(verificationRoot);
307
+ await publicationGit(repositoryRoot, [
308
+ '--work-tree', verificationRoot, 'checkout', '--quiet', journal.expectedCommit, '--', '.',
309
+ ], env, 'pendingRepositoryInvalid', 'Pending Catalog publication commit tree is damaged.');
310
+ await assertSnapshotBinding(verificationRoot, journal.descriptor, journal.display);
155
311
  }
156
- catch (error) {
157
- let details = '';
158
- if (typeof error === 'object' && error !== null && 'stdout' in error && typeof error.stdout === 'string') {
159
- try {
160
- const result = JSON.parse(error.stdout);
161
- details = (result.errors ?? [])
162
- .map((entry) => typeof entry.message === 'string' ? entry.message : '')
163
- .filter(Boolean)
164
- .join('; ');
165
- }
166
- catch {
167
- // Keep the public validator failure bounded to its plugin identity.
168
- }
169
- }
170
- throw new Error(`Plugin ${plugin.manifest.name} failed public source validation before Catalog publication${details ? `: ${details}` : '.'}`);
312
+ finally {
313
+ await fs.remove(verificationRoot);
171
314
  }
172
315
  }
316
+ catch (error) {
317
+ throw new Error(`Catalog ${version} pending publication repository is missing or damaged. Increase the Catalog version.`, { cause: error });
318
+ }
173
319
  }
174
- const publishBuildAdapter = {
175
- async build(options) {
176
- await bundleLocalPlugin(options.plugin, options.outputRoot, {
177
- buildMode: 'staging',
178
- runtimeResolver: createCatalogRuntimeImportResolver(options.plugins),
179
- });
180
- },
181
- };
182
- export async function runCatalogPublishCommand(options) {
183
- if (options.json && !options.yes)
184
- throw new Error('Catalog publish with --json requires --yes.');
185
- if (!options.interactive && !options.yes)
186
- throw new Error('Non-interactive Catalog publish requires --yes.');
187
- const remote = options.remote ?? 'origin';
188
- const branch = options.branch ?? 'catalog';
189
- const env = sanitizedGitEnvironment(options.env);
190
- const workspaceRoot = await fs.realpath(path.resolve(options.workspaceRoot));
191
- const repoRoot = await git(workspaceRoot, ['rev-parse', '--show-toplevel'], env, 'Workspace must be inside a real Git worktree.');
192
- const sourceHead = await git(repoRoot, ['rev-parse', '--verify', 'HEAD'], env, 'Workspace Git HEAD must be committed and not unborn.');
193
- const status = await git(repoRoot, [
194
- 'status', '--porcelain=v1', '--untracked-files=all', '--ignore-submodules=none',
195
- ], env, 'Could not inspect the source worktree.');
196
- if (status !== '')
197
- throw new Error('Catalog publish requires the complete source Git worktree to be clean.');
198
- const temporaryRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'aw-public-catalog-'));
199
- let fetchUrl = '';
200
- let pushUrl = '';
201
- let safeFetchUrl = '';
202
- let safePushUrl = '';
320
+ async function persistPublicationState(preparation, finalStateRoot, journal, hooks) {
321
+ const parent = path.dirname(finalStateRoot);
322
+ await fs.ensureDir(parent);
323
+ const staging = path.join(parent, `.${path.basename(finalStateRoot)}.${crypto.randomUUID()}.tmp`);
324
+ const repositoryPath = path.join(staging, catalogPublicationRepositoryName());
325
+ const journalPath = path.join(staging, 'journal.json');
203
326
  try {
204
- const sourceRoot = path.join(temporaryRoot, 'source');
205
- await materializeSourceHead({ repoRoot, sourceHead, outputRoot: sourceRoot, temporaryRoot, env });
206
- const workspaceRelative = path.relative(repoRoot, workspaceRoot);
207
- if (workspaceRelative === '..' || workspaceRelative.startsWith(`..${path.sep}`) || path.isAbsolute(workspaceRelative)) {
208
- throw new Error('Catalog workspace must stay inside its Git worktree root.');
327
+ await publicationGit(preparation.repositoryRoot, [
328
+ 'remote', 'remove', 'publish',
329
+ ], preparation.env, 'temporaryRepositoryFailed', 'Could not seal the publication repository.');
330
+ await fs.ensureDir(staging);
331
+ await fs.copy(preparation.repositoryRoot, repositoryPath, { dereference: false, errorOnExist: true });
332
+ await writeCatalogPublicationJournalAtomic(journalPath, journal);
333
+ const persisted = await readCatalogPublicationJournal(journalPath, journal.display.catalogVersion);
334
+ if (!persisted || persisted.planDigest !== journal.planDigest) {
335
+ throw new Error(`Catalog ${journal.display.catalogVersion} publication state could not be verified.`);
209
336
  }
210
- const sourceWorkspaceRoot = path.join(sourceRoot, workspaceRelative);
211
- await git(repoRoot, ['check-ref-format', '--branch', branch], env, 'Invalid Catalog publication branch name.');
212
- const workspace = await readPluginWorkspace(sourceWorkspaceRoot, { reservedImports: CLI_RESERVED_IMPORTS });
213
- await validatePublishedSourceWorkspace(workspace, env);
214
- const catalogVersion = workspace.metadata.catalog.version;
215
- const tag = `catalog-v${catalogVersion}`;
216
- await git(repoRoot, ['check-ref-format', `refs/tags/${tag}`], env, 'Invalid Catalog publication tag.');
217
- const markerPath = attemptPath(workspaceRoot, catalogVersion);
218
- if (!(await gitExit(repoRoot, ['check-ignore', '-q', markerPath], env))) {
219
- throw new Error('Catalog publish state under .aw/publish must be ignored by Git. Add .aw/ to .gitignore.');
337
+ await validatePersistentRepository(repositoryPath, persisted, preparation.env);
338
+ await hooks.beforeFinalRename?.({
339
+ temporaryStateRoot: staging,
340
+ finalStateRoot,
341
+ });
342
+ try {
343
+ await fs.rename(staging, finalStateRoot);
344
+ return persisted;
220
345
  }
221
- await migrateLegacyAttempt(workspaceRoot, catalogVersion);
222
- if (await fs.pathExists(markerPath)) {
223
- throw new Error(`Catalog ${catalogVersion} already has an attempted publication record. `
224
- + 'Run aw catalog version <higher> before publishing again.');
346
+ catch (error) {
347
+ if (!(await fs.pathExists(finalStateRoot)))
348
+ throw error;
349
+ if (!(await assertPublicationDirectorySafe(finalStateRoot, journal.display.catalogVersion)))
350
+ throw error;
351
+ const existing = await readCatalogPublicationJournal(path.join(finalStateRoot, 'journal.json'), journal.display.catalogVersion);
352
+ if (!existing) {
353
+ throw new Error(`Catalog ${journal.display.catalogVersion} publication state is incomplete. Increase the Catalog version.`);
354
+ }
355
+ if (existing.planDigest !== journal.planDigest) {
356
+ throw new Error(`Catalog ${journal.display.catalogVersion} already has a different publication plan. Increase the Catalog version.`);
357
+ }
358
+ if (existing.state !== 'published') {
359
+ await validatePersistentRepository(path.join(finalStateRoot, catalogPublicationRepositoryName()), existing, preparation.env);
360
+ }
361
+ return existing;
225
362
  }
226
- fetchUrl = await git(repoRoot, ['remote', 'get-url', remote], env, `Git remote ${JSON.stringify(remote)} is not configured.`);
227
- pushUrl = await git(repoRoot, ['remote', 'get-url', '--push', remote], env, `Git remote ${JSON.stringify(remote)} has no push URL.`);
228
- safeFetchUrl = safeRemoteIdentity(fetchUrl);
229
- safePushUrl = safeRemoteIdentity(pushUrl);
230
- const remoteIdentityDigest = digest(JSON.stringify({ fetchUrl, pushUrl }));
231
- const branchRef = `refs/heads/${branch}`;
232
- const tagRef = `refs/tags/${tag}`;
233
- const repositoryRoot = path.join(temporaryRoot, 'repository');
234
- await fs.ensureDir(repositoryRoot);
235
- await git(repositoryRoot, ['init', '--quiet'], env, 'Could not create the isolated publication repository.');
236
- await git(repositoryRoot, ['config', 'core.hooksPath', path.join(temporaryRoot, 'disabled-hooks')], env, 'Could not disable publication hooks.');
237
- await git(repositoryRoot, ['config', 'core.symlinks', 'true'], env, 'Could not configure the isolated publication repository.');
238
- await git(repositoryRoot, ['remote', 'add', 'publish', pushUrl], env, 'Could not configure the publication remote.');
239
- const initialRefs = parseRemoteRefs(await git(repositoryRoot, [
240
- 'ls-remote', 'publish', branchRef, tagRef, `${tagRef}^{}`,
241
- ], env, 'Could not inspect the Catalog publication remote.'));
242
- if (initialRefs.has(tagRef) || initialRefs.has(`${tagRef}^{}`)) {
243
- throw new Error(`Remote Catalog tag ${tag} already exists. Increase the Catalog version.`);
363
+ }
364
+ finally {
365
+ await fs.remove(staging);
366
+ }
367
+ }
368
+ function receiptBase(context, journal, resolution) {
369
+ const repositoryPath = journal.repository === null
370
+ ? null
371
+ : catalogPublicationRepositoryPath(context.catalogWorkspaceRoot, journal.display.catalogVersion);
372
+ return {
373
+ ok: true,
374
+ workspaceRoot: context.catalogWorkspaceRoot,
375
+ workspaceRootResolvedFrom: resolution.workspaceRootResolvedFrom ?? 'explicit',
376
+ workspaceIdentity: journal.descriptor.workspaceIdentity,
377
+ catalogVersion: journal.display.catalogVersion,
378
+ channel: journal.display.channel,
379
+ remote: context.remote,
380
+ remoteResolvedFrom: resolution.remoteResolvedFrom ?? 'explicit',
381
+ remoteUrl: context.safeFetchUrl,
382
+ fetchUrl: context.safeFetchUrl,
383
+ pushUrl: context.safePushUrl,
384
+ branch: journal.descriptor.branch,
385
+ branchResolvedFrom: resolution.branchResolvedFrom ?? 'explicit',
386
+ parent: journal.descriptor.parent,
387
+ tag: journal.descriptor.tag,
388
+ expectedCommit: journal.expectedCommit,
389
+ sourceHead: journal.descriptor.sourceHead,
390
+ pluginCount: journal.display.pluginCount,
391
+ snapshotDigest: journal.descriptor.snapshotDigest,
392
+ planDigest: journal.planDigest,
393
+ descriptor: journal.descriptor,
394
+ journalPath: catalogPublicationJournalPath(context.catalogWorkspaceRoot, journal.display.catalogVersion),
395
+ repositoryPath,
396
+ };
397
+ }
398
+ async function readExistingPlan(context, resolution) {
399
+ await assertPublicationStatePathSafe(context.catalogWorkspaceRoot);
400
+ const stateRoot = catalogPublicationDirectoryPath(context.catalogWorkspaceRoot, context.catalogVersion);
401
+ const journalPath = catalogPublicationJournalPath(context.catalogWorkspaceRoot, context.catalogVersion);
402
+ const repositoryPath = catalogPublicationRepositoryPath(context.catalogWorkspaceRoot, context.catalogVersion);
403
+ const stateRootExists = await assertPublicationDirectorySafe(stateRoot, context.catalogVersion);
404
+ const journal = await readCatalogPublicationJournal(journalPath, context.catalogVersion);
405
+ if (!journal) {
406
+ if (stateRootExists) {
407
+ throw new Error(`Catalog ${context.catalogVersion} pending publication journal is missing. Increase the Catalog version.`);
244
408
  }
245
- const parent = initialRefs.get(branchRef) ?? null;
246
- let previousSnapshotRoot;
247
- if (parent) {
248
- await git(repositoryRoot, ['fetch', '--quiet', '--no-tags', 'publish', `${branchRef}:refs/remotes/publish/catalog`], env, 'Could not fetch the published Catalog branch.');
249
- previousSnapshotRoot = path.join(temporaryRoot, 'previous');
250
- await fs.ensureDir(previousSnapshotRoot);
251
- await git(repositoryRoot, ['--work-tree', previousSnapshotRoot, 'checkout', '--quiet', 'refs/remotes/publish/catalog', '--', '.'], env, 'Could not read the published Catalog snapshot.');
252
- await validatePublishedCatalogSnapshot(previousSnapshotRoot);
409
+ return null;
410
+ }
411
+ assertLiveContextMatchesDescriptor(context, journal.descriptor);
412
+ if (journal.state !== 'published') {
413
+ await validatePersistentRepository(repositoryPath, journal, context.env);
414
+ }
415
+ const state = await remoteRefState(context.repoRoot, context.pushUrl, context.branchRef, context.tagRef, context.env);
416
+ if (journal.state === 'published'
417
+ && (state.branchCommit !== journal.expectedCommit
418
+ || !state.tagAnnotated
419
+ || state.tagCommit !== journal.expectedCommit)) {
420
+ throw new Error(`Catalog ${journal.display.catalogVersion} published journal conflicts with remote refs. Increase the Catalog version.`);
421
+ }
422
+ assertReconciliableRemoteState(state, journal);
423
+ return {
424
+ command: 'catalog:publish:plan',
425
+ state: journal.state,
426
+ ...receiptBase(context, journal, resolution),
427
+ };
428
+ }
429
+ async function persistNewPlan(options) {
430
+ const { preparation, descriptor, snapshotRoot, resolution } = options;
431
+ await assertPublicationStatePathSafe(preparation.catalogWorkspaceRoot);
432
+ if (!sameDescriptor(preparation.descriptor, descriptor)) {
433
+ throw new Error('Catalog publication descriptor changed during preparation.');
434
+ }
435
+ const display = displayFromPreparation(preparation);
436
+ const stateRoot = catalogPublicationDirectoryPath(preparation.catalogWorkspaceRoot, display.catalogVersion);
437
+ const journalPath = catalogPublicationJournalPath(preparation.catalogWorkspaceRoot, display.catalogVersion);
438
+ if (!(await publicationGitExit(preparation.repoRoot, ['check-ignore', '-q', journalPath], preparation.env))) {
439
+ throw new Error('Catalog publish state under .aw/publish must be ignored by Git. Add .aw/ to .gitignore.');
440
+ }
441
+ if (await fs.pathExists(stateRoot)) {
442
+ throw new Error(`Catalog ${display.catalogVersion} already has publication state. Use its existing plan or increase the Catalog version.`);
443
+ }
444
+ if (!preparation.tagAvailable) {
445
+ throw new Error(`Remote Catalog tag ${descriptor.tag} already exists. Increase the Catalog version.`);
446
+ }
447
+ const expectedCommit = await createPublicationCommit(preparation, descriptor, snapshotRoot, display);
448
+ let context = await inspectCatalogPublicationLiveContext({
449
+ workspaceRoot: preparation.catalogWorkspaceRoot,
450
+ ...(descriptor.remote.name === null ? { remoteUrl: preparation.pushUrl } : { remote: descriptor.remote.name }),
451
+ branch: descriptor.branch,
452
+ env: preparation.env,
453
+ });
454
+ assertLiveContextMatchesDescriptor(context, descriptor);
455
+ const liveRefs = await remoteRefState(preparation.repositoryRoot, 'publish', preparation.branchRef, preparation.tagRef, preparation.env);
456
+ if (liveRefs.branchCommit !== descriptor.parent || liveRefs.tagPresent) {
457
+ throw new Error(`Catalog ${display.catalogVersion} remote changed during plan creation. Increase the Catalog version.`);
458
+ }
459
+ const journal = {
460
+ schemaVersion: 2,
461
+ state: 'prepared',
462
+ planDigest: catalogPublicationPlanDigest(descriptor, expectedCommit),
463
+ descriptor,
464
+ expectedCommit,
465
+ repository: catalogPublicationRepositoryName(),
466
+ display,
467
+ preparedAt: new Date().toISOString(),
468
+ };
469
+ const persisted = await persistPublicationState(preparation, stateRoot, journal, {
470
+ beforeFinalRename: async (paths) => {
471
+ await options.beforeFinalRename?.(paths);
472
+ context = await inspectCatalogPublicationLiveContext({
473
+ workspaceRoot: preparation.catalogWorkspaceRoot,
474
+ ...(descriptor.remote.name === null
475
+ ? { remoteUrl: preparation.pushUrl }
476
+ : { remote: descriptor.remote.name }),
477
+ branch: descriptor.branch,
478
+ env: preparation.env,
479
+ });
480
+ assertLiveContextMatchesDescriptor(context, descriptor);
481
+ const finalRefs = await remoteRefState(context.repoRoot, context.pushUrl, context.branchRef, context.tagRef, context.env);
482
+ if (finalRefs.branchCommit !== descriptor.parent || finalRefs.tagPresent) {
483
+ throw new Error(`Catalog ${display.catalogVersion} remote changed during plan creation. Increase the Catalog version.`);
484
+ }
485
+ },
486
+ });
487
+ return {
488
+ command: 'catalog:publish:plan',
489
+ state: persisted.state,
490
+ ...receiptBase(context, persisted, resolution),
491
+ };
492
+ }
493
+ export async function persistCatalogPublicationPlan(options) {
494
+ return persistNewPlan({
495
+ preparation: options.preparation,
496
+ descriptor: options.descriptor ?? options.preparation.descriptor,
497
+ snapshotRoot: options.snapshotRoot ?? options.preparation.prepared.outputRoot,
498
+ resolution: options,
499
+ beforeFinalRename: options.beforeFinalRename,
500
+ });
501
+ }
502
+ export async function prepareCatalogPublicationPlan(options) {
503
+ const context = await inspectCatalogPublicationLiveContext(options);
504
+ const existing = await readExistingPlan(context, options);
505
+ if (existing)
506
+ return existing;
507
+ const initialState = await remoteRefState(context.repoRoot, context.pushUrl, context.branchRef, context.tagRef, context.env);
508
+ if (initialState.tagPresent) {
509
+ throw new Error(`Remote Catalog tag ${context.tag} already exists. Increase the Catalog version.`);
510
+ }
511
+ if (initialState.branchCommit !== null) {
512
+ const branchState = await readCatalogPublicationBranchState({
513
+ workspaceRoot: context.catalogWorkspaceRoot,
514
+ ...(options.remoteUrl === undefined ? { remote: options.remote } : { remoteUrl: options.remoteUrl }),
515
+ branch: context.branch,
516
+ env: options.env,
517
+ });
518
+ if (branchState?.version === context.catalogVersion) {
519
+ throw new Error(`Remote Catalog branch already contains version ${context.catalogVersion} without its journal. Increase the Catalog version.`);
253
520
  }
254
- const prepared = await preparePublishedWorkspaceCatalog({
255
- workspaceRoot: sourceWorkspaceRoot,
256
- sourceHead,
257
- previousSnapshotRoot,
258
- adapter: publishBuildAdapter,
259
- reservedImports: CLI_RESERVED_IMPORTS,
521
+ }
522
+ const preparation = await prepareCatalogPublicationInspection(options);
523
+ try {
524
+ return await persistNewPlan({
525
+ preparation,
526
+ descriptor: preparation.descriptor,
527
+ snapshotRoot: preparation.prepared.outputRoot,
528
+ resolution: options,
529
+ beforeFinalRename: options.beforeFinalRename,
260
530
  });
261
- const preparedHead = await git(repoRoot, ['rev-parse', '--verify', 'HEAD'], env, 'Could not recheck the source Git HEAD.');
262
- const preparedStatus = await git(repoRoot, [
263
- 'status', '--porcelain=v1', '--untracked-files=all', '--ignore-submodules=none',
264
- ], env, 'Could not recheck the source worktree.');
265
- if (preparedHead !== sourceHead || preparedStatus !== '') {
266
- throw new Error('Source HEAD or worktree changed during Catalog preparation. Commit or clean it before publishing.');
531
+ }
532
+ finally {
533
+ await disposeCatalogPublicationInspection(preparation);
534
+ }
535
+ }
536
+ async function markUncertain(journalPath, journal) {
537
+ const uncertain = {
538
+ schemaVersion: 2,
539
+ state: 'uncertain',
540
+ planDigest: journal.planDigest,
541
+ descriptor: journal.descriptor,
542
+ expectedCommit: journal.expectedCommit,
543
+ repository: journal.repository,
544
+ display: journal.display,
545
+ preparedAt: journal.preparedAt,
546
+ uncertainAt: new Date().toISOString(),
547
+ };
548
+ await writeCatalogPublicationJournalAtomic(journalPath, uncertain);
549
+ return uncertain;
550
+ }
551
+ async function readAuthorizedPublicationPlan(options) {
552
+ await assertPublicationStatePathSafe(options.workspaceRoot);
553
+ const located = await findCatalogPublicationJournalByPlanDigest(options.workspaceRoot, options.expectedPlanDigest);
554
+ const context = await inspectCatalogPublicationApplyContext(options);
555
+ assertApplyContextMatchesDescriptor(context, located.journal.descriptor);
556
+ return {
557
+ context,
558
+ journalPath: located.journalPath,
559
+ repositoryPath: catalogPublicationRepositoryPath(context.catalogWorkspaceRoot, located.catalogVersion),
560
+ tagRef: `refs/tags/${located.journal.descriptor.tag}`,
561
+ journal: located.journal,
562
+ };
563
+ }
564
+ async function cleanupPublishedRepository(repositoryPath, journal, env, removeRepository) {
565
+ try {
566
+ await fs.lstat(repositoryPath);
567
+ }
568
+ catch (error) {
569
+ if (error.code === 'ENOENT')
570
+ return [];
571
+ return [CATALOG_PUBLICATION_CLEANUP_WARNING];
572
+ }
573
+ const pendingJournal = {
574
+ schemaVersion: 2,
575
+ state: 'prepared',
576
+ planDigest: journal.planDigest,
577
+ descriptor: journal.descriptor,
578
+ expectedCommit: journal.expectedCommit,
579
+ repository: catalogPublicationRepositoryName(),
580
+ display: journal.display,
581
+ preparedAt: journal.preparedAt,
582
+ };
583
+ try {
584
+ await validatePersistentRepository(repositoryPath, pendingJournal, env);
585
+ await removeRepository(repositoryPath);
586
+ return [];
587
+ }
588
+ catch {
589
+ return [CATALOG_PUBLICATION_CLEANUP_WARNING];
590
+ }
591
+ }
592
+ async function inspectCatalogPublicationPlanForApply(options) {
593
+ const authorized = await readAuthorizedPublicationPlan(options);
594
+ const { context, journal, repositoryPath, tagRef } = authorized;
595
+ if (journal.state !== 'published') {
596
+ await validatePersistentRepository(repositoryPath, journal, context.env);
597
+ }
598
+ const state = await remoteRefState(journal.state === 'published' ? context.repoRoot : repositoryPath, context.pushUrl, context.branchRef, tagRef, context.env);
599
+ if (journal.state === 'published'
600
+ && (state.branchCommit !== journal.expectedCommit
601
+ || !state.tagAnnotated
602
+ || state.tagCommit !== journal.expectedCommit)) {
603
+ throw new Error(`Catalog ${journal.display.catalogVersion} published journal conflicts with remote refs. Increase the Catalog version.`);
604
+ }
605
+ assertReconciliableRemoteState(state, journal);
606
+ return {
607
+ command: 'catalog:publish:plan',
608
+ state: journal.state,
609
+ ...receiptBase(context, journal, options),
610
+ };
611
+ }
612
+ export async function applyCatalogPublicationPlan(options) {
613
+ if (!/^sha256:[0-9a-f]{64}$/u.test(options.expectedPlanDigest)) {
614
+ throw new Error('Catalog publish apply requires --expected-plan-digest from catalog publish plan.');
615
+ }
616
+ const authorized = await readAuthorizedPublicationPlan(options);
617
+ const { context, journalPath, repositoryPath, tagRef } = authorized;
618
+ let { journal } = authorized;
619
+ if (journal.state === 'published') {
620
+ const state = await remoteRefState(context.repoRoot, context.pushUrl, context.branchRef, tagRef, context.env);
621
+ if (state.branchCommit !== journal.expectedCommit || !state.tagAnnotated || state.tagCommit !== journal.expectedCommit) {
622
+ throw new Error(`Catalog ${journal.display.catalogVersion} published journal conflicts with remote refs. Increase the Catalog version.`);
267
623
  }
268
- if (!options.yes) {
269
- options.io.stderr([
270
- `Source HEAD: ${sourceHead}`,
271
- `Catalog: ${prepared.catalogVersion} (${prepared.channel})`,
272
- `Push remote: ${remote} (${safePushUrl})`,
273
- `Branch: ${branchRef}`,
274
- `Tag: ${tagRef}`,
275
- `Plugins: ${prepared.pluginNames.length}`,
276
- 'One atomic push will publish the branch and annotated tag.',
277
- ].join('\n') + '\n');
278
- if (!options.confirm || !(await options.confirm('Publish this Catalog snapshot?'))) {
279
- options.io.stderr('Catalog publication cancelled.\n');
280
- return null;
624
+ const warnings = await cleanupPublishedRepository(repositoryPath, journal, context.env, options.removeRepository ?? fs.remove);
625
+ return {
626
+ command: 'catalog:publish:apply',
627
+ state: 'published',
628
+ commit: journal.expectedCommit,
629
+ reconciliation: 'already-published',
630
+ warnings,
631
+ ...receiptBase(context, journal, options),
632
+ };
633
+ }
634
+ await validatePersistentRepository(repositoryPath, journal, context.env);
635
+ let state = await remoteRefState(repositoryPath, context.pushUrl, context.branchRef, tagRef, context.env);
636
+ assertReconciliableRemoteState(state, journal);
637
+ let reconciliation;
638
+ const branchAtExpected = state.branchCommit === journal.expectedCommit;
639
+ const tagAtExpected = state.tagAnnotated && state.tagCommit === journal.expectedCommit;
640
+ if (branchAtExpected && tagAtExpected) {
641
+ reconciliation = 'already-remote';
642
+ }
643
+ else {
644
+ await options.beforeRemoteWrite?.();
645
+ const writeContext = await inspectCatalogPublicationApplyContext(options);
646
+ assertApplyContextMatchesDescriptor(writeContext, journal.descriptor);
647
+ await validatePersistentRepository(repositoryPath, journal, writeContext.env);
648
+ state = await remoteRefState(repositoryPath, writeContext.pushUrl, writeContext.branchRef, tagRef, writeContext.env);
649
+ assertReconciliableRemoteState(state, journal);
650
+ try {
651
+ if (state.branchCommit === journal.expectedCommit
652
+ && state.tagAnnotated
653
+ && state.tagCommit === journal.expectedCommit) {
654
+ reconciliation = 'already-remote';
655
+ }
656
+ else if (state.branchCommit === journal.descriptor.parent && !state.tagPresent) {
657
+ reconciliation = 'atomic';
658
+ await publicationGit(repositoryPath, [
659
+ 'push', '--atomic',
660
+ `--force-with-lease=${writeContext.branchRef}:${journal.descriptor.parent ?? ''}`,
661
+ writeContext.pushUrl,
662
+ `${journal.expectedCommit}:${writeContext.branchRef}`,
663
+ `${tagRef}:${tagRef}`,
664
+ ], writeContext.env, 'publicationUncertain', 'Catalog atomic push failed or its result is uncertain.');
665
+ }
666
+ else if (state.branchCommit === journal.expectedCommit && !state.tagPresent) {
667
+ reconciliation = 'tag';
668
+ await publicationGit(repositoryPath, [
669
+ 'push', writeContext.pushUrl, `${tagRef}:${tagRef}`,
670
+ ], writeContext.env, 'publicationUncertain', 'Catalog tag push failed or its result is uncertain.');
671
+ }
672
+ else {
673
+ reconciliation = 'branch';
674
+ await publicationGit(repositoryPath, [
675
+ 'push', `--force-with-lease=${writeContext.branchRef}:${journal.descriptor.parent ?? ''}`,
676
+ writeContext.pushUrl, `${journal.expectedCommit}:${writeContext.branchRef}`,
677
+ ], writeContext.env, 'publicationUncertain', 'Catalog branch push failed or its result is uncertain.');
281
678
  }
282
679
  }
283
- if (parent)
284
- await git(repositoryRoot, ['checkout', '--quiet', '--detach', 'refs/remotes/publish/catalog'], env, 'Could not select the publication parent.');
285
- else
286
- await git(repositoryRoot, ['checkout', '--quiet', '--orphan', 'catalog-publication'], env, 'Could not create the initial Catalog publication.');
287
- await clearWorktree(repositoryRoot);
288
- await fs.copy(prepared.outputRoot, repositoryRoot, { dereference: false });
289
- await git(repositoryRoot, ['add', '--force', '--all'], env, 'Could not stage the Catalog publication tree.');
290
- await git(repositoryRoot, [
291
- '-c', 'user.name=AW Catalog Publisher',
292
- '-c', 'user.email=catalog-publisher@agent-workflows.invalid',
293
- 'commit', '--quiet', '-m', `Catalog ${catalogVersion}`,
294
- ], env, 'Could not create the Catalog publication commit.');
295
- const commit = await git(repositoryRoot, ['rev-parse', 'HEAD'], env, 'Could not resolve the Catalog publication commit.');
296
- const parents = (await git(repositoryRoot, ['show', '-s', '--format=%P', commit], env, 'Could not verify the Catalog publication parent.')).split(/\s+/u).filter(Boolean);
297
- if ((parent && (parents.length !== 1 || parents[0] !== parent)) || (!parent && parents.length !== 0)) {
298
- throw new Error('Catalog publication commit has an invalid parent.');
299
- }
300
- const verificationRoot = path.join(temporaryRoot, 'verification');
301
- await fs.ensureDir(verificationRoot);
302
- await git(repositoryRoot, ['--work-tree', verificationRoot, 'checkout', '--quiet', commit, '--', '.'], env, 'Could not verify the Catalog publication commit tree.');
303
- const committed = await validatePublishedCatalogSnapshot(verificationRoot);
304
- if (committed.snapshotDigest !== prepared.snapshotDigest)
305
- throw new Error('Catalog publication commit tree differs from the prepared snapshot.');
306
- await git(repositoryRoot, [
307
- '-c', 'user.name=AW Catalog Publisher',
308
- '-c', 'user.email=catalog-publisher@agent-workflows.invalid',
309
- 'tag', '--annotate', tag, '--message', `Catalog ${catalogVersion}`,
310
- ], env, 'Could not create the annotated Catalog tag.');
311
- const attemptedAt = new Date().toISOString();
312
- const attempted = {
313
- schemaVersion: 1,
314
- state: 'attempted',
315
- workspaceIdentity: digest(JSON.stringify({ repoRoot, workspaceRelative: path.relative(repoRoot, workspaceRoot) })),
316
- catalogVersion,
317
- sourceHead,
318
- remote: { name: remote, identityDigest: remoteIdentityDigest },
319
- branch,
320
- tag,
321
- preparedSnapshotDigest: prepared.snapshotDigest,
322
- attemptedAt,
323
- };
324
- await writeJsonAtomic(markerPath, attempted);
325
- const liveRefs = parseRemoteRefs(await git(repositoryRoot, [
326
- 'ls-remote', 'publish', branchRef, tagRef, `${tagRef}^{}`,
327
- ], env, 'Could not recheck the Catalog publication remote.'));
328
- if ((liveRefs.get(branchRef) ?? null) !== parent || liveRefs.has(tagRef) || liveRefs.has(`${tagRef}^{}`)) {
329
- throw new Error('Catalog remote changed during preparation. Increase the Catalog version before publishing again.');
680
+ catch (error) {
681
+ journal = await markUncertain(journalPath, journal);
682
+ throw new Error(`Catalog ${journal.display.catalogVersion} publication result is uncertain. Retry apply with the same plan digest.`, { cause: error });
330
683
  }
331
684
  try {
332
- await git(repositoryRoot, [
333
- 'push', '--atomic', 'publish', `${commit}:${branchRef}`, `${tagRef}:${tagRef}`,
334
- ], env, `Catalog atomic push failed or its result is uncertain. Do not retry ${catalogVersion}; increase the Catalog version.`);
685
+ state = await remoteRefState(repositoryPath, writeContext.pushUrl, writeContext.branchRef, tagRef, writeContext.env);
335
686
  }
336
- catch {
337
- throw new Error(`Catalog atomic push failed or its result is uncertain. Do not retry ${catalogVersion}; run aw catalog version <higher>.`);
687
+ catch (error) {
688
+ journal = await markUncertain(journalPath, journal);
689
+ throw new Error(`Catalog ${journal.display.catalogVersion} publication result is uncertain. Retry apply with the same plan digest.`, { cause: error });
338
690
  }
339
- const publishedRefs = parseRemoteRefs(await git(repositoryRoot, [
340
- 'ls-remote', 'publish', branchRef, tagRef, `${tagRef}^{}`,
341
- ], env, `Catalog publication result is uncertain. Do not retry ${catalogVersion}; increase the Catalog version.`));
342
- if (publishedRefs.get(branchRef) !== commit || publishedRefs.get(`${tagRef}^{}`) !== commit) {
343
- throw new Error(`Catalog publication result is uncertain. Do not retry ${catalogVersion}; run aw catalog version <higher>.`);
691
+ if (state.branchCommit !== journal.expectedCommit || !state.tagAnnotated || state.tagCommit !== journal.expectedCommit) {
692
+ journal = await markUncertain(journalPath, journal);
693
+ throw new Error(`Catalog ${journal.display.catalogVersion} publication result is uncertain. Retry apply with the same plan digest.`);
344
694
  }
345
- await writeJsonAtomic(markerPath, { ...attempted, state: 'published', commit, publishedAt: new Date().toISOString() });
346
- return {
347
- command: 'catalog:publish',
348
- ok: true,
349
- catalogVersion,
350
- channel: prepared.channel,
351
- remote,
352
- remoteUrl: safeFetchUrl,
353
- fetchUrl: safeFetchUrl,
354
- pushUrl: safePushUrl,
355
- branch,
356
- tag,
357
- commit,
358
- sourceHead,
359
- pluginCount: prepared.pluginNames.length,
360
- snapshotDigest: prepared.snapshotDigest,
361
- };
362
695
  }
363
- catch (error) {
364
- const message = error instanceof Error ? error.message : String(error);
365
- throw new Error(message
366
- .replaceAll(temporaryRoot, '<temporary Catalog state>')
367
- .replaceAll(fetchUrl, safeFetchUrl)
368
- .replaceAll(pushUrl, safePushUrl));
696
+ const published = {
697
+ schemaVersion: 2,
698
+ state: 'published',
699
+ planDigest: journal.planDigest,
700
+ descriptor: journal.descriptor,
701
+ expectedCommit: journal.expectedCommit,
702
+ repository: null,
703
+ display: journal.display,
704
+ preparedAt: journal.preparedAt,
705
+ publishedAt: new Date().toISOString(),
706
+ };
707
+ await writeCatalogPublicationJournalAtomic(journalPath, published);
708
+ const warnings = await cleanupPublishedRepository(repositoryPath, published, context.env, options.removeRepository ?? fs.remove);
709
+ return {
710
+ command: 'catalog:publish:apply',
711
+ state: 'published',
712
+ commit: published.expectedCommit,
713
+ reconciliation,
714
+ warnings,
715
+ ...receiptBase(context, published, options),
716
+ };
717
+ }
718
+ export async function runCatalogPublishPlanCommand(options) {
719
+ const workspace = await resolveCatalogWorkspaceRoot({
720
+ cwd: options.cwd,
721
+ ...(options.workspaceRoot === undefined ? {} : { explicitRoot: options.workspaceRoot }),
722
+ mode: 'existing',
723
+ });
724
+ const target = await resolveCatalogPublicationTarget({
725
+ workspaceRoot: workspace.workspaceRoot,
726
+ remote: options.remote,
727
+ branch: options.branch,
728
+ env: options.env,
729
+ requireRemote: true,
730
+ });
731
+ return prepareCatalogPublicationPlan({
732
+ workspaceRoot: workspace.workspaceRoot,
733
+ remote: target.remote,
734
+ branch: target.branch,
735
+ env: options.env,
736
+ workspaceRootResolvedFrom: workspace.workspaceRootResolvedFrom,
737
+ remoteResolvedFrom: target.remoteResolvedFrom,
738
+ branchResolvedFrom: target.branchResolvedFrom,
739
+ });
740
+ }
741
+ export async function runCatalogPublishApplyCommand(options) {
742
+ if (options.json && !options.yes)
743
+ throw new Error('Catalog publish apply with --json requires --yes.');
744
+ if (!options.interactive && !options.yes)
745
+ throw new Error('Non-interactive Catalog publish apply requires --yes.');
746
+ if (!/^sha256:[0-9a-f]{64}$/u.test(options.expectedPlanDigest ?? '')) {
747
+ throw new Error('Catalog publish apply requires --expected-plan-digest from catalog publish plan.');
369
748
  }
370
- finally {
371
- await fs.remove(temporaryRoot);
749
+ const workspace = await resolveCatalogWorkspaceRoot({
750
+ cwd: options.cwd,
751
+ ...(options.workspaceRoot === undefined ? {} : { explicitRoot: options.workspaceRoot }),
752
+ mode: 'existing',
753
+ });
754
+ const target = await resolveCatalogPublicationTarget({
755
+ workspaceRoot: workspace.workspaceRoot,
756
+ remote: options.remote,
757
+ branch: options.branch,
758
+ env: options.env,
759
+ requireRemote: true,
760
+ });
761
+ if (!options.yes) {
762
+ const plan = await inspectCatalogPublicationPlanForApply({
763
+ workspaceRoot: workspace.workspaceRoot,
764
+ remote: target.remote,
765
+ branch: target.branch,
766
+ expectedPlanDigest: options.expectedPlanDigest,
767
+ env: options.env,
768
+ workspaceRootResolvedFrom: workspace.workspaceRootResolvedFrom,
769
+ remoteResolvedFrom: target.remoteResolvedFrom,
770
+ branchResolvedFrom: target.branchResolvedFrom,
771
+ });
772
+ options.io.stderr([
773
+ `Workspace identity: ${plan.workspaceIdentity}`,
774
+ `Source HEAD: ${plan.sourceHead}`,
775
+ `Remote: ${plan.remote}`,
776
+ `Fetch URL: ${plan.fetchUrl}`,
777
+ `Push URL: ${plan.pushUrl}`,
778
+ `Branch: refs/heads/${plan.branch}`,
779
+ `Parent: ${plan.parent ?? '<root>'}`,
780
+ `Tag: refs/tags/${plan.tag}`,
781
+ `Snapshot digest: ${plan.snapshotDigest}`,
782
+ `Expected commit: ${plan.expectedCommit}`,
783
+ `Plan digest: ${plan.planDigest}`,
784
+ ].join('\n') + '\n');
785
+ if (!options.confirm || !(await options.confirm('Apply this Catalog publication plan?'))) {
786
+ options.io.stderr('Catalog publication cancelled.\n');
787
+ return null;
788
+ }
372
789
  }
790
+ const result = await applyCatalogPublicationPlan({
791
+ workspaceRoot: workspace.workspaceRoot,
792
+ remote: target.remote,
793
+ branch: target.branch,
794
+ expectedPlanDigest: options.expectedPlanDigest,
795
+ env: options.env,
796
+ workspaceRootResolvedFrom: workspace.workspaceRootResolvedFrom,
797
+ remoteResolvedFrom: target.remoteResolvedFrom,
798
+ branchResolvedFrom: target.branchResolvedFrom,
799
+ });
800
+ for (const warning of result.warnings)
801
+ options.io.stderr(`${warning}\n`);
802
+ return result;
373
803
  }
374
804
  //# sourceMappingURL=catalog-publish.js.map