@lesliechan721/aw 0.1.0-beta.5 → 0.1.0-beta.50

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 (566) 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-root.mjs +4 -4
  11. package/dist/authoring/scripts/lib/plugin-root.mjs.map +1 -1
  12. package/dist/authoring/scripts/lib/plugin-version-check.d.mts +1 -0
  13. package/dist/authoring/scripts/lib/plugin-version-check.mjs +229 -8
  14. package/dist/authoring/scripts/lib/plugin-version-check.mjs.map +1 -1
  15. package/dist/authoring/scripts/lib/skill-scaffold.d.mts +77 -90
  16. package/dist/authoring/scripts/lib/skill-scaffold.mjs +99 -120
  17. package/dist/authoring/scripts/lib/skill-scaffold.mjs.map +1 -1
  18. package/dist/authoring/scripts/plugin-status.mjs +8 -11
  19. package/dist/authoring/scripts/plugin-status.mjs.map +1 -1
  20. package/dist/authoring/scripts/remove-plugin.mjs +3 -2
  21. package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
  22. package/dist/authoring/scripts/validate-plugin.mjs +346 -1131
  23. package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
  24. package/dist/scripts/aw-skill-eval-materializer.d.ts +26 -0
  25. package/dist/scripts/aw-skill-eval-materializer.js +306 -0
  26. package/dist/scripts/aw-skill-eval-materializer.js.map +1 -0
  27. package/dist/scripts/bundle-plugins.d.ts +1 -0
  28. package/dist/scripts/bundle-plugins.js +20 -5
  29. package/dist/scripts/bundle-plugins.js.map +1 -1
  30. package/dist/scripts/plugin-staging.d.ts +7 -9
  31. package/dist/scripts/plugin-staging.js +18 -29
  32. package/dist/scripts/plugin-staging.js.map +1 -1
  33. package/dist/scripts/test-plugin-scripts.d.ts +2 -0
  34. package/dist/scripts/test-plugin-scripts.js +47 -76
  35. package/dist/scripts/test-plugin-scripts.js.map +1 -1
  36. package/dist/scripts/test-workers.d.mts +24 -0
  37. package/dist/scripts/test-workers.mjs +59 -0
  38. package/dist/scripts/test-workers.mjs.map +1 -0
  39. package/dist/src/adapters/helpers.js +2 -2
  40. package/dist/src/adapters/helpers.js.map +1 -1
  41. package/dist/src/authoring/workspace-commands.d.ts +17 -1
  42. package/dist/src/authoring/workspace-commands.js +21 -4
  43. package/dist/src/authoring/workspace-commands.js.map +1 -1
  44. package/dist/src/commands/aw-capabilities.d.ts +78 -0
  45. package/dist/src/commands/aw-capabilities.js +264 -0
  46. package/dist/src/commands/aw-capabilities.js.map +1 -0
  47. package/dist/src/commands/catalog-dev-source.d.ts +154 -0
  48. package/dist/src/commands/catalog-dev-source.js +655 -0
  49. package/dist/src/commands/catalog-dev-source.js.map +1 -0
  50. package/dist/src/commands/catalog-generation.d.ts +21 -0
  51. package/dist/src/commands/catalog-generation.js +9 -0
  52. package/dist/src/commands/catalog-generation.js.map +1 -0
  53. package/dist/src/commands/catalog-publication-inspection.d.ts +71 -30
  54. package/dist/src/commands/catalog-publication-inspection.js +475 -63
  55. package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
  56. package/dist/src/commands/catalog-publication-journal.d.ts +68 -0
  57. package/dist/src/commands/catalog-publication-journal.js +292 -0
  58. package/dist/src/commands/catalog-publication-journal.js.map +1 -0
  59. package/dist/src/commands/catalog-publication-target.d.ts +18 -0
  60. package/dist/src/commands/catalog-publication-target.js +95 -0
  61. package/dist/src/commands/catalog-publication-target.js.map +1 -0
  62. package/dist/src/commands/catalog-publish.d.ts +73 -15
  63. package/dist/src/commands/catalog-publish.js +701 -212
  64. package/dist/src/commands/catalog-publish.js.map +1 -1
  65. package/dist/src/commands/catalog-source.d.ts +60 -22
  66. package/dist/src/commands/catalog-source.js +311 -91
  67. package/dist/src/commands/catalog-source.js.map +1 -1
  68. package/dist/src/commands/catalog-status.d.ts +18 -22
  69. package/dist/src/commands/catalog-status.js +81 -115
  70. package/dist/src/commands/catalog-status.js.map +1 -1
  71. package/dist/src/commands/catalog-store.d.ts +104 -0
  72. package/dist/src/commands/catalog-store.js +685 -0
  73. package/dist/src/commands/catalog-store.js.map +1 -0
  74. package/dist/src/commands/catalog-workspace-resolution.d.ts +13 -0
  75. package/dist/src/commands/catalog-workspace-resolution.js +42 -0
  76. package/dist/src/commands/catalog-workspace-resolution.js.map +1 -0
  77. package/dist/src/commands/console.js +28 -17
  78. package/dist/src/commands/console.js.map +1 -1
  79. package/dist/src/commands/dependency-operation-plan.d.ts +52 -15
  80. package/dist/src/commands/dependency-operation-plan.js +289 -7
  81. package/dist/src/commands/dependency-operation-plan.js.map +1 -1
  82. package/dist/src/commands/init.d.ts +5 -11
  83. package/dist/src/commands/init.js +30 -51
  84. package/dist/src/commands/init.js.map +1 -1
  85. package/dist/src/commands/offline-cleanup-evidence.d.ts +67 -0
  86. package/dist/src/commands/offline-cleanup-evidence.js +181 -0
  87. package/dist/src/commands/offline-cleanup-evidence.js.map +1 -0
  88. package/dist/src/commands/operation-plan.d.ts +146 -0
  89. package/dist/src/commands/operation-plan.js +71 -0
  90. package/dist/src/commands/operation-plan.js.map +1 -0
  91. package/dist/src/commands/operation-planner.d.ts +46 -0
  92. package/dist/src/commands/operation-planner.js +141 -0
  93. package/dist/src/commands/operation-planner.js.map +1 -0
  94. package/dist/src/commands/options.d.ts +9 -7
  95. package/dist/src/commands/options.js +83 -21
  96. package/dist/src/commands/options.js.map +1 -1
  97. package/dist/src/commands/plugin-capabilities.js +23 -3
  98. package/dist/src/commands/plugin-capabilities.js.map +1 -1
  99. package/dist/src/commands/rebuild-command.d.ts +77 -31
  100. package/dist/src/commands/rebuild-command.js +4862 -729
  101. package/dist/src/commands/rebuild-command.js.map +1 -1
  102. package/dist/src/commands/rebuild-integration.d.ts +131 -21
  103. package/dist/src/commands/rebuild-integration.js +2866 -1339
  104. package/dist/src/commands/rebuild-integration.js.map +1 -1
  105. package/dist/src/commands/rebuild-operations.d.ts +58 -30
  106. package/dist/src/commands/rebuild-operations.js +260 -319
  107. package/dist/src/commands/rebuild-operations.js.map +1 -1
  108. package/dist/src/commands/reconcile-operation-plan.d.ts +28 -0
  109. package/dist/src/commands/reconcile-operation-plan.js +47 -0
  110. package/dist/src/commands/reconcile-operation-plan.js.map +1 -0
  111. package/dist/src/commands/review-inspection.d.ts +228 -0
  112. package/dist/src/commands/review-inspection.js +1341 -0
  113. package/dist/src/commands/review-inspection.js.map +1 -0
  114. package/dist/src/commands/review-preparation.d.ts +49 -0
  115. package/dist/src/commands/review-preparation.js +427 -0
  116. package/dist/src/commands/review-preparation.js.map +1 -0
  117. package/dist/src/commands/runtime.d.ts +1 -5
  118. package/dist/src/commands/runtime.js +24 -50
  119. package/dist/src/commands/runtime.js.map +1 -1
  120. package/dist/src/commands/skill-eval.d.ts +39 -0
  121. package/dist/src/commands/skill-eval.js +400 -0
  122. package/dist/src/commands/skill-eval.js.map +1 -0
  123. package/dist/src/commands/status-v6.d.ts +279 -0
  124. package/dist/src/commands/status-v6.js +2787 -0
  125. package/dist/src/commands/status-v6.js.map +1 -0
  126. package/dist/src/commands/sync-command.d.ts +40 -0
  127. package/dist/src/commands/sync-command.js +250 -0
  128. package/dist/src/commands/sync-command.js.map +1 -0
  129. package/dist/src/commands/wizard.d.ts +8 -5
  130. package/dist/src/commands/wizard.js +6 -4
  131. package/dist/src/commands/wizard.js.map +1 -1
  132. package/dist/src/commands/write-commands.d.ts +9 -3
  133. package/dist/src/commands/write-commands.js +127 -31
  134. package/dist/src/commands/write-commands.js.map +1 -1
  135. package/dist/src/constants.d.ts +7 -1
  136. package/dist/src/constants.js +7 -1
  137. package/dist/src/constants.js.map +1 -1
  138. package/dist/src/eval/manifest-v1.d.ts +71 -0
  139. package/dist/src/eval/manifest-v1.js +370 -0
  140. package/dist/src/eval/manifest-v1.js.map +1 -0
  141. package/dist/src/generators/local-plugin.d.ts +5 -1
  142. package/dist/src/generators/local-plugin.js +236 -109
  143. package/dist/src/generators/local-plugin.js.map +1 -1
  144. package/dist/src/index.d.ts +10 -4
  145. package/dist/src/index.js +1793 -486
  146. package/dist/src/index.js.map +1 -1
  147. package/dist/src/output/command-receipt.d.ts +43 -46
  148. package/dist/src/output/command-receipt.js +256 -80
  149. package/dist/src/output/command-receipt.js.map +1 -1
  150. package/dist/src/output/model.d.ts +3 -44
  151. package/dist/src/output/model.js +1 -144
  152. package/dist/src/output/model.js.map +1 -1
  153. package/dist/src/output/rebuild-progress.js +1 -13
  154. package/dist/src/output/rebuild-progress.js.map +1 -1
  155. package/dist/src/portable/commands.d.ts +46 -7
  156. package/dist/src/portable/commands.js +349 -37
  157. package/dist/src/portable/commands.js.map +1 -1
  158. package/dist/src/portable/materializer.d.ts +17 -4
  159. package/dist/src/portable/materializer.js +179 -41
  160. package/dist/src/portable/materializer.js.map +1 -1
  161. package/dist/src/portable/skills-cli.d.ts +15 -7
  162. package/dist/src/portable/skills-cli.js +74 -20
  163. package/dist/src/portable/skills-cli.js.map +1 -1
  164. package/dist/src/review/eval-source-input.d.ts +43 -0
  165. package/dist/src/review/eval-source-input.js +207 -0
  166. package/dist/src/review/eval-source-input.js.map +1 -0
  167. package/dist/src/review/review-profile.d.ts +17 -0
  168. package/dist/src/review/review-profile.js +234 -0
  169. package/dist/src/review/review-profile.js.map +1 -0
  170. package/dist/src/review/review-selection.d.ts +30 -0
  171. package/dist/src/review/review-selection.js +527 -0
  172. package/dist/src/review/review-selection.js.map +1 -0
  173. package/dist/src/review/review-types.d.ts +68 -0
  174. package/dist/src/review/review-types.js +16 -0
  175. package/dist/src/review/review-types.js.map +1 -0
  176. package/dist/src/review/skill-materialization.d.ts +13 -0
  177. package/dist/src/review/skill-materialization.js +75 -0
  178. package/dist/src/review/skill-materialization.js.map +1 -0
  179. package/dist/src/review/source-binding.d.ts +183 -0
  180. package/dist/src/review/source-binding.js +708 -0
  181. package/dist/src/review/source-binding.js.map +1 -0
  182. package/dist/src/tui/catalog-freshness.d.ts +1 -0
  183. package/dist/src/tui/catalog-freshness.js +2 -0
  184. package/dist/src/tui/catalog-freshness.js.map +1 -0
  185. package/dist/src/tui/catalog-generation.d.ts +21 -0
  186. package/dist/src/tui/catalog-generation.js +156 -0
  187. package/dist/src/tui/catalog-generation.js.map +1 -0
  188. package/dist/src/tui/catalog-sources/projection.d.ts +4 -0
  189. package/dist/src/tui/catalog-sources/projection.js +17 -0
  190. package/dist/src/tui/catalog-sources/projection.js.map +1 -0
  191. package/dist/src/tui/catalog-sources/review.d.ts +3 -0
  192. package/dist/src/tui/catalog-sources/review.js +13 -0
  193. package/dist/src/tui/catalog-sources/review.js.map +1 -0
  194. package/dist/src/tui/catalog-sources/screens.d.ts +12 -0
  195. package/dist/src/tui/catalog-sources/screens.js +40 -0
  196. package/dist/src/tui/catalog-sources/screens.js.map +1 -0
  197. package/dist/src/tui/catalog-sources/session.d.ts +32 -0
  198. package/dist/src/tui/catalog-sources/session.js +300 -0
  199. package/dist/src/tui/catalog-sources/session.js.map +1 -0
  200. package/dist/src/tui/catalog-sources/types.d.ts +54 -0
  201. package/dist/src/tui/catalog-sources/types.js +2 -0
  202. package/dist/src/tui/catalog-sources/types.js.map +1 -0
  203. package/dist/src/tui/catalog-store-task.d.ts +16 -0
  204. package/dist/src/tui/catalog-store-task.js +19 -0
  205. package/dist/src/tui/catalog-store-task.js.map +1 -0
  206. package/dist/src/tui/clipboard.d.ts +13 -0
  207. package/dist/src/tui/clipboard.js +95 -0
  208. package/dist/src/tui/clipboard.js.map +1 -0
  209. package/dist/src/tui/components.d.ts +110 -3
  210. package/dist/src/tui/components.js +183 -36
  211. package/dist/src/tui/components.js.map +1 -1
  212. package/dist/src/tui/config-array-draft.d.ts +29 -0
  213. package/dist/src/tui/config-array-draft.js +48 -0
  214. package/dist/src/tui/config-array-draft.js.map +1 -0
  215. package/dist/src/tui/config-leaf-editor.d.ts +16 -0
  216. package/dist/src/tui/config-leaf-editor.js +206 -0
  217. package/dist/src/tui/config-leaf-editor.js.map +1 -0
  218. package/dist/src/tui/config-value-presentation.d.ts +20 -0
  219. package/dist/src/tui/config-value-presentation.js +104 -0
  220. package/dist/src/tui/config-value-presentation.js.map +1 -0
  221. package/dist/src/tui/console-app-v4.d.ts +14 -4
  222. package/dist/src/tui/console-app-v4.js +8941 -1872
  223. package/dist/src/tui/console-app-v4.js.map +1 -1
  224. package/dist/src/tui/content-item-card.d.ts +13 -0
  225. package/dist/src/tui/content-item-card.js +51 -0
  226. package/dist/src/tui/content-item-card.js.map +1 -0
  227. package/dist/src/tui/controller-runtime.d.ts +10 -2
  228. package/dist/src/tui/controller-runtime.js +3211 -388
  229. package/dist/src/tui/controller-runtime.js.map +1 -1
  230. package/dist/src/tui/controller.d.ts +615 -45
  231. package/dist/src/tui/controller.js +3558 -768
  232. package/dist/src/tui/controller.js.map +1 -1
  233. package/dist/src/tui/dependency-graph-view.d.ts +39 -0
  234. package/dist/src/tui/dependency-graph-view.js +121 -0
  235. package/dist/src/tui/dependency-graph-view.js.map +1 -0
  236. package/dist/src/tui/dependency-graph.d.ts +81 -0
  237. package/dist/src/tui/dependency-graph.js +452 -0
  238. package/dist/src/tui/dependency-graph.js.map +1 -0
  239. package/dist/src/tui/diagnostic-projection.d.ts +23 -0
  240. package/dist/src/tui/diagnostic-projection.js +567 -0
  241. package/dist/src/tui/diagnostic-projection.js.map +1 -0
  242. package/dist/src/tui/diagnostics.d.ts +3 -3
  243. package/dist/src/tui/diagnostics.js +14 -2
  244. package/dist/src/tui/diagnostics.js.map +1 -1
  245. package/dist/src/tui/entity-cards.d.ts +55 -0
  246. package/dist/src/tui/entity-cards.js +220 -0
  247. package/dist/src/tui/entity-cards.js.map +1 -0
  248. package/dist/src/tui/glossary.d.ts +23 -0
  249. package/dist/src/tui/glossary.js +42 -0
  250. package/dist/src/tui/glossary.js.map +1 -0
  251. package/dist/src/tui/index.d.ts +6 -1
  252. package/dist/src/tui/index.js +5 -1
  253. package/dist/src/tui/index.js.map +1 -1
  254. package/dist/src/tui/input-display.d.ts +9 -0
  255. package/dist/src/tui/input-display.js +58 -0
  256. package/dist/src/tui/input-display.js.map +1 -0
  257. package/dist/src/tui/keys.d.ts +44 -0
  258. package/dist/src/tui/keys.js +43 -15
  259. package/dist/src/tui/keys.js.map +1 -1
  260. package/dist/src/tui/lifecycle-action-view.d.ts +6 -0
  261. package/dist/src/tui/lifecycle-action-view.js +36 -0
  262. package/dist/src/tui/lifecycle-action-view.js.map +1 -0
  263. package/dist/src/tui/model.d.ts +223 -31
  264. package/dist/src/tui/model.js +1510 -397
  265. package/dist/src/tui/model.js.map +1 -1
  266. package/dist/src/tui/operation-diagnostic-screens.d.ts +8 -0
  267. package/dist/src/tui/operation-diagnostic-screens.js +71 -0
  268. package/dist/src/tui/operation-diagnostic-screens.js.map +1 -0
  269. package/dist/src/tui/operation-history.d.ts +81 -0
  270. package/dist/src/tui/operation-history.js +136 -0
  271. package/dist/src/tui/operation-history.js.map +1 -0
  272. package/dist/src/tui/operation-review-planner.d.ts +21 -0
  273. package/dist/src/tui/operation-review-planner.js +1295 -0
  274. package/dist/src/tui/operation-review-planner.js.map +1 -0
  275. package/dist/src/tui/plugin-content.d.ts +31 -0
  276. package/dist/src/tui/plugin-content.js +680 -0
  277. package/dist/src/tui/plugin-content.js.map +1 -0
  278. package/dist/src/tui/plugin-detail.d.ts +52 -0
  279. package/dist/src/tui/plugin-detail.js +165 -0
  280. package/dist/src/tui/plugin-detail.js.map +1 -0
  281. package/dist/src/tui/plugin-write-task.d.ts +69 -0
  282. package/dist/src/tui/plugin-write-task.js +286 -0
  283. package/dist/src/tui/plugin-write-task.js.map +1 -0
  284. package/dist/src/tui/project-inventory.d.ts +68 -0
  285. package/dist/src/tui/project-inventory.js +203 -0
  286. package/dist/src/tui/project-inventory.js.map +1 -0
  287. package/dist/src/tui/prompt.js +4 -15
  288. package/dist/src/tui/prompt.js.map +1 -1
  289. package/dist/src/tui/query-header.d.ts +30 -0
  290. package/dist/src/tui/query-header.js +40 -0
  291. package/dist/src/tui/query-header.js.map +1 -0
  292. package/dist/src/tui/reader.d.ts +37 -0
  293. package/dist/src/tui/reader.js +47 -0
  294. package/dist/src/tui/reader.js.map +1 -0
  295. package/dist/src/tui/router.d.ts +197 -10
  296. package/dist/src/tui/router.js +338 -50
  297. package/dist/src/tui/router.js.map +1 -1
  298. package/dist/src/tui/screen-registry.d.ts +701 -0
  299. package/dist/src/tui/screen-registry.js +230 -0
  300. package/dist/src/tui/screen-registry.js.map +1 -0
  301. package/dist/src/tui/session-console-app.d.ts +6 -0
  302. package/dist/src/tui/session-console-app.js +13 -0
  303. package/dist/src/tui/session-console-app.js.map +1 -0
  304. package/dist/src/tui/session-host.d.ts +45 -0
  305. package/dist/src/tui/session-host.js +209 -0
  306. package/dist/src/tui/session-host.js.map +1 -0
  307. package/dist/src/tui/source-detail-card.d.ts +29 -0
  308. package/dist/src/tui/source-detail-card.js +45 -0
  309. package/dist/src/tui/source-detail-card.js.map +1 -0
  310. package/dist/src/tui/source-ref-presets.d.ts +3 -0
  311. package/dist/src/tui/source-ref-presets.js +11 -0
  312. package/dist/src/tui/source-ref-presets.js.map +1 -0
  313. package/dist/src/tui/theme.d.ts +12 -0
  314. package/dist/src/tui/theme.js +12 -0
  315. package/dist/src/tui/theme.js.map +1 -1
  316. package/dist/src/tui/viewport.d.ts +1 -0
  317. package/dist/src/tui/viewport.js +23 -0
  318. package/dist/src/tui/viewport.js.map +1 -1
  319. package/dist/src/tui/views.js +31 -3
  320. package/dist/src/tui/views.js.map +1 -1
  321. package/dist/src/tui/wizard.js +37 -13
  322. package/dist/src/tui/wizard.js.map +1 -1
  323. package/dist/src/types.d.ts +244 -20
  324. package/dist/src/types.js +1 -0
  325. package/dist/src/types.js.map +1 -1
  326. package/dist/src/utils/agent-version.d.ts +7 -1
  327. package/dist/src/utils/agent-version.js +41 -8
  328. package/dist/src/utils/agent-version.js.map +1 -1
  329. package/dist/src/utils/artifact-plan.d.ts +5 -4
  330. package/dist/src/utils/artifact-plan.js +18 -7
  331. package/dist/src/utils/artifact-plan.js.map +1 -1
  332. package/dist/src/utils/artifact-renderer.d.ts +17 -7
  333. package/dist/src/utils/artifact-renderer.js +214 -216
  334. package/dist/src/utils/artifact-renderer.js.map +1 -1
  335. package/dist/src/utils/artifact-request.d.ts +21 -0
  336. package/dist/src/utils/artifact-request.js +78 -0
  337. package/dist/src/utils/artifact-request.js.map +1 -0
  338. package/dist/src/utils/aw-home-mutation-lock.d.ts +1 -0
  339. package/dist/src/utils/aw-home-mutation-lock.js +32 -4
  340. package/dist/src/utils/aw-home-mutation-lock.js.map +1 -1
  341. package/dist/src/utils/bundle-integrity.d.ts +0 -1
  342. package/dist/src/utils/bundle-integrity.js +0 -25
  343. package/dist/src/utils/bundle-integrity.js.map +1 -1
  344. package/dist/src/utils/bundle-layout.js +22 -29
  345. package/dist/src/utils/bundle-layout.js.map +1 -1
  346. package/dist/src/utils/catalog-capability-projection.d.ts +8 -0
  347. package/dist/src/utils/catalog-capability-projection.js +14 -0
  348. package/dist/src/utils/catalog-capability-projection.js.map +1 -0
  349. package/dist/src/utils/catalog-digests.d.ts +10 -0
  350. package/dist/src/utils/catalog-digests.js +57 -20
  351. package/dist/src/utils/catalog-digests.js.map +1 -1
  352. package/dist/src/utils/catalog-generation-control-snapshot.d.ts +11 -0
  353. package/dist/src/utils/catalog-generation-control-snapshot.js +45 -0
  354. package/dist/src/utils/catalog-generation-control-snapshot.js.map +1 -0
  355. package/dist/src/utils/catalog-generation-error.d.ts +16 -0
  356. package/dist/src/utils/catalog-generation-error.js +30 -0
  357. package/dist/src/utils/catalog-generation-error.js.map +1 -0
  358. package/dist/src/utils/catalog-generation-resolver.d.ts +44 -0
  359. package/dist/src/utils/catalog-generation-resolver.js +273 -0
  360. package/dist/src/utils/catalog-generation-resolver.js.map +1 -0
  361. package/dist/src/utils/catalog-generation-service.d.ts +172 -0
  362. package/dist/src/utils/catalog-generation-service.js +1271 -0
  363. package/dist/src/utils/catalog-generation-service.js.map +1 -0
  364. package/dist/src/utils/catalog-generation-state.d.ts +22 -0
  365. package/dist/src/utils/catalog-generation-state.js +192 -0
  366. package/dist/src/utils/catalog-generation-state.js.map +1 -0
  367. package/dist/src/utils/catalog-generation-store.d.ts +58 -0
  368. package/dist/src/utils/catalog-generation-store.js +452 -0
  369. package/dist/src/utils/catalog-generation-store.js.map +1 -0
  370. package/dist/src/utils/catalog-manifest-v7.d.ts +5 -0
  371. package/dist/src/utils/{catalog-manifest-v4.js → catalog-manifest-v7.js} +35 -43
  372. package/dist/src/utils/catalog-manifest-v7.js.map +1 -0
  373. package/dist/src/utils/catalog-operation-context.d.ts +20 -0
  374. package/dist/src/utils/catalog-operation-context.js +142 -0
  375. package/dist/src/utils/catalog-operation-context.js.map +1 -0
  376. package/dist/src/utils/catalog-public-error.d.ts +7 -3
  377. package/dist/src/utils/catalog-public-error.js +28 -8
  378. package/dist/src/utils/catalog-public-error.js.map +1 -1
  379. package/dist/src/utils/catalog-runtime-projection.d.ts +3 -0
  380. package/dist/src/utils/catalog-runtime-projection.js +5 -40
  381. package/dist/src/utils/catalog-runtime-projection.js.map +1 -1
  382. package/dist/src/utils/catalog-snapshot.d.ts +5 -3
  383. package/dist/src/utils/catalog-snapshot.js +11 -3
  384. package/dist/src/utils/catalog-snapshot.js.map +1 -1
  385. package/dist/src/utils/catalog-source-identity.d.ts +1 -0
  386. package/dist/src/utils/catalog-source-identity.js +21 -2
  387. package/dist/src/utils/catalog-source-identity.js.map +1 -1
  388. package/dist/src/utils/catalog-source-impact.d.ts +21 -0
  389. package/dist/src/utils/catalog-source-impact.js +344 -0
  390. package/dist/src/utils/catalog-source-impact.js.map +1 -0
  391. package/dist/src/utils/catalog-source-references.d.ts +3 -2
  392. package/dist/src/utils/catalog-source-references.js +195 -347
  393. package/dist/src/utils/catalog-source-references.js.map +1 -1
  394. package/dist/src/utils/catalog-sources.d.ts +15 -1
  395. package/dist/src/utils/catalog-sources.js +206 -27
  396. package/dist/src/utils/catalog-sources.js.map +1 -1
  397. package/dist/src/utils/codex-config.d.ts +2 -0
  398. package/dist/src/utils/codex-config.js +26 -5
  399. package/dist/src/utils/codex-config.js.map +1 -1
  400. package/dist/src/utils/codex-manager.d.ts +79 -0
  401. package/dist/src/utils/codex-manager.js +747 -0
  402. package/dist/src/utils/codex-manager.js.map +1 -0
  403. package/dist/src/utils/codex-marketplace-path.d.ts +5 -0
  404. package/dist/src/utils/codex-marketplace-path.js +45 -0
  405. package/dist/src/utils/codex-marketplace-path.js.map +1 -0
  406. package/dist/src/utils/codex-native-observation.d.ts +49 -0
  407. package/dist/src/utils/codex-native-observation.js +154 -0
  408. package/dist/src/utils/codex-native-observation.js.map +1 -0
  409. package/dist/src/utils/codex-native-render-receipt.d.ts +40 -0
  410. package/dist/src/utils/codex-native-render-receipt.js +205 -0
  411. package/dist/src/utils/codex-native-render-receipt.js.map +1 -0
  412. package/dist/src/utils/codex-reconciler.d.ts +126 -0
  413. package/dist/src/utils/codex-reconciler.js +298 -0
  414. package/dist/src/utils/codex-reconciler.js.map +1 -0
  415. package/dist/src/utils/codex-shared-native.d.ts +43 -0
  416. package/dist/src/utils/codex-shared-native.js +81 -0
  417. package/dist/src/utils/codex-shared-native.js.map +1 -0
  418. package/dist/src/utils/codex-skill-staging.d.ts +2 -0
  419. package/dist/src/utils/codex-skill-staging.js.map +1 -1
  420. package/dist/src/utils/codex-surface-analysis.d.ts +46 -0
  421. package/dist/src/utils/codex-surface-analysis.js +247 -0
  422. package/dist/src/utils/codex-surface-analysis.js.map +1 -0
  423. package/dist/src/utils/dynamic-skill-tree.d.ts +4 -0
  424. package/dist/src/utils/dynamic-skill-tree.js +35 -5
  425. package/dist/src/utils/dynamic-skill-tree.js.map +1 -1
  426. package/dist/src/utils/git-catalog-provider.d.ts +16 -0
  427. package/dist/src/utils/git-catalog-provider.js +177 -145
  428. package/dist/src/utils/git-catalog-provider.js.map +1 -1
  429. package/dist/src/utils/local-marketplace.d.ts +18 -1
  430. package/dist/src/utils/local-marketplace.js +354 -84
  431. package/dist/src/utils/local-marketplace.js.map +1 -1
  432. package/dist/src/utils/manifest.d.ts +1 -3
  433. package/dist/src/utils/manifest.js +1 -3
  434. package/dist/src/utils/manifest.js.map +1 -1
  435. package/dist/src/utils/multi-source-catalog.d.ts +3 -9
  436. package/dist/src/utils/multi-source-catalog.js +54 -110
  437. package/dist/src/utils/multi-source-catalog.js.map +1 -1
  438. package/dist/src/utils/native-cli.d.ts +55 -7
  439. package/dist/src/utils/native-cli.js +400 -58
  440. package/dist/src/utils/native-cli.js.map +1 -1
  441. package/dist/src/utils/orphan-marketplace-cleanup.js +0 -4
  442. package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
  443. package/dist/src/utils/ownership.d.ts +84 -20
  444. package/dist/src/utils/ownership.js +179 -222
  445. package/dist/src/utils/ownership.js.map +1 -1
  446. package/dist/src/utils/path-catalog-provider.d.ts +1 -1
  447. package/dist/src/utils/path-catalog-provider.js +54 -65
  448. package/dist/src/utils/path-catalog-provider.js.map +1 -1
  449. package/dist/src/utils/paths.d.ts +0 -1
  450. package/dist/src/utils/paths.js +0 -1
  451. package/dist/src/utils/paths.js.map +1 -1
  452. package/dist/src/utils/plugin-config-impact.d.ts +33 -0
  453. package/dist/src/utils/plugin-config-impact.js +298 -0
  454. package/dist/src/utils/plugin-config-impact.js.map +1 -0
  455. package/dist/src/utils/plugin-config-write.d.ts +52 -27
  456. package/dist/src/utils/plugin-config-write.js +1000 -296
  457. package/dist/src/utils/plugin-config-write.js.map +1 -1
  458. package/dist/src/utils/plugin-config.d.ts +153 -93
  459. package/dist/src/utils/plugin-config.js +1116 -968
  460. package/dist/src/utils/plugin-config.js.map +1 -1
  461. package/dist/src/utils/plugin-intent-state.d.ts +49 -0
  462. package/dist/src/utils/plugin-intent-state.js +320 -0
  463. package/dist/src/utils/plugin-intent-state.js.map +1 -0
  464. package/dist/src/utils/plugin-scripts.d.ts +65 -125
  465. package/dist/src/utils/plugin-scripts.js +484 -524
  466. package/dist/src/utils/plugin-scripts.js.map +1 -1
  467. package/dist/src/utils/process-tree.d.ts +2 -2
  468. package/dist/src/utils/process-tree.js +1 -1
  469. package/dist/src/utils/process-tree.js.map +1 -1
  470. package/dist/src/utils/project-boundary.d.ts +11 -13
  471. package/dist/src/utils/project-boundary.js +28 -34
  472. package/dist/src/utils/project-boundary.js.map +1 -1
  473. package/dist/src/utils/runtime-config.d.ts +20 -0
  474. package/dist/src/utils/runtime-config.js +75 -0
  475. package/dist/src/utils/runtime-config.js.map +1 -0
  476. package/dist/src/utils/safe-fs.d.ts +21 -0
  477. package/dist/src/utils/safe-fs.js +111 -0
  478. package/dist/src/utils/safe-fs.js.map +1 -0
  479. package/dist/src/utils/safe-operation-diagnostic.d.ts +15 -0
  480. package/dist/src/utils/safe-operation-diagnostic.js +33 -0
  481. package/dist/src/utils/safe-operation-diagnostic.js.map +1 -0
  482. package/dist/src/utils/sensitive-content.d.ts +4 -0
  483. package/dist/src/utils/sensitive-content.js +36 -0
  484. package/dist/src/utils/sensitive-content.js.map +1 -0
  485. package/dist/src/utils/state-paths.js +7 -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 +7 -0
  491. package/dist/src/utils/windows-claude-shim.js +10 -0
  492. package/dist/src/utils/windows-claude-shim.js.map +1 -0
  493. package/dist/src/utils/windows-npm-shim.d.ts +14 -0
  494. package/dist/src/utils/windows-npm-shim.js +140 -0
  495. package/dist/src/utils/windows-npm-shim.js.map +1 -0
  496. package/dist/vitest.config.js +92 -10
  497. package/dist/vitest.config.js.map +1 -1
  498. package/package.json +27 -18
  499. package/dist/authoring/scripts/check-plugin-versions.d.mts +0 -2
  500. package/dist/authoring/scripts/check-plugin-versions.mjs +0 -5
  501. package/dist/authoring/scripts/check-plugin-versions.mjs.map +0 -1
  502. package/dist/scripts/aw-skill-eval-engine.d.ts +0 -13
  503. package/dist/scripts/aw-skill-eval-engine.js +0 -31
  504. package/dist/scripts/aw-skill-eval-engine.js.map +0 -1
  505. package/dist/scripts/codex-eval-app-server.d.ts +0 -89
  506. package/dist/scripts/codex-eval-app-server.js +0 -1228
  507. package/dist/scripts/codex-eval-app-server.js.map +0 -1
  508. package/dist/scripts/codex-eval-isolation.d.ts +0 -61
  509. package/dist/scripts/codex-eval-isolation.js +0 -318
  510. package/dist/scripts/codex-eval-isolation.js.map +0 -1
  511. package/dist/scripts/codex-eval-process-management.d.ts +0 -8
  512. package/dist/scripts/codex-eval-process-management.js +0 -69
  513. package/dist/scripts/codex-eval-process-management.js.map +0 -1
  514. package/dist/scripts/codex-eval-process-tree.d.ts +0 -38
  515. package/dist/scripts/codex-eval-process-tree.js +0 -803
  516. package/dist/scripts/codex-eval-process-tree.js.map +0 -1
  517. package/dist/scripts/codex-eval-runtime-config.d.ts +0 -62
  518. package/dist/scripts/codex-eval-runtime-config.js +0 -843
  519. package/dist/scripts/codex-eval-runtime-config.js.map +0 -1
  520. package/dist/scripts/codex-trigger-eval.d.ts +0 -84
  521. package/dist/scripts/codex-trigger-eval.js +0 -968
  522. package/dist/scripts/codex-trigger-eval.js.map +0 -1
  523. package/dist/scripts/eval-plugin-skills-audited.d.ts +0 -6
  524. package/dist/scripts/eval-plugin-skills-audited.js +0 -261
  525. package/dist/scripts/eval-plugin-skills-audited.js.map +0 -1
  526. package/dist/scripts/eval-plugin-skills.d.ts +0 -45
  527. package/dist/scripts/eval-plugin-skills.js +0 -1586
  528. package/dist/scripts/eval-plugin-skills.js.map +0 -1
  529. package/dist/scripts/eval-run-layout.d.ts +0 -17
  530. package/dist/scripts/eval-run-layout.js +0 -26
  531. package/dist/scripts/eval-run-layout.js.map +0 -1
  532. package/dist/scripts/plugin-eval-contract.d.ts +0 -185
  533. package/dist/scripts/plugin-eval-contract.js +0 -695
  534. package/dist/scripts/plugin-eval-contract.js.map +0 -1
  535. package/dist/scripts/plugin-eval-materializer.d.ts +0 -13
  536. package/dist/scripts/plugin-eval-materializer.js +0 -421
  537. package/dist/scripts/plugin-eval-materializer.js.map +0 -1
  538. package/dist/scripts/skill-reporting.d.ts +0 -212
  539. package/dist/scripts/skill-reporting.js +0 -922
  540. package/dist/scripts/skill-reporting.js.map +0 -1
  541. package/dist/src/commands/status-v4.d.ts +0 -123
  542. package/dist/src/commands/status-v4.js +0 -905
  543. package/dist/src/commands/status-v4.js.map +0 -1
  544. package/dist/src/commands/status.d.ts +0 -93
  545. package/dist/src/commands/status.js +0 -442
  546. package/dist/src/commands/status.js.map +0 -1
  547. package/dist/src/utils/active-marketplace-runtime-lock.d.ts +0 -12
  548. package/dist/src/utils/active-marketplace-runtime-lock.js +0 -133
  549. package/dist/src/utils/active-marketplace-runtime-lock.js.map +0 -1
  550. package/dist/src/utils/catalog-manifest-v3.d.ts +0 -2
  551. package/dist/src/utils/catalog-manifest-v3.js +0 -3
  552. package/dist/src/utils/catalog-manifest-v3.js.map +0 -1
  553. package/dist/src/utils/catalog-manifest-v4.d.ts +0 -5
  554. package/dist/src/utils/catalog-manifest-v4.js.map +0 -1
  555. package/dist/src/utils/catalog-source-cache.d.ts +0 -62
  556. package/dist/src/utils/catalog-source-cache.js +0 -296
  557. package/dist/src/utils/catalog-source-cache.js.map +0 -1
  558. package/dist/src/utils/codex-project-surface.d.ts +0 -3
  559. package/dist/src/utils/codex-project-surface.js +0 -49
  560. package/dist/src/utils/codex-project-surface.js.map +0 -1
  561. package/dist/src/utils/lifecycle-active-store.d.ts +0 -175
  562. package/dist/src/utils/lifecycle-active-store.js +0 -1276
  563. package/dist/src/utils/lifecycle-active-store.js.map +0 -1
  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
@@ -0,0 +1,2787 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { analyzeCodexSurface } from '../utils/codex-surface-analysis.js';
4
+ import { catalogSourceErrorCode, sanitizeCatalogSourceError, } from '../utils/catalog-public-error.js';
5
+ import { calculateCatalogSourceIdentity } from '../utils/catalog-source-identity.js';
6
+ import { canonicalMarketplaceRegistrationNames, inventoryCatalogSourceReferences, inventoryLegacyOwnerReferences, } from '../utils/catalog-source-references.js';
7
+ import { readStrictNamespacedMarketplaceRoot } from '../utils/local-marketplace.js';
8
+ import { readCatalogSourcesConfigSnapshot, resolveCatalogSourceRef } from '../utils/catalog-sources.js';
9
+ import { formatPluginId, parsePluginId, planPluginSelectorSourceIds, withResolvedMultiSourceCatalog, } from '../utils/multi-source-catalog.js';
10
+ import { assertStrictSemVer, checkAwCapabilitySupport, compareStrictSemVer, readPluginManifest, tryParseStrictSemVer, } from '../utils/manifest.js';
11
+ import { resolveCliPackageRoot, resolveCodexPaths } from '../utils/paths.js';
12
+ import { resolveSupportedPlatforms, supportsPlatform } from '../utils/platform-support.js';
13
+ import { parsePlatformValue, parseScopeValue } from './options.js';
14
+ import { inspectCodexPluginRegistrationLive, inspectCodexSharedNativeLive, inspectRebuildTarget, } from './rebuild-integration.js';
15
+ import { createNoopReporter } from '../output/reporter.js';
16
+ import { createNoopDebugLogger } from '../output/debug-log.js';
17
+ import { getDefaultNativeCliRunner } from '../utils/native-cli.js';
18
+ import { createCodexNativeObservationSession, } from '../utils/codex-native-observation.js';
19
+ import { resolveAwHome } from '../utils/paths.js';
20
+ import { codexProjectConfigAliasesUserHome, createProjectLocationKey, getClaudeHome, getCodexHome, resolveCanonicalRepoProjectKey, } from '../utils/state-paths.js';
21
+ import { resolveEffectivePluginConfig, resolveProjectArtifactRenderConfig, } from '../utils/plugin-config.js';
22
+ import { readCodexConfigFile } from '../utils/codex-config.js';
23
+ import { observePluginIntentState, } from '../utils/plugin-intent-state.js';
24
+ import { IMPLEMENTED_AW_CAPABILITIES } from './aw-capabilities.js';
25
+ import { createDependencyPlacementPlan } from './dependency-operation-plan.js';
26
+ import { getCodexOperationRequirement } from '../utils/agent-version.js';
27
+ import { inspectSystemCodex, } from '../utils/codex-manager.js';
28
+ export function statusTargetPlacements(target) {
29
+ if (target.platform === 'claude')
30
+ return [target];
31
+ return target.placements.map((placement) => ({
32
+ pluginName: target.pluginName,
33
+ sourceId: target.sourceId,
34
+ sourceIdentity: target.sourceIdentity,
35
+ pluginId: target.pluginId,
36
+ ...(target.version ? { version: target.version } : {}),
37
+ platform: target.platform,
38
+ cwd: target.cwd,
39
+ ...placement,
40
+ sharedComponents: target.components.filter((component) => component.kind !== 'systemConsumer' || component.key === `codex:${placement.scope}`),
41
+ sharedReasons: target.reasons.filter((reason) => reason.code.startsWith('codexSharedNative') || reason.code === 'staleCacheObserved'),
42
+ }));
43
+ }
44
+ export function flattenStatusTargets(targets) {
45
+ return targets.flatMap(statusTargetPlacements);
46
+ }
47
+ export function projectStatusSharedNativeReasons(sharedNative, existingReasonCodes = [], desiredEnabled = false) {
48
+ if (!sharedNative)
49
+ return [];
50
+ const warning = (code, message) => ({
51
+ code,
52
+ message: `${code}: ${message}`,
53
+ severity: 'warning',
54
+ });
55
+ const blocking = (code, message) => ({
56
+ code,
57
+ message: `${code}: ${message}`,
58
+ severity: 'blocking',
59
+ });
60
+ return [
61
+ ...(sharedNative.state === 'blocked' && sharedNative.reason === 'foreign'
62
+ && !existingReasonCodes.includes('codexSharedNativeForeign')
63
+ ? [blocking('codexSharedNativeForeign', `${sharedNative.pluginId} is foreign and was preserved.`)]
64
+ : []),
65
+ ...(sharedNative.state === 'blocked' && sharedNative.reason === 'unreadable'
66
+ && !existingReasonCodes.includes('codexSharedNativeCorrupt')
67
+ ? [blocking('codexSharedNativeCorrupt', `${sharedNative.pluginId} is unreadable.`)]
68
+ : []),
69
+ ...(sharedNative.state === 'replaceable' && sharedNative.reason === 'damaged'
70
+ ? [warning('codexSharedNativeCorrupt', `${sharedNative.pluginId} shared generated content is missing or damaged and can be replaced.`)]
71
+ : []),
72
+ ...(sharedNative.state === 'replaceable' && sharedNative.reason === 'outdated'
73
+ ? [warning('codexSharedNativeUpdateRequired', `${sharedNative.pluginId} requires a shared update.`)]
74
+ : []),
75
+ ...(sharedNative.state === 'replaceable' && sharedNative.reason === 'renderDrift'
76
+ ? [warning('codexSharedNativeRenderDrift', `${sharedNative.pluginId} shared generated content does not match the current render inputs and can be replaced.`)]
77
+ : []),
78
+ ...(sharedNative.staleCacheObserved
79
+ ? [warning('staleCacheObserved', `${sharedNative.pluginId} has non-blocking stale Codex cache residue.`)]
80
+ : []),
81
+ ...(sharedNative.state === 'unobserved' && desiredEnabled
82
+ ? [warning('codexSharedNativeUnobserved', `${sharedNative.pluginId} was not observed by a compatible Codex consumer.`)]
83
+ : []),
84
+ ];
85
+ }
86
+ function statusComponent(target, kind, key) {
87
+ return [...target.components, ...(target.sharedComponents ?? [])].find((component) => component.kind === kind && (key === undefined || component.key === key));
88
+ }
89
+ export function statusTargetIntent(target) {
90
+ const metadata = statusComponent(target, 'intent', 'desired')?.metadata;
91
+ return {
92
+ enabled: metadata?.enabled === true,
93
+ scopes: Array.isArray(metadata?.scopes)
94
+ ? metadata.scopes.filter((scope) => scope === 'user' || scope === 'project')
95
+ : [],
96
+ relation: metadata?.relation === 'root'
97
+ || metadata?.relation === 'dependency'
98
+ || metadata?.relation === 'managed'
99
+ ? metadata.relation
100
+ : 'none',
101
+ };
102
+ }
103
+ export function statusTargetOwnershipState(target) {
104
+ const components = target.components.filter((component) => component.kind === 'ownership');
105
+ if (components.some((component) => component.state === 'error'))
106
+ return 'error';
107
+ if (components.some((component) => component.state === 'partial'))
108
+ return 'partial';
109
+ if (components.some((component) => component.state === 'present'))
110
+ return 'present';
111
+ return 'absent';
112
+ }
113
+ export function statusTargetSharedNative(target) {
114
+ const component = statusComponent(target, 'sharedNative');
115
+ if (!component || (component.state !== 'missing'
116
+ && component.state !== 'usable'
117
+ && component.state !== 'replaceable'
118
+ && component.state !== 'blocked'
119
+ && component.state !== 'unobserved'))
120
+ return undefined;
121
+ const reason = component.metadata?.reason;
122
+ return {
123
+ pluginId: component.key,
124
+ state: component.state,
125
+ ...(reason === 'outdated' || reason === 'damaged' || reason === 'renderDrift'
126
+ || reason === 'foreign' || reason === 'unreadable'
127
+ ? { reason }
128
+ : {}),
129
+ ...(typeof component.metadata?.version === 'string'
130
+ ? { version: component.metadata.version }
131
+ : {}),
132
+ ...(typeof component.metadata?.desiredVersion === 'string'
133
+ ? { desiredVersion: component.metadata.desiredVersion }
134
+ : {}),
135
+ ...(typeof component.metadata?.diagnostic === 'string'
136
+ ? { diagnostic: component.metadata.diagnostic }
137
+ : {}),
138
+ ...(component.metadata?.staleCacheObserved === true ? { staleCacheObserved: true } : {}),
139
+ };
140
+ }
141
+ export function statusTargetActivation(target) {
142
+ const user = statusComponent(target, 'activation', 'user');
143
+ const project = statusComponent(target, 'activation', 'project');
144
+ const consumer = statusComponent(target, 'systemConsumer');
145
+ if (!user && !project && !consumer)
146
+ return undefined;
147
+ const activation = user ?? project ?? consumer;
148
+ const evidence = activation?.metadata?.evidence;
149
+ const requiredMinVersion = consumer?.metadata?.requiredMinVersion;
150
+ let systemConsumer;
151
+ if (consumer && typeof requiredMinVersion === 'string') {
152
+ const detectedVersion = consumer.metadata?.detectedVersion;
153
+ const code = consumer.metadata?.code;
154
+ const diagnostic = consumer.metadata?.diagnostic;
155
+ systemConsumer = consumer.state === 'missing' || consumer.state === 'unobserved'
156
+ ? { state: consumer.state, requiredMinVersion }
157
+ : consumer.state === 'compatible' && typeof detectedVersion === 'string'
158
+ ? { state: 'compatible', detectedVersion, requiredMinVersion }
159
+ : consumer.state === 'incompatible'
160
+ && (code === 'codexProjectPluginVersionTooLow' || code === 'codexSystemCliUnsupported')
161
+ && typeof detectedVersion === 'string'
162
+ && typeof diagnostic === 'string'
163
+ ? { state: 'incompatible', code, detectedVersion, diagnostic, requiredMinVersion }
164
+ : consumer.state === 'unresolved'
165
+ && (code === 'codexProjectPluginUnsupported' || code === 'codexSystemCliUnsupported')
166
+ && typeof diagnostic === 'string'
167
+ ? { state: 'unresolved', code, diagnostic, requiredMinVersion }
168
+ : undefined;
169
+ }
170
+ return {
171
+ ...(user ? { user: user.state === 'enabled' } : {}),
172
+ ...(project ? { project: project.state === 'enabled' } : {}),
173
+ ...(typeof activation?.metadata?.effective === 'boolean'
174
+ ? { effective: activation.metadata.effective }
175
+ : {}),
176
+ evidence: evidence === 'observed' || evidence === 'unobserved' ? evidence : 'assumed',
177
+ ...(systemConsumer ? { systemConsumer } : {}),
178
+ };
179
+ }
180
+ export function statusTargetExtensions(target) {
181
+ const component = statusComponent(target, 'extension', 'aw');
182
+ if (!component || (component.state !== 'ready'
183
+ && component.state !== 'missing'
184
+ && component.state !== 'drifted'
185
+ && component.state !== 'conflict'))
186
+ return undefined;
187
+ const kinds = Array.isArray(component.metadata?.kinds)
188
+ ? component.metadata.kinds.filter((kind) => kind === 'skill'
189
+ || kind === 'instruction'
190
+ || kind === 'permission'
191
+ || kind === 'agent'
192
+ || kind === 'config')
193
+ : [];
194
+ return { state: component.state, kinds };
195
+ }
196
+ function resolveCatalogEntrySupportedPlatforms(policy) {
197
+ return resolveSupportedPlatforms({ marketplace: { policy } });
198
+ }
199
+ let dependencyInspectionHookForTests;
200
+ export function setStatusDependencyInspectionHookForTests(hook) {
201
+ dependencyInspectionHookForTests = hook;
202
+ }
203
+ export async function loadConsoleItemsResult(options = {}, runtime = {}) {
204
+ const result = await statusCommandV8({
205
+ cwd: options.cwd ?? process.cwd(),
206
+ env: runtime.env,
207
+ platform: options.platform,
208
+ scope: options.scope,
209
+ verbose: options.verbose,
210
+ });
211
+ const groups = new Map();
212
+ const summaries = new Map(result.pluginSummaries.map((summary) => [summary.pluginId, summary]));
213
+ for (const target of result.payload.targets) {
214
+ const summary = summaries.get(target.pluginId);
215
+ let pluginSummary;
216
+ if (summary !== undefined) {
217
+ const { pluginName: _pluginName, pluginId: _pluginId, ...projected } = summary;
218
+ pluginSummary = projected;
219
+ }
220
+ const current = groups.get(target.pluginId) ?? {
221
+ pluginName: target.pluginId,
222
+ ...(target.version ? { version: target.version } : {}),
223
+ ...(pluginSummary ? { pluginSummary } : {}),
224
+ targets: [],
225
+ };
226
+ current.targets.push(...statusTargetPlacements(target));
227
+ groups.set(target.pluginId, current);
228
+ }
229
+ const allSourcesFailed = result.payload.catalog.sources.length > 0
230
+ && result.payload.catalog.sources.every((source) => source.error !== undefined);
231
+ return {
232
+ items: [...groups.values()].sort((left, right) => left.pluginName.localeCompare(right.pluginName)),
233
+ catalogUnavailable: allSourcesFailed,
234
+ status: result.payload,
235
+ };
236
+ }
237
+ export async function loadConsoleItems(options = {}, runtime = {}) {
238
+ return (await loadConsoleItemsResult(options, runtime)).items;
239
+ }
240
+ function projectStateInventoryError(error, env, cwd) {
241
+ const sanitized = sanitizeCatalogSourceError(error, env, [
242
+ getCodexHome(env),
243
+ getClaudeHome(env),
244
+ path.resolve(cwd),
245
+ ]);
246
+ const native = /(?:Codex|Claude|config\.toml|settings|installed_plugins)/iu.test(sanitized.message);
247
+ const code = native ? 'nativeStateUnreadable' : 'stateInventoryFailed';
248
+ return { code, message: `${code}: ${sanitized.message}`, relevance: { global: true } };
249
+ }
250
+ function inventoryErrorMatchesSelection(options) {
251
+ const relevance = options.error.relevance;
252
+ if (relevance.global)
253
+ return true;
254
+ if (relevance.projectLocationKey
255
+ && (!options.currentProjectLocationKey
256
+ || relevance.projectLocationKey !== options.currentProjectLocationKey))
257
+ return false;
258
+ if (options.platformExplicit && relevance.platform
259
+ && !options.platforms.includes(relevance.platform))
260
+ return false;
261
+ if (options.scopeExplicit && relevance.scope
262
+ && !options.scopes.includes(relevance.scope))
263
+ return false;
264
+ if (options.selectors.length === 0 || (!relevance.sourceId && !relevance.pluginName))
265
+ return true;
266
+ return options.selectors.some((selector) => (!relevance.pluginName || selector.parsed.pluginName === relevance.pluginName)
267
+ && (!relevance.sourceId
268
+ || selector.parsed.sourceId === undefined
269
+ || selector.parsed.sourceId === relevance.sourceId));
270
+ }
271
+ function finalizeTargetError(error, targetState) {
272
+ return {
273
+ ...error,
274
+ severity: error.code === 'artifactCollision'
275
+ || error.code === 'dependencyGraphInvalid'
276
+ || (targetState === 'error'
277
+ && error.dependencyPluginId === undefined)
278
+ ? 'blocking'
279
+ : 'warning',
280
+ };
281
+ }
282
+ function projectTargetError(error, env, cwd, targetState) {
283
+ const sanitized = sanitizeCatalogSourceError(new Error(error.message), env, [
284
+ getCodexHome(env),
285
+ getClaudeHome(env),
286
+ path.resolve(cwd),
287
+ ]);
288
+ return finalizeTargetError({ ...error, message: sanitized.message }, targetState);
289
+ }
290
+ function sourceRequestedRef(source, cliVersion) {
291
+ return source.type === 'git' ? resolveCatalogSourceRef(source.refPolicy, cliVersion) : 'path';
292
+ }
293
+ function selectedPlatforms(value) {
294
+ const selection = value === undefined ? 'both' : parsePlatformValue(value);
295
+ return selection === 'both' ? ['codex', 'claude'] : [selection];
296
+ }
297
+ function selectedScopes(value) {
298
+ return value === undefined ? ['user', 'project'] : [parseScopeValue(value)];
299
+ }
300
+ function emptyIntent() {
301
+ return {
302
+ schemaVersion: 2,
303
+ kind: 'aw-plugin-intents',
304
+ roots: [],
305
+ dependencyScopeOverrides: [],
306
+ };
307
+ }
308
+ function desiredTargetKey(pluginId, platform) {
309
+ return `${pluginId}\0${platform}`;
310
+ }
311
+ function calculateDesiredTargetStates(options) {
312
+ const desired = new Map();
313
+ const add = (pluginId, platform, scope, relation) => {
314
+ const key = desiredTargetKey(pluginId, platform);
315
+ const current = desired.get(key) ?? { scopes: new Set(), relation: 'none' };
316
+ current.scopes.add(scope);
317
+ if (relation === 'root' || (relation === 'dependency' && current.relation !== 'root')) {
318
+ current.relation = relation;
319
+ }
320
+ desired.set(key, current);
321
+ };
322
+ const byId = new Map(options.available.map((entry) => [
323
+ formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
324
+ entry,
325
+ ]));
326
+ for (const [scope, intent] of [
327
+ ['user', options.userIntent],
328
+ ['project', options.projectIntent],
329
+ ]) {
330
+ for (const root of intent.roots) {
331
+ for (const platform of root.platforms)
332
+ add(root.pluginId, platform, scope, 'root');
333
+ }
334
+ for (const platform of ['codex', 'claude']) {
335
+ const platformRoots = intent.roots.filter((root) => root.platforms.includes(platform) && byId.has(root.pluginId));
336
+ const closure = new Set();
337
+ const visit = (pluginId) => {
338
+ if (closure.has(pluginId))
339
+ return;
340
+ closure.add(pluginId);
341
+ const entry = byId.get(pluginId);
342
+ if (!entry)
343
+ return;
344
+ for (const dependency of entry.dependencies) {
345
+ visit(formatPluginId({ sourceId: entry.source.id, pluginName: dependency }));
346
+ }
347
+ };
348
+ for (const root of platformRoots)
349
+ visit(root.pluginId);
350
+ const nodes = [...closure].flatMap((pluginId) => {
351
+ const entry = byId.get(pluginId);
352
+ if (!entry || !entry.targets[platform].user && !entry.targets[platform].project)
353
+ return [];
354
+ const allowedScopes = [
355
+ ...(entry.targets[platform].project
356
+ && (platform !== 'codex' || options.codexProjectAllowed) ? ['project'] : []),
357
+ ...(entry.targets[platform].user ? ['user'] : []),
358
+ ];
359
+ return allowedScopes.length === 0 ? [] : [{
360
+ pluginId,
361
+ pluginName: entry.name,
362
+ platform,
363
+ relation: platformRoots.some((root) => root.pluginId === pluginId)
364
+ ? 'requested'
365
+ : 'dependency',
366
+ depth: platformRoots.some((root) => root.pluginId === pluginId) ? 0 : 1,
367
+ allowedScopes,
368
+ ...(scope === 'project'
369
+ && !platformRoots.some((root) => root.pluginId === pluginId)
370
+ && entry.states?.[platform]?.user?.state === 'present'
371
+ && !entry.states[platform]?.user?.errors.some((error) => error.severity === 'blocking')
372
+ ? { preferredScope: 'user', preferredScopeReason: 'existingWiderTarget' }
373
+ : {}),
374
+ }];
375
+ });
376
+ const nodeIds = new Set(nodes.map((node) => node.pluginId));
377
+ const roots = platformRoots.flatMap((root) => nodeIds.has(root.pluginId)
378
+ ? [{ pluginId: root.pluginId, platform, scope }]
379
+ : []);
380
+ if (roots.length === 0)
381
+ continue;
382
+ const edges = nodes.flatMap((node) => {
383
+ const entry = byId.get(node.pluginId);
384
+ return entry.dependencies.flatMap((dependency) => {
385
+ const dependencyId = formatPluginId({
386
+ sourceId: entry.source.id,
387
+ pluginName: dependency,
388
+ });
389
+ return nodeIds.has(dependencyId)
390
+ ? [{ from: node.pluginId, to: dependencyId, platform }]
391
+ : [];
392
+ });
393
+ });
394
+ const plan = createDependencyPlacementPlan({
395
+ requestedPluginIds: roots.map((root) => root.pluginId),
396
+ nodes,
397
+ roots,
398
+ dependencyEdges: edges,
399
+ scopeOverrides: intent.dependencyScopeOverrides.filter((override) => nodeIds.has(override.pluginId)
400
+ && (override.platform === undefined || override.platform === platform)),
401
+ });
402
+ for (const target of plan.targets) {
403
+ add(target.pluginId, target.platform, target.resolvedScope, target.relation === 'requested' ? 'root' : 'dependency');
404
+ }
405
+ }
406
+ }
407
+ return new Map([...desired].map(([key, value]) => [key, {
408
+ scopes: [...value.scopes].sort(),
409
+ relation: value.relation,
410
+ }]));
411
+ }
412
+ function projectDependencyClosureForTarget(options) {
413
+ const byId = new Map(options.available.map((entry) => [
414
+ formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
415
+ entry,
416
+ ]));
417
+ const closure = new Set();
418
+ const visit = (pluginId) => {
419
+ const entry = byId.get(pluginId);
420
+ if (!entry)
421
+ return;
422
+ for (const dependency of entry.dependencies) {
423
+ const dependencyId = formatPluginId({
424
+ sourceId: entry.source.id,
425
+ pluginName: dependency,
426
+ });
427
+ const dependencyEntry = byId.get(dependencyId);
428
+ if (!dependencyEntry
429
+ || (!dependencyEntry.targets[options.platform].user
430
+ && !dependencyEntry.targets[options.platform].project)
431
+ || closure.has(dependencyId)) {
432
+ continue;
433
+ }
434
+ closure.add(dependencyId);
435
+ visit(dependencyId);
436
+ }
437
+ };
438
+ visit(options.pluginId);
439
+ return closure;
440
+ }
441
+ export function statusRecovery(options) {
442
+ if (options.errorCodes?.includes('removedPluginCleanupRequired')) {
443
+ return [{
444
+ command: 'cleanup',
445
+ description: '整体清理已删除插件在两个平台、用户与当前项目中的安装、设置和遗留记录。',
446
+ }];
447
+ }
448
+ if (options.errorCodes?.some((code) => code === 'codexProjectPluginVersionTooLow'
449
+ || code === 'codexProjectPluginUnsupported'
450
+ || code === 'codexSystemCliUnsupported')) {
451
+ return [{
452
+ command: 'manual',
453
+ description: '升级或修复官方 system Codex CLI 后重试原操作。',
454
+ }];
455
+ }
456
+ if (options.errorCodes?.includes('awCapabilityUnsupported')) {
457
+ return [{
458
+ command: 'manual',
459
+ description: '升级 AW CLI 到支持插件所需 capability 的版本后重试。',
460
+ }];
461
+ }
462
+ if (options.errorCodes?.includes('dependencyGraphInvalid')) {
463
+ return [{
464
+ command: 'manual',
465
+ description: '修复 Catalog 中的插件依赖循环后重试。',
466
+ }];
467
+ }
468
+ if (options.state === 'ready' || options.state === 'absent')
469
+ return [];
470
+ if (options.desired.scopes.length === 0
471
+ && options.sharedNative?.state === 'replaceable'
472
+ && options.sharedNative.reason === 'damaged') {
473
+ return [
474
+ ...(options.actualEnabled ? [{
475
+ command: 'cleanup',
476
+ ...(options.scope ? { scope: options.scope } : {}),
477
+ description: `仅清理 ${options.scope ?? '当前'} scope 的激活;不会修复或删除损坏的共享内容。`,
478
+ }] : []),
479
+ {
480
+ command: 'manual',
481
+ description: `共享内容已损坏。先明确选择 user 或 project 使用范围,再运行 aw install ${options.pluginId} --platform codex --scope <user|project> 重建。`,
482
+ },
483
+ ];
484
+ }
485
+ if (options.state === 'orphaned') {
486
+ return [{ command: 'cleanup', description: '清理可证明属于 AW 的遗留输出。' }];
487
+ }
488
+ if (options.state === 'blocked' && options.errorCodes?.some((code) => code === 'sourceMissing'
489
+ || code === 'catalogSourceUnavailable'
490
+ || code === 'bundleUnavailable'
491
+ || code === 'codexIntentSourceUnavailable')) {
492
+ return [
493
+ { command: 'sync', description: '来源恢复后同步 desired intent。' },
494
+ { command: 'cleanup', description: '来源无法恢复时清理可证明属于 AW 的输出。' },
495
+ ];
496
+ }
497
+ if (options.state === 'blocked') {
498
+ if (options.desired.scopes.includes('user') && options.desired.scopes.includes('project')) {
499
+ return ['user', 'project'].flatMap((scope) => {
500
+ const retainedScope = scope === 'user' ? 'project' : 'user';
501
+ const retainedRoot = options.conflictRoots?.[retainedScope]?.[0];
502
+ if (!retainedRoot)
503
+ return [];
504
+ return (options.conflictRoots?.[scope] ?? []).map((rootPluginId) => ({
505
+ command: 'uninstall',
506
+ scope,
507
+ description: `运行 aw uninstall ${rootPluginId} --platform ${options.platform} --scope ${scope},再运行 aw sync ${retainedRoot} --platform ${options.platform} --scope ${retainedScope}。`,
508
+ }));
509
+ });
510
+ }
511
+ const collision = options.sharedNative?.state === 'blocked'
512
+ ? `Codex shared native ${options.sharedNative.pluginId}`
513
+ : `${options.pluginId} 的 foreign extension`;
514
+ return [
515
+ {
516
+ command: 'sync',
517
+ description: `先移除或重命名 ${collision},再运行 aw sync ${options.pluginId} --platform ${options.platform}。cleanup 会保留 foreign 内容,不会删除该冲突。`,
518
+ },
519
+ ];
520
+ }
521
+ if (options.dependencyMoves?.length) {
522
+ const rootScope = options.desired.scopes[0] ?? 'project';
523
+ const removeDependencies = options.dependencyMoves.map((move) => `aw cleanup ${move.pluginId} --platform ${options.platform} --scope ${move.fromScope}`);
524
+ const dependencyScopes = options.dependencyMoves.map((move) => `--dependency-scope ${move.pluginId}#${options.platform}=${move.toScope}`);
525
+ return [{
526
+ command: 'manual',
527
+ description: `先按依赖保护提示依次移除 ${options.dependencyMoves.map((move) => move.pluginId).join('、')} 的所有直接和间接依赖者;若命令报告 dependencyStillRequired,继续处理提示的其他依赖者。再运行 ${removeDependencies.join(',再运行 ')} 移除依赖旧位置。最后逐个按原平台和 scope 重新添加全部已移除 root,并在安装时选择新的依赖 scope;当前 root 的示例命令是 aw install ${options.pluginId} --platform ${options.platform} --scope ${rootScope} ${dependencyScopes.join(' ')}。`,
528
+ }];
529
+ }
530
+ return [{
531
+ command: options.errorCodes?.some((code) => code === 'codexSharedNativeCorrupt'
532
+ || code === 'codexActivationDrift'
533
+ || code === 'codexExtensionDrift') ? 'reinstall' : 'sync',
534
+ ...(options.desired.scopes.length === 1 ? { scope: options.desired.scopes[0] } : {}),
535
+ description: '同步 desired intent 和当前现场;现场损坏时使用重新安装修复。',
536
+ }];
537
+ }
538
+ function rootIntentsForTarget(options) {
539
+ const byId = new Map(options.available.map((entry) => [
540
+ formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
541
+ entry,
542
+ ]));
543
+ const result = {};
544
+ for (const [scope, intent] of [
545
+ ['user', options.userIntent],
546
+ ['project', options.projectIntent],
547
+ ]) {
548
+ const roots = intent.roots.filter((root) => {
549
+ if (!root.platforms.includes(options.platform))
550
+ return false;
551
+ const seen = new Set();
552
+ const reaches = (pluginId) => {
553
+ if (pluginId === options.pluginId)
554
+ return true;
555
+ if (seen.has(pluginId))
556
+ return false;
557
+ seen.add(pluginId);
558
+ const entry = byId.get(pluginId);
559
+ return entry?.dependencies.some((dependency) => reaches(formatPluginId({
560
+ sourceId: entry.source.id,
561
+ pluginName: dependency,
562
+ }))) === true;
563
+ };
564
+ return reaches(root.pluginId);
565
+ }).map((root) => root.pluginId).sort();
566
+ if (roots.length > 0)
567
+ result[scope] = roots;
568
+ }
569
+ return result;
570
+ }
571
+ function projectedLiveState(options) {
572
+ if (options.inspection.state === 'error'
573
+ || options.inspection.components.some((entry) => entry.state === 'error'))
574
+ return 'error';
575
+ const owned = options.inspection.components.filter((entry) => (entry.state === 'present' || entry.state === 'partial'));
576
+ if (owned.length === 0)
577
+ return 'absent';
578
+ if (owned.some((entry) => entry.state === 'partial'))
579
+ return 'partial';
580
+ const required = new Set(options.required);
581
+ const optional = new Set(options.optional);
582
+ if (options.inspection.components.some((entry) => entry.state === 'present' && !required.has(entry.component) && !optional.has(entry.component))) {
583
+ return 'partial';
584
+ }
585
+ if (!options.required.every((component) => options.inspection.components.some((entry) => entry.component === component && entry.state === 'present')))
586
+ return 'partial';
587
+ if (options.required.length > 0)
588
+ return 'present';
589
+ return options.optional.some((component) => options.inspection.components.some((entry) => entry.component === component && entry.state === 'present')) ? 'present' : 'absent';
590
+ }
591
+ export function projectTargetRevision(availableVersion, installedVersion) {
592
+ if (!availableVersion || !installedVersion
593
+ || !tryParseStrictSemVer(availableVersion)
594
+ || !tryParseStrictSemVer(installedVersion)) {
595
+ return {
596
+ state: 'unknown',
597
+ ...(availableVersion ? { availableVersion } : {}),
598
+ ...(installedVersion ? { installedVersion } : {}),
599
+ };
600
+ }
601
+ const relation = compareStrictSemVer(installedVersion, availableVersion);
602
+ if (relation === 0)
603
+ return { state: 'current', availableVersion, installedVersion };
604
+ if (relation < 0)
605
+ return { state: 'upgradeAvailable', availableVersion, installedVersion };
606
+ return { state: 'unknown', availableVersion, installedVersion };
607
+ }
608
+ function renderStatusV8(payload, verbose) {
609
+ const lines = [`Catalog sources: ${payload.catalog.sources.length}`];
610
+ for (const source of payload.catalog.sources) {
611
+ lines.push(`${source.primary ? '*' : '-'} ${source.id}: ${source.error ?? source.freshness ?? 'unavailable'}`);
612
+ }
613
+ for (const target of payload.targets) {
614
+ const reasons = target.reasons.length > 0
615
+ ? ` [${target.reasons.map((reason) => reason.message.startsWith(`${reason.code}:`)
616
+ ? reason.message : `${reason.code}: ${reason.message}`).join('; ')}]`
617
+ : '';
618
+ if (target.platform === 'claude') {
619
+ lines.push(`${target.pluginId} ${target.platform} (${target.scope}): ${target.state}${reasons}`);
620
+ }
621
+ else {
622
+ lines.push(`${target.pluginId} ${target.platform}: ${target.state}${reasons}`);
623
+ const desiredScopes = target.placements.filter((placement) => placement.components.some((component) => component.kind === 'intent' && component.metadata?.enabled === true))
624
+ .map((placement) => placement.scope);
625
+ const actualScopes = target.placements.filter((placement) => placement.components.some((component) => component.kind === 'activation'
626
+ && component.key === placement.scope
627
+ && component.state === 'enabled'))
628
+ .map((placement) => placement.scope);
629
+ const usage = (scopes) => scopes.length === 0
630
+ ? 'disabled'
631
+ : scopes.length === 2 ? 'user+project' : scopes[0];
632
+ lines.push(` desired use: ${usage(desiredScopes)}`);
633
+ lines.push(` actual use: ${usage(actualScopes)}`);
634
+ const shared = target.components.find((component) => component.kind === 'sharedNative');
635
+ if (shared)
636
+ lines.push(` shared content: ${shared.state} (${shared.key})`);
637
+ for (const placement of target.placements) {
638
+ lines.push(` ${placement.scope}: ${placement.state}`);
639
+ }
640
+ }
641
+ if (verbose) {
642
+ for (const component of target.components) {
643
+ lines.push(` component ${component.kind}/${component.key}: ${component.state}`);
644
+ }
645
+ if (target.platform === 'codex') {
646
+ for (const placement of target.placements) {
647
+ lines.push(` placement ${placement.scope}: ${placement.state}`);
648
+ for (const component of placement.components) {
649
+ lines.push(` component ${component.kind}/${component.key}: ${component.state}`);
650
+ }
651
+ }
652
+ }
653
+ for (const action of target.recoveryActions) {
654
+ lines.push(` recovery ${action.command}: ${action.description}`);
655
+ }
656
+ }
657
+ }
658
+ for (const issue of payload.configIssues ?? []) {
659
+ lines.push(`Warning: ${issue.pluginId} config ${issue.key} has an unsupported project override; user/default is effective. Unset the project value.`);
660
+ }
661
+ for (const error of payload.errors)
662
+ lines.push(`Error: ${error.message}`);
663
+ return lines.join('\n');
664
+ }
665
+ function collisionMessage(collision) {
666
+ const reason = {
667
+ ownerMismatch: '已有内容属于其他 owner',
668
+ unownedContent: '已有内容没有 AW owner 标记',
669
+ typeMismatch: '已有内容类型与目标不匹配',
670
+ }[collision.reason];
671
+ return `artifactCollision: ${collision.artifactKind} ${collision.artifactKey}: ${reason}。请移除或迁移冲突内容后重试。`;
672
+ }
673
+ function collisionRootIssueId(options) {
674
+ return [
675
+ 'artifactCollision',
676
+ options.pluginId,
677
+ options.platform,
678
+ options.scope,
679
+ options.collision.artifactKind,
680
+ options.collision.artifactKey,
681
+ ].join(':');
682
+ }
683
+ async function statusCommandV8InSession(options) {
684
+ const env = options.env ?? process.env;
685
+ const dependencyPluginCache = new Map();
686
+ const dependencyInspectionCache = new Map();
687
+ const cliVersion = options.cliVersion ?? assertStrictSemVer(JSON.parse(fs.readFileSync(path.join(resolveCliPackageRoot(), 'package.json'), 'utf8')).version, 'packages/cli/package.json version');
688
+ const snapshot = await readCatalogSourcesConfigSnapshot(env);
689
+ const intentErrors = [];
690
+ const readIntent = async (scope) => {
691
+ const observation = await observePluginIntentState({ scope, cwd: options.cwd, env });
692
+ if (observation.state === 'invalid' || observation.state === 'unavailable') {
693
+ intentErrors.push({
694
+ code: 'pluginIntentStateInvalid',
695
+ message: `pluginIntentStateInvalid: ${scope} plugin intent state is invalid.`,
696
+ });
697
+ }
698
+ return observation;
699
+ };
700
+ const [userIntentObservation, initialProjectIntentObservation] = await Promise.all([
701
+ readIntent('user'),
702
+ readIntent('project'),
703
+ ]);
704
+ const userIntent = userIntentObservation.state === 'ready'
705
+ ? userIntentObservation.value : emptyIntent();
706
+ let projectIntentObservation = initialProjectIntentObservation;
707
+ let projectIntent = projectIntentObservation.state === 'ready'
708
+ ? projectIntentObservation.value : emptyIntent();
709
+ const codexConfigErrors = [];
710
+ const readActivationConfig = async (scope) => {
711
+ try {
712
+ return await readCodexConfigFile(resolveCodexPaths(options.cwd, scope, env).configTomlPath);
713
+ }
714
+ catch {
715
+ codexConfigErrors.push({
716
+ scope,
717
+ code: 'codexActivationDrift',
718
+ message: `codexActivationDrift: ${scope} Codex activation config is unreadable.`,
719
+ });
720
+ return undefined;
721
+ }
722
+ };
723
+ const codexScopePathsAlias = codexProjectConfigAliasesUserHome(options.cwd, env);
724
+ const [userCodexConfig, projectCodexConfig] = await Promise.all([
725
+ readActivationConfig('user'),
726
+ codexScopePathsAlias ? undefined : readActivationConfig('project'),
727
+ ]);
728
+ let projectRoot;
729
+ try {
730
+ projectRoot = await resolveCanonicalRepoProjectKey(options.cwd);
731
+ }
732
+ catch (error) {
733
+ if (error instanceof Error && error.name === 'AbortError')
734
+ throw error;
735
+ projectIntentObservation = {
736
+ state: 'unavailable',
737
+ code: 'pluginIntentStateUnavailable',
738
+ message: '无法确定当前项目位置,不能读取插件声明。',
739
+ };
740
+ projectIntent = emptyIntent();
741
+ if (!intentErrors.some((error) => error.message.includes('project plugin intent'))) {
742
+ intentErrors.push({
743
+ code: 'pluginIntentStateInvalid',
744
+ message: 'pluginIntentStateInvalid: project plugin intent state is unavailable.',
745
+ });
746
+ }
747
+ }
748
+ const currentProjectKey = projectRoot;
749
+ const currentProjectLocationKey = currentProjectKey
750
+ ? createProjectLocationKey(currentProjectKey) : undefined;
751
+ const inventoryErrors = [];
752
+ const readInventory = options.inventoryCatalogSourceReferences
753
+ ?? inventoryCatalogSourceReferences;
754
+ const ownerInventory = await readInventory({ cwd: options.cwd, env }).catch(async (error) => {
755
+ inventoryErrors.push(projectStateInventoryError(error, env, options.cwd));
756
+ return inventoryLegacyOwnerReferences({ cwd: options.cwd, env }).catch((fallbackError) => {
757
+ inventoryErrors.push(projectStateInventoryError(fallbackError, env, options.cwd));
758
+ return { inventorySchemaVersion: 1, references: [], errors: [] };
759
+ });
760
+ });
761
+ for (const error of ownerInventory.errors ?? []) {
762
+ const code = error.kind === 'nativeStateRead' ? 'nativeStateUnreadable' : 'stateInventoryFailed';
763
+ inventoryErrors.push({
764
+ code,
765
+ message: `${code}: ${error.kind}@${error.location}: ${error.message}`,
766
+ relevance: error.relevance,
767
+ });
768
+ }
769
+ const nativeCliRunner = options.nativeCliRunner ?? getDefaultNativeCliRunner();
770
+ const codexSystemConsumerInspections = new Map();
771
+ const inspectCodexSystemConsumer = (scope) => {
772
+ let inspection = codexSystemConsumerInspections.get(scope);
773
+ if (!inspection) {
774
+ inspection = inspectSystemCodex({
775
+ runner: nativeCliRunner,
776
+ cwd: options.cwd,
777
+ env,
778
+ operationRequirement: getCodexOperationRequirement(scope),
779
+ });
780
+ codexSystemConsumerInspections.set(scope, inspection);
781
+ }
782
+ return inspection;
783
+ };
784
+ const codexRegistrationCache = new Map();
785
+ const inspectCodexRegistration = async (pluginId, scope) => {
786
+ const consumer = await inspectCodexSystemConsumer(scope);
787
+ if (consumer.state !== 'compatible') {
788
+ return {
789
+ observation: { state: 'unobserved' },
790
+ observations: { user: false, project: false },
791
+ activations: {},
792
+ };
793
+ }
794
+ let inspection = codexRegistrationCache.get(pluginId);
795
+ if (!inspection) {
796
+ inspection = inspectCodexPluginRegistrationLive({
797
+ pluginId,
798
+ cwd: options.cwd,
799
+ env,
800
+ nativeCliRunner,
801
+ scope: options.scope === 'user' ? 'user' : 'both',
802
+ observationSession: options.codexObservationSession,
803
+ });
804
+ codexRegistrationCache.set(pluginId, inspection);
805
+ }
806
+ return inspection;
807
+ };
808
+ const nativeProbeCache = new Map();
809
+ const codexDesiredUserActivationIds = new Set();
810
+ const readOnlyNativeProbe = (probe) => async () => {
811
+ const key = [
812
+ probe.sourceIdentity,
813
+ probe.pluginName,
814
+ probe.platform,
815
+ probe.scope,
816
+ probe.marketplaceName,
817
+ String(probe.desired),
818
+ ].join('\0');
819
+ let value = nativeProbeCache.get(key);
820
+ if (!value) {
821
+ const hasLocalResidue = ownerInventory.references.some((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
822
+ && reference.sourceId === probe.sourceId
823
+ && reference.pluginName === probe.pluginName
824
+ && reference.platform === probe.platform);
825
+ value = probe.platform === 'codex'
826
+ ? inspectCodexRegistration(`${probe.pluginName}@${probe.marketplaceName}`, options.scope === undefined ? probe.scope : scopes[0]).then((registration) => {
827
+ if (registration.observation.state === 'failed') {
828
+ throw new Error('codexNativeObservationFailed: status requires Codex plugin list evidence.');
829
+ }
830
+ if (registration.observation.state === 'unobserved') {
831
+ return probe.desired || hasLocalResidue ? 'partial' : 'absent';
832
+ }
833
+ if (registration.observation.value === 'absent')
834
+ return 'absent';
835
+ if (!userCodexConfig || (probe.scope === 'project' && !projectCodexConfig)) {
836
+ return 'partial';
837
+ }
838
+ const configEnabled = (probe.scope === 'user'
839
+ ? userCodexConfig
840
+ : projectCodexConfig)?.snapshot.plugins[`${probe.pluginName}@${probe.marketplaceName}`]?.enabled === true;
841
+ return configEnabled
842
+ ? 'present'
843
+ : 'partial';
844
+ })
845
+ : Promise.resolve(ownerInventory.references.some((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
846
+ && reference.sourceId === probe.sourceId
847
+ && reference.sourceIdentity === probe.sourceIdentity
848
+ && reference.pluginName === probe.pluginName
849
+ && reference.platform === probe.platform
850
+ && reference.scope === probe.scope
851
+ && (probe.scope === 'user' || reference.projectKey === currentProjectKey))
852
+ ? 'present'
853
+ : 'absent');
854
+ nativeProbeCache.set(key, value);
855
+ }
856
+ return value;
857
+ };
858
+ const hasCurrentCodexProjectOwner = (sourceId, pluginName) => ownerInventory.references.some((reference) => reference.kind === 'namespacedOwner'
859
+ && reference.sourceId === sourceId
860
+ && reference.pluginName === pluginName
861
+ && reference.platform === 'codex'
862
+ && reference.scope === 'project'
863
+ && reference.projectKey === currentProjectKey);
864
+ const configured = new Map(snapshot.config.sources.map((source) => [source.id, source]));
865
+ const requested = options.plugins ?? [];
866
+ const platforms = selectedPlatforms(options.platform);
867
+ const scopes = selectedScopes(options.scope);
868
+ const selectorErrors = [];
869
+ const parsedSelectors = [];
870
+ const plannedSelectors = [];
871
+ const liveOnlySelectors = [];
872
+ for (const selector of requested) {
873
+ let parsed;
874
+ try {
875
+ parsed = parsePluginId(selector);
876
+ }
877
+ catch (error) {
878
+ selectorErrors.push({
879
+ code: 'invalidPluginSelector',
880
+ message: error instanceof Error ? error.message : String(error),
881
+ });
882
+ continue;
883
+ }
884
+ parsedSelectors.push({ raw: selector, parsed });
885
+ if (parsed.sourceId !== undefined && !configured.has(parsed.sourceId)) {
886
+ const hasLiveReference = ownerInventory.references.some((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
887
+ && reference.sourceId === parsed.sourceId
888
+ && reference.pluginName === parsed.pluginName
889
+ && platforms.includes(reference.platform)
890
+ && scopes.includes(reference.scope)
891
+ && (reference.scope !== 'project' || reference.projectKey === currentProjectKey));
892
+ if (hasLiveReference) {
893
+ liveOnlySelectors.push({ raw: selector, parsed });
894
+ }
895
+ else if (!inventoryErrors.some((error) => inventoryErrorMatchesSelection({
896
+ error,
897
+ selectors: [{ raw: selector, parsed }],
898
+ platformExplicit: options.platform !== undefined,
899
+ scopeExplicit: options.scope !== undefined,
900
+ platforms,
901
+ scopes,
902
+ currentProjectLocationKey,
903
+ }))) {
904
+ selectorErrors.push({
905
+ code: 'pluginNotFound',
906
+ message: `Plugin "${selector}" was not found because catalog source "${parsed.sourceId}" is not configured.`,
907
+ });
908
+ }
909
+ continue;
910
+ }
911
+ plannedSelectors.push({ raw: selector, parsed });
912
+ }
913
+ const selectedInventoryErrors = inventoryErrors.filter((error) => inventoryErrorMatchesSelection({
914
+ error,
915
+ selectors: parsedSelectors,
916
+ platformExplicit: options.platform !== undefined,
917
+ scopeExplicit: options.scope !== undefined,
918
+ platforms,
919
+ scopes,
920
+ currentProjectLocationKey,
921
+ }));
922
+ const plannedSourceIds = requested.length === 0
923
+ ? undefined
924
+ : planPluginSelectorSourceIds(plannedSelectors.map((selector) => selector.parsed));
925
+ const selectedConfiguredSources = plannedSourceIds === undefined
926
+ ? snapshot.config.sources
927
+ : plannedSourceIds.map((sourceId) => configured.get(sourceId));
928
+ const identityEntries = await Promise.all(selectedConfiguredSources.map(async (source) => {
929
+ try {
930
+ return [source.id, { identity: await calculateCatalogSourceIdentity(source) }];
931
+ }
932
+ catch (error) {
933
+ const sanitized = sanitizeCatalogSourceError(error, env);
934
+ return [source.id, {
935
+ error: sanitized.message,
936
+ }];
937
+ }
938
+ }));
939
+ const identities = new Map(identityEntries);
940
+ const catalog = await withResolvedMultiSourceCatalog({
941
+ cliVersion,
942
+ configSnapshot: snapshot,
943
+ ...(plannedSourceIds === undefined ? {} : { sourceIds: plannedSourceIds }),
944
+ ...(options.catalogOperationContext
945
+ ? { operationContext: options.catalogOperationContext }
946
+ : {}),
947
+ env,
948
+ consume: async (resolution) => ({
949
+ primarySourceId: resolution.primarySourceId,
950
+ configDigest: resolution.configDigest,
951
+ compositeDigest: resolution.compositeDigest,
952
+ sources: await Promise.all(resolution.sources.map(async (item) => {
953
+ const source = configured.get(item.sourceId);
954
+ const identity = identities.get(item.sourceId);
955
+ const base = {
956
+ id: item.sourceId,
957
+ identity: identity.identity ?? 'unavailable',
958
+ type: source.type,
959
+ primary: source.primary,
960
+ requestedRef: item.resolution?.requestedRef ?? sourceRequestedRef(source, cliVersion),
961
+ };
962
+ if (identity.error || item.error) {
963
+ const error = item.error ?? new Error(identity.error);
964
+ return {
965
+ ...base,
966
+ error: [identity.error, item.error?.message].filter(Boolean).join('; '),
967
+ errorCode: catalogSourceErrorCode(error),
968
+ };
969
+ }
970
+ try {
971
+ const catalogEntriesByName = new Map(item.resolution.manifest.entries.map((entry) => [
972
+ entry.name,
973
+ entry,
974
+ ]));
975
+ const cyclicDependencyPluginNames = new Set();
976
+ const dependencyVisitState = new Map();
977
+ const dependencyVisitStack = [];
978
+ const visitDependencyGraph = (pluginName) => {
979
+ const state = dependencyVisitState.get(pluginName);
980
+ if (state === 'visited')
981
+ return;
982
+ if (state === 'visiting') {
983
+ const cycleStart = dependencyVisitStack.lastIndexOf(pluginName);
984
+ for (const name of dependencyVisitStack.slice(cycleStart)) {
985
+ cyclicDependencyPluginNames.add(name);
986
+ }
987
+ return;
988
+ }
989
+ dependencyVisitState.set(pluginName, 'visiting');
990
+ dependencyVisitStack.push(pluginName);
991
+ for (const dependencyName of catalogEntriesByName.get(pluginName)?.dependencies ?? []) {
992
+ if (catalogEntriesByName.has(dependencyName))
993
+ visitDependencyGraph(dependencyName);
994
+ }
995
+ dependencyVisitStack.pop();
996
+ dependencyVisitState.set(pluginName, 'visited');
997
+ };
998
+ for (const pluginName of catalogEntriesByName.keys())
999
+ visitDependencyGraph(pluginName);
1000
+ const placementEntries = item.resolution.manifest.entries.map((entry) => {
1001
+ const supportedPlatforms = resolveCatalogEntrySupportedPlatforms(entry.policy);
1002
+ return {
1003
+ name: entry.name,
1004
+ dependencies: entry.dependencies,
1005
+ source: { id: item.resolution.sourceId },
1006
+ targets: {
1007
+ codex: {
1008
+ user: supportedPlatforms.has('codex'),
1009
+ project: supportedPlatforms.has('codex'),
1010
+ },
1011
+ claude: {
1012
+ user: supportedPlatforms.has('claude'),
1013
+ project: supportedPlatforms.has('claude'),
1014
+ },
1015
+ },
1016
+ };
1017
+ });
1018
+ const sourceDesired = calculateDesiredTargetStates({
1019
+ userIntent,
1020
+ projectIntent,
1021
+ available: placementEntries,
1022
+ codexProjectAllowed: !codexScopePathsAlias,
1023
+ });
1024
+ const registeredNames = canonicalMarketplaceRegistrationNames(ownerInventory.references, item.resolution.sourceId);
1025
+ if (registeredNames.length > 1) {
1026
+ throw new Error('marketplaceIdentityUnavailable: Multiple canonical native marketplace registrations match the source.');
1027
+ }
1028
+ const desiredMarketplaceName = registeredNames[0]
1029
+ ?? (item.resolution.sourceId === resolution.primarySourceId
1030
+ ? 'aw'
1031
+ : `aw-${item.resolution.sourceId}`);
1032
+ for (const entry of placementEntries) {
1033
+ const pluginId = formatPluginId({
1034
+ sourceId: item.resolution.sourceId,
1035
+ pluginName: entry.name,
1036
+ });
1037
+ if (sourceDesired.get(desiredTargetKey(pluginId, 'codex'))?.scopes.includes('user')) {
1038
+ codexDesiredUserActivationIds.add(`${entry.name}@${desiredMarketplaceName}`);
1039
+ }
1040
+ }
1041
+ const plugins = await Promise.all(item.resolution.manifest.entries.map(async (entry) => {
1042
+ const capabilitySupport = checkAwCapabilitySupport(entry.requires.aw.capabilities ?? [], IMPLEMENTED_AW_CAPABILITIES);
1043
+ if (!capabilitySupport.supported) {
1044
+ const supportedPlatforms = resolveCatalogEntrySupportedPlatforms(entry.policy);
1045
+ const states = {};
1046
+ const message = `awCapabilityUnsupported: ${item.resolution.sourceId}/${entry.name} requires unsupported AW capabilities: ${capabilitySupport.missing.join(', ')}.`;
1047
+ for (const platform of ['codex', 'claude']) {
1048
+ if (!supportedPlatforms.has(platform))
1049
+ continue;
1050
+ states[platform] = {};
1051
+ for (const scope of ['user', 'project']) {
1052
+ states[platform][scope] = {
1053
+ state: 'error',
1054
+ components: [],
1055
+ errors: [finalizeTargetError({ code: 'awCapabilityUnsupported', message }, 'error')],
1056
+ };
1057
+ }
1058
+ }
1059
+ return {
1060
+ name: entry.name,
1061
+ version: entry.version,
1062
+ displayName: entry.interface?.displayName ?? entry.name,
1063
+ shortDescription: entry.interface?.shortDescription ?? entry.description,
1064
+ description: entry.description,
1065
+ targets: {
1066
+ claude: {
1067
+ user: supportedPlatforms.has('claude'),
1068
+ project: supportedPlatforms.has('claude'),
1069
+ },
1070
+ codex: {
1071
+ user: supportedPlatforms.has('codex'),
1072
+ project: supportedPlatforms.has('codex'),
1073
+ },
1074
+ },
1075
+ states,
1076
+ dependencies: entry.dependencies,
1077
+ missingCapabilities: capabilitySupport.missing,
1078
+ };
1079
+ }
1080
+ const plugin = await readPluginManifest(path.join(item.resolution.rootDir, 'plugins', entry.name), { mode: 'bundle' });
1081
+ const claude = supportsPlatform(plugin.manifest, 'claude');
1082
+ const codex = supportsPlatform(plugin.manifest, 'codex');
1083
+ const codexSurface = analyzeCodexSurface(plugin.manifest);
1084
+ plugin.sourceId = item.resolution.sourceId;
1085
+ plugin.sourceIdentity = item.resolution.sourceIdentity;
1086
+ plugin.catalogLogicalIdentity = item.resolution.logicalIdentity;
1087
+ plugin.pluginId = formatPluginId({ sourceId: item.resolution.sourceId, pluginName: entry.name });
1088
+ let configIssues;
1089
+ let configDiagnostic;
1090
+ if (plugin.manifest.config?.fields) {
1091
+ const issues = new Map();
1092
+ for (const scope of scopes) {
1093
+ try {
1094
+ const resolved = scope === 'project'
1095
+ ? await resolveProjectArtifactRenderConfig({
1096
+ sourceId: plugin.sourceId,
1097
+ sourceIdentity: plugin.sourceIdentity,
1098
+ logicalIdentity: plugin.catalogLogicalIdentity,
1099
+ pluginName: plugin.manifest.name,
1100
+ manifest: plugin.manifest,
1101
+ cwd: options.cwd,
1102
+ env,
1103
+ })
1104
+ : await resolveEffectivePluginConfig({
1105
+ sourceId: plugin.sourceId,
1106
+ sourceIdentity: plugin.sourceIdentity,
1107
+ logicalIdentity: plugin.catalogLogicalIdentity,
1108
+ pluginName: plugin.manifest.name,
1109
+ manifest: plugin.manifest,
1110
+ targetScope: 'user',
1111
+ cwd: options.cwd,
1112
+ env,
1113
+ });
1114
+ for (const issue of resolved.issues) {
1115
+ const source = issue.source ?? 'missing';
1116
+ const configIssue = {
1117
+ scope,
1118
+ type: issue.type,
1119
+ key: issue.key,
1120
+ title: plugin.manifest.config.fields[issue.key]?.title ?? issue.key,
1121
+ source,
1122
+ };
1123
+ issues.set(`${scope}\0${configIssue.type}\0${configIssue.key}\0${configIssue.source}`, configIssue);
1124
+ }
1125
+ for (const override of resolved.unsupportedLayerOverrides) {
1126
+ const configIssue = {
1127
+ scope,
1128
+ type: override.type,
1129
+ key: override.key,
1130
+ title: plugin.manifest.config.fields[override.key]?.title ?? override.key,
1131
+ source: override.source,
1132
+ };
1133
+ issues.set(`${scope}\0${configIssue.type}\0${configIssue.key}\0${configIssue.source}`, configIssue);
1134
+ }
1135
+ }
1136
+ catch {
1137
+ configDiagnostic ??= {
1138
+ scope,
1139
+ code: 'configReadFailed',
1140
+ message: '插件设置当前不可读。未读取或显示设置值。',
1141
+ };
1142
+ }
1143
+ }
1144
+ configIssues = [...issues.values()];
1145
+ }
1146
+ const states = {};
1147
+ const defaultMarketplaceName = item.resolution.sourceId === resolution.primarySourceId
1148
+ ? 'aw'
1149
+ : `aw-${item.resolution.sourceId}`;
1150
+ const marketplaceNameFor = (pluginName, platform, scope) => {
1151
+ const liveName = ownerInventory.references.find((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
1152
+ && reference.sourceId === item.resolution.sourceId
1153
+ && reference.sourceIdentity === item.resolution.sourceIdentity
1154
+ && reference.pluginName === pluginName
1155
+ && reference.platform === platform
1156
+ && reference.scope === scope
1157
+ && (scope === 'user' || reference.projectKey === currentProjectKey)
1158
+ && reference.marketplaceName)?.marketplaceName;
1159
+ if (liveName)
1160
+ return liveName;
1161
+ const registeredNames = canonicalMarketplaceRegistrationNames(ownerInventory.references, item.resolution.sourceId);
1162
+ if (registeredNames.length > 1) {
1163
+ throw new Error('marketplaceIdentityUnavailable: Multiple canonical native marketplace registrations match the source.');
1164
+ }
1165
+ return registeredNames[0] ?? defaultMarketplaceName;
1166
+ };
1167
+ const marketplaceRoot = path.join(resolveAwHome(env), 'marketplaces', item.resolution.sourceId);
1168
+ for (const platform of ['codex', 'claude']) {
1169
+ states[platform] = {};
1170
+ for (const scope of ['user', 'project']) {
1171
+ if (platform === 'codex'
1172
+ && scope === 'project'
1173
+ && codexScopePathsAlias
1174
+ && !hasCurrentCodexProjectOwner(item.resolution.sourceId, entry.name))
1175
+ continue;
1176
+ const supported = platform === 'claude'
1177
+ ? claude
1178
+ : codex && codexSurface.ok;
1179
+ if (!supported)
1180
+ continue;
1181
+ const changedOwner = ownerInventory.references.find((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
1182
+ && reference.sourceId === item.resolution.sourceId
1183
+ && reference.pluginName === entry.name
1184
+ && reference.platform === platform
1185
+ && reference.scope === scope
1186
+ && (scope === 'user' || reference.projectKey === currentProjectKey)
1187
+ && reference.sourceIdentity
1188
+ && reference.sourceIdentity !== item.resolution.sourceIdentity);
1189
+ if (changedOwner) {
1190
+ states[platform][scope] = {
1191
+ state: 'error',
1192
+ components: [],
1193
+ errors: [finalizeTargetError({
1194
+ code: 'sourceChanged',
1195
+ message: `sourceChanged: owner at ${changedOwner.location} has a different source identity.`,
1196
+ }, 'error')],
1197
+ };
1198
+ continue;
1199
+ }
1200
+ try {
1201
+ const marketplaceName = marketplaceNameFor(entry.name, platform, scope);
1202
+ const inspected = await inspectRebuildTarget({
1203
+ sourceId: item.resolution.sourceId,
1204
+ sourceIdentity: item.resolution.sourceIdentity,
1205
+ pluginId: plugin.pluginId,
1206
+ marketplaceName,
1207
+ marketplaceRoot,
1208
+ plugin,
1209
+ platform,
1210
+ scope,
1211
+ cwd: options.cwd,
1212
+ catalog: {
1213
+ rootDir: item.resolution.rootDir,
1214
+ source: 'local',
1215
+ },
1216
+ context: {
1217
+ env,
1218
+ nativeCliRunner,
1219
+ reporter: createNoopReporter(),
1220
+ debugLogger: createNoopDebugLogger(),
1221
+ codexObservationSession: options.codexObservationSession,
1222
+ },
1223
+ userActivationDesired: codexDesiredUserActivationIds,
1224
+ nativeProbe: readOnlyNativeProbe({
1225
+ pluginName: entry.name,
1226
+ sourceId: item.resolution.sourceId,
1227
+ sourceIdentity: item.resolution.sourceIdentity,
1228
+ platform,
1229
+ scope,
1230
+ marketplaceName,
1231
+ marketplaceRoot,
1232
+ desired: sourceDesired.get(desiredTargetKey(plugin.pluginId, platform))
1233
+ ?.scopes.includes(scope) === true,
1234
+ }),
1235
+ shallow: true,
1236
+ });
1237
+ const liveState = projectedLiveState({
1238
+ inspection: inspected.inspection,
1239
+ required: inspected.target.desiredOwnedComponents ?? inspected.target.ownedComponents,
1240
+ optional: inspected.target.optionalOwnedComponents ?? [],
1241
+ });
1242
+ const collisionErrors = inspected.inspection.components.flatMap((component) => component.collision ? [finalizeTargetError({
1243
+ code: 'artifactCollision',
1244
+ message: collisionMessage(component.collision),
1245
+ collision: component.collision,
1246
+ rootIssueId: collisionRootIssueId({
1247
+ pluginId: formatPluginId({
1248
+ sourceId: item.resolution.sourceId,
1249
+ pluginName: entry.name,
1250
+ }),
1251
+ platform,
1252
+ scope,
1253
+ collision: component.collision,
1254
+ }),
1255
+ rootIssueCode: 'artifactCollision',
1256
+ }, liveState)] : []);
1257
+ const dependencyErrors = [];
1258
+ const dependencyReadiness = [];
1259
+ const directDependencies = plugin.manifest.dependencies ?? [];
1260
+ const desiredInScope = sourceDesired.get(desiredTargetKey(plugin.pluginId, platform))?.scopes.includes(scope) === true;
1261
+ const codexPluginId = `${entry.name}@${marketplaceName}`;
1262
+ const actualCodexActivation = platform === 'codex'
1263
+ && (scope === 'user' ? userCodexConfig : projectCodexConfig)
1264
+ ?.snapshot.plugins[codexPluginId]?.enabled === true;
1265
+ const hasScopedExtensionResidue = platform === 'codex'
1266
+ && inspected.inspection.components.some((component) => component.component.kind !== 'native-plugin'
1267
+ && !component.component.identity.artifactKey.startsWith('activation-')
1268
+ && !component.component.identity.artifactKey.startsWith('marketplace-')
1269
+ && (component.state !== 'absent' || component.collision !== undefined));
1270
+ const dependencyPriority = {
1271
+ ready: 5,
1272
+ blockedByCollision: 4,
1273
+ incomplete: 3,
1274
+ error: 2,
1275
+ absent: 1,
1276
+ };
1277
+ function dependencyPlacementsFor(dependencyId, consumerScope) {
1278
+ const dependencyOverride = (consumerScope === 'project'
1279
+ ? projectIntent
1280
+ : userIntent).dependencyScopeOverrides.find((override) => override.pluginId === dependencyId
1281
+ && (override.platform === undefined || override.platform === platform));
1282
+ return dependencyOverride
1283
+ ? [dependencyOverride.scope]
1284
+ : consumerScope === 'project' ? ['project', 'user'] : ['user'];
1285
+ }
1286
+ async function inspectDependencyAtScope(dependencyName, dependencyScope) {
1287
+ const dependencyId = formatPluginId({
1288
+ sourceId: item.resolution.sourceId,
1289
+ pluginName: dependencyName,
1290
+ });
1291
+ const inspectionCacheKey = [
1292
+ item.resolution.sourceIdentity,
1293
+ dependencyId,
1294
+ platform,
1295
+ dependencyScope,
1296
+ dependencyScope === 'project' ? currentProjectKey : '',
1297
+ ].join('\0');
1298
+ if (cyclicDependencyPluginNames.has(dependencyName)) {
1299
+ return {
1300
+ state: 'error',
1301
+ dependencyScope,
1302
+ rootIssueId: `dependencyGraphInvalid:${dependencyId}`,
1303
+ rootIssueCode: 'dependencyGraphInvalid',
1304
+ issuePluginId: dependencyId,
1305
+ issueScope: dependencyScope,
1306
+ };
1307
+ }
1308
+ const cached = dependencyInspectionCache.get(inspectionCacheKey);
1309
+ if (cached)
1310
+ return cached;
1311
+ const inspection = (async () => {
1312
+ const dependencyEntry = item.resolution.manifest.entries.find((candidate) => candidate.name === dependencyName);
1313
+ if (!dependencyEntry) {
1314
+ return {
1315
+ state: 'absent',
1316
+ dependencyScope,
1317
+ rootIssueId: `dependencyMissing:${dependencyId}:${platform}:${dependencyScope}`,
1318
+ rootIssueCode: 'dependencyMissing',
1319
+ issuePluginId: dependencyId,
1320
+ issueScope: dependencyScope,
1321
+ };
1322
+ }
1323
+ const dependencySupport = checkAwCapabilitySupport(dependencyEntry.requires.aw.capabilities ?? [], IMPLEMENTED_AW_CAPABILITIES);
1324
+ if (!dependencySupport.supported) {
1325
+ return {
1326
+ state: 'error',
1327
+ dependencyScope,
1328
+ rootIssueId: `awCapabilityUnsupported:${dependencyId}`,
1329
+ rootIssueCode: 'awCapabilityUnsupported',
1330
+ issuePluginId: dependencyId,
1331
+ issueScope: dependencyScope,
1332
+ missingCapabilities: dependencySupport.missing,
1333
+ };
1334
+ }
1335
+ const pluginCacheKey = [item.resolution.sourceIdentity, dependencyId].join('\0');
1336
+ let dependencyPluginPromise = dependencyPluginCache.get(pluginCacheKey);
1337
+ if (!dependencyPluginPromise) {
1338
+ dependencyPluginPromise = readPluginManifest(path.join(item.resolution.rootDir, 'plugins', dependencyName), { mode: 'bundle' }).then((dependencyPlugin) => {
1339
+ dependencyPlugin.sourceId = item.resolution.sourceId;
1340
+ dependencyPlugin.sourceIdentity = item.resolution.sourceIdentity;
1341
+ dependencyPlugin.catalogLogicalIdentity = item.resolution.logicalIdentity;
1342
+ dependencyPlugin.pluginId = dependencyId;
1343
+ return dependencyPlugin;
1344
+ });
1345
+ dependencyPluginCache.set(pluginCacheKey, dependencyPluginPromise);
1346
+ }
1347
+ const dependencyPlugin = await dependencyPluginPromise;
1348
+ dependencyInspectionHookForTests?.();
1349
+ const dependencyMarketplaceName = marketplaceNameFor(dependencyName, platform, dependencyScope);
1350
+ const dependencyInspected = await inspectRebuildTarget({
1351
+ sourceId: item.resolution.sourceId,
1352
+ sourceIdentity: item.resolution.sourceIdentity,
1353
+ pluginId: dependencyId,
1354
+ marketplaceName: dependencyMarketplaceName,
1355
+ marketplaceRoot,
1356
+ plugin: dependencyPlugin,
1357
+ platform,
1358
+ scope: dependencyScope,
1359
+ cwd: options.cwd,
1360
+ catalog: { rootDir: item.resolution.rootDir, source: 'local' },
1361
+ context: {
1362
+ env,
1363
+ nativeCliRunner,
1364
+ reporter: createNoopReporter(),
1365
+ debugLogger: createNoopDebugLogger(),
1366
+ codexObservationSession: options.codexObservationSession,
1367
+ },
1368
+ userActivationDesired: codexDesiredUserActivationIds,
1369
+ nativeProbe: readOnlyNativeProbe({
1370
+ pluginName: dependencyName,
1371
+ sourceId: item.resolution.sourceId,
1372
+ sourceIdentity: item.resolution.sourceIdentity,
1373
+ platform,
1374
+ scope: dependencyScope,
1375
+ marketplaceName: dependencyMarketplaceName,
1376
+ marketplaceRoot,
1377
+ desired: sourceDesired.get(desiredTargetKey(dependencyId, platform))
1378
+ ?.scopes.includes(dependencyScope) === true,
1379
+ }),
1380
+ shallow: true,
1381
+ });
1382
+ const dependencyLiveState = projectedLiveState({
1383
+ inspection: dependencyInspected.inspection,
1384
+ required: dependencyInspected.target.desiredOwnedComponents
1385
+ ?? dependencyInspected.target.ownedComponents,
1386
+ optional: dependencyInspected.target.optionalOwnedComponents ?? [],
1387
+ });
1388
+ const collision = dependencyInspected.inspection.components.find((component) => component.collision)?.collision;
1389
+ if (collision) {
1390
+ return {
1391
+ state: 'blockedByCollision',
1392
+ dependencyScope,
1393
+ rootIssueId: collisionRootIssueId({
1394
+ pluginId: dependencyId,
1395
+ platform,
1396
+ scope: dependencyScope,
1397
+ collision,
1398
+ }),
1399
+ rootIssueCode: 'artifactCollision',
1400
+ issuePluginId: dependencyId,
1401
+ issueScope: dependencyScope,
1402
+ };
1403
+ }
1404
+ const requiredDependencyComponents = dependencyInspected.target
1405
+ .desiredOwnedComponents ?? dependencyInspected.target.ownedComponents;
1406
+ const desiredDependency = sourceDesired.get(desiredTargetKey(dependencyId, platform));
1407
+ const projectMigrationPending = dependencyScope === 'project'
1408
+ && projectIntent.dependencyScopeOverrides.some((override) => override.pluginId === dependencyId
1409
+ && override.scope === 'project'
1410
+ && (override.platform === undefined || override.platform === platform))
1411
+ && desiredDependency?.scopes.includes('project') === true
1412
+ && desiredDependency.scopes.includes('user') === false
1413
+ && ownerInventory.references.some((reference) => reference.kind === 'namespacedOwner'
1414
+ && reference.sourceId === item.resolution.sourceId
1415
+ && reference.pluginName === dependencyName
1416
+ && reference.platform === platform
1417
+ && reference.scope === 'user');
1418
+ const migrationOnlyPartial = dependencyLiveState === 'partial'
1419
+ && projectMigrationPending
1420
+ && dependencyInspected.inspection.components.every((component) => component.state === 'present' || component.state === 'absent')
1421
+ && requiredDependencyComponents.every((required) => dependencyInspected.inspection.components.some((component) => component.component === required
1422
+ && (component.state === 'present'
1423
+ || component.state === 'absent'
1424
+ && component.component.kind !== 'native-plugin'
1425
+ && 'locator' in component.component
1426
+ && component.component.locator.kind === 'codex-activation'
1427
+ && component.component.locator.desired === false)));
1428
+ const effectiveDependencyLiveState = migrationOnlyPartial
1429
+ ? 'present'
1430
+ : dependencyLiveState;
1431
+ if (effectiveDependencyLiveState !== 'present') {
1432
+ const state = effectiveDependencyLiveState === 'absent' ? 'absent'
1433
+ : effectiveDependencyLiveState === 'partial' ? 'incomplete'
1434
+ : 'error';
1435
+ return {
1436
+ state,
1437
+ dependencyScope,
1438
+ rootIssueId: state === 'absent'
1439
+ ? `dependencyMissing:${dependencyId}:${platform}:${dependencyScope}`
1440
+ : state === 'incomplete'
1441
+ ? `incompleteInstallation:${dependencyId}:${platform}:${dependencyScope}`
1442
+ : `diagnostic:${dependencyId}:${platform}:${dependencyScope}`,
1443
+ rootIssueCode: state === 'absent' ? 'dependencyMissing'
1444
+ : state === 'incomplete' ? 'incompleteInstallation' : 'diagnostic',
1445
+ issuePluginId: dependencyId,
1446
+ issueScope: dependencyScope,
1447
+ };
1448
+ }
1449
+ for (const childName of dependencyPlugin.manifest.dependencies ?? []) {
1450
+ const childId = formatPluginId({
1451
+ sourceId: item.resolution.sourceId,
1452
+ pluginName: childName,
1453
+ });
1454
+ let childResult;
1455
+ for (const childScope of dependencyPlacementsFor(childId, dependencyScope)) {
1456
+ const candidate = await inspectDependencyAtScope(childName, childScope);
1457
+ if (candidate.state === 'ready') {
1458
+ childResult = candidate;
1459
+ break;
1460
+ }
1461
+ if (!childResult
1462
+ || dependencyPriority[candidate.state]
1463
+ > dependencyPriority[childResult.state]) {
1464
+ childResult = candidate;
1465
+ }
1466
+ }
1467
+ if (childResult?.state !== 'ready') {
1468
+ return {
1469
+ ...childResult,
1470
+ dependencyScope,
1471
+ };
1472
+ }
1473
+ }
1474
+ return { state: 'ready', dependencyScope };
1475
+ })().catch(() => ({
1476
+ state: 'error',
1477
+ dependencyScope,
1478
+ rootIssueId: `diagnostic:${dependencyId}:${platform}:${dependencyScope}`,
1479
+ rootIssueCode: 'diagnostic',
1480
+ issuePluginId: dependencyId,
1481
+ issueScope: dependencyScope,
1482
+ }));
1483
+ dependencyInspectionCache.set(inspectionCacheKey, inspection);
1484
+ return inspection;
1485
+ }
1486
+ if (directDependencies.length > 0
1487
+ && (desiredInScope
1488
+ || actualCodexActivation
1489
+ || hasScopedExtensionResidue
1490
+ || (platform !== 'codex'
1491
+ && (liveState === 'present' || liveState === 'partial')))) {
1492
+ for (const dependencyName of directDependencies) {
1493
+ const dependencyId = formatPluginId({
1494
+ sourceId: item.resolution.sourceId,
1495
+ pluginName: dependencyName,
1496
+ });
1497
+ const dependencyEntry = item.resolution.manifest.entries.find((candidate) => candidate.name === dependencyName);
1498
+ if (!dependencyEntry) {
1499
+ const rootIssueId = `dependencyMissing:${dependencyId}:${platform}:${scope}`;
1500
+ dependencyReadiness.push({
1501
+ dependencyPluginId: dependencyId,
1502
+ dependencyPlatform: platform,
1503
+ dependencyScope: scope,
1504
+ dependencyProject: scope === 'project' ? 'current' : null,
1505
+ state: 'absent',
1506
+ rootIssueId,
1507
+ rootIssueCode: 'dependencyMissing',
1508
+ });
1509
+ dependencyErrors.push(finalizeTargetError({
1510
+ code: 'dependencyMissing',
1511
+ message: `dependencyMissing: ${dependencyId} is not available in the current source snapshot.`,
1512
+ dependencyPluginId: dependencyId,
1513
+ dependencyPlatform: platform,
1514
+ dependencyScope: scope,
1515
+ dependencyProject: scope === 'project' ? 'current' : null,
1516
+ rootIssueId,
1517
+ rootIssueCode: 'dependencyMissing',
1518
+ }, 'partial'));
1519
+ continue;
1520
+ }
1521
+ const dependencySupport = checkAwCapabilitySupport(dependencyEntry.requires.aw.capabilities ?? [], IMPLEMENTED_AW_CAPABILITIES);
1522
+ if (!dependencySupport.supported) {
1523
+ const rootIssueId = `awCapabilityUnsupported:${dependencyId}`;
1524
+ dependencyReadiness.push({
1525
+ dependencyPluginId: dependencyId,
1526
+ dependencyPlatform: platform,
1527
+ dependencyScope: scope,
1528
+ dependencyProject: scope === 'project' ? 'current' : null,
1529
+ state: 'error',
1530
+ rootIssueId,
1531
+ rootIssueCode: 'awCapabilityUnsupported',
1532
+ });
1533
+ dependencyErrors.push(finalizeTargetError({
1534
+ code: 'awCapabilityUnsupported',
1535
+ message: `awCapabilityUnsupported: ${dependencyId} requires unsupported AW capabilities: ${dependencySupport.missing.join(', ')}.`,
1536
+ dependencyPluginId: dependencyId,
1537
+ dependencyPlatform: platform,
1538
+ dependencyScope: scope,
1539
+ dependencyProject: scope === 'project' ? 'current' : null,
1540
+ rootIssueId,
1541
+ rootIssueCode: 'awCapabilityUnsupported',
1542
+ }, 'partial'));
1543
+ continue;
1544
+ }
1545
+ const placements = dependencyPlacementsFor(dependencyId, scope);
1546
+ let dependencyResult = {
1547
+ state: 'absent',
1548
+ };
1549
+ for (const dependencyScope of placements) {
1550
+ const candidate = await inspectDependencyAtScope(dependencyName, dependencyScope);
1551
+ if (candidate.state === 'ready') {
1552
+ dependencyResult = candidate;
1553
+ break;
1554
+ }
1555
+ const priority = {
1556
+ ready: 5,
1557
+ blockedByCollision: 4,
1558
+ incomplete: 3,
1559
+ error: 2,
1560
+ absent: 1,
1561
+ };
1562
+ if (priority[candidate.state] > priority[dependencyResult.state]) {
1563
+ dependencyResult = candidate;
1564
+ }
1565
+ }
1566
+ if (dependencyResult.state === 'absent' && !dependencyResult.rootIssueId) {
1567
+ const dependencyScope = dependencyResult.dependencyScope ?? placements[0];
1568
+ dependencyResult = {
1569
+ state: 'absent',
1570
+ dependencyScope,
1571
+ rootIssueId: `dependencyMissing:${dependencyId}:${platform}:${dependencyScope}`,
1572
+ rootIssueCode: 'dependencyMissing',
1573
+ };
1574
+ }
1575
+ const dependencyScope = dependencyResult.dependencyScope ?? placements[0];
1576
+ dependencyReadiness.push({
1577
+ dependencyPluginId: dependencyId,
1578
+ dependencyPlatform: platform,
1579
+ dependencyScope,
1580
+ dependencyProject: dependencyScope === 'project' ? 'current' : null,
1581
+ state: dependencyResult.state,
1582
+ ...(dependencyResult.rootIssueId
1583
+ ? { rootIssueId: dependencyResult.rootIssueId }
1584
+ : {}),
1585
+ ...(dependencyResult.rootIssueCode
1586
+ ? { rootIssueCode: dependencyResult.rootIssueCode }
1587
+ : {}),
1588
+ });
1589
+ const issuePluginId = dependencyResult.issuePluginId ?? dependencyId;
1590
+ const issueScope = dependencyResult.issueScope ?? dependencyScope;
1591
+ if (dependencyResult.state === 'absent') {
1592
+ dependencyErrors.push(finalizeTargetError({
1593
+ code: 'dependencyMissing',
1594
+ message: `dependencyMissing: ${issuePluginId} is absent from its required live placement.`,
1595
+ dependencyPluginId: issuePluginId,
1596
+ dependencyPlatform: platform,
1597
+ dependencyScope: issueScope,
1598
+ dependencyProject: issueScope === 'project' ? 'current' : null,
1599
+ rootIssueId: dependencyResult.rootIssueId,
1600
+ rootIssueCode: dependencyResult.rootIssueCode,
1601
+ }, 'partial'));
1602
+ }
1603
+ else if (dependencyResult.state !== 'ready') {
1604
+ const code = dependencyResult.rootIssueCode === 'awCapabilityUnsupported'
1605
+ ? 'awCapabilityUnsupported'
1606
+ : dependencyResult.rootIssueCode === 'dependencyGraphInvalid'
1607
+ ? 'dependencyGraphInvalid'
1608
+ : 'dependencyNotReady';
1609
+ const message = code === 'awCapabilityUnsupported'
1610
+ ? `${code}: ${issuePluginId} requires unsupported AW capabilities: ${(dependencyResult.missingCapabilities ?? []).join(', ')}.`
1611
+ : code === 'dependencyGraphInvalid'
1612
+ ? `${code}: dependency cycle includes ${issuePluginId}.`
1613
+ : `${code}: ${issuePluginId} is not ready at its required live placement.`;
1614
+ dependencyErrors.push(finalizeTargetError({
1615
+ code,
1616
+ message,
1617
+ dependencyPluginId: issuePluginId,
1618
+ dependencyPlatform: platform,
1619
+ dependencyScope: issueScope,
1620
+ dependencyProject: issueScope === 'project' ? 'current' : null,
1621
+ ...(dependencyResult.rootIssueId
1622
+ ? { rootIssueId: dependencyResult.rootIssueId }
1623
+ : {}),
1624
+ ...(dependencyResult.rootIssueCode
1625
+ ? { rootIssueCode: dependencyResult.rootIssueCode }
1626
+ : {}),
1627
+ }, 'partial'));
1628
+ }
1629
+ }
1630
+ }
1631
+ states[platform][scope] = {
1632
+ state: liveState,
1633
+ errors: [...inspected.inspection.errors.map((error) => finalizeTargetError({
1634
+ code: 'componentInspectionFailed',
1635
+ message: `${error.label}: ${error.message}`,
1636
+ }, liveState)), ...collisionErrors, ...dependencyErrors],
1637
+ ...(dependencyReadiness.length > 0 ? { dependencyReadiness } : {}),
1638
+ components: inspected.inspection.components.map((component) => {
1639
+ const projectedError = component.collision
1640
+ ? projectTargetError({
1641
+ code: 'artifactCollision',
1642
+ message: collisionMessage(component.collision),
1643
+ collision: component.collision,
1644
+ }, env, options.cwd, liveState)
1645
+ : component.diagnostic
1646
+ ? projectTargetError({
1647
+ code: 'componentInspectionFailed',
1648
+ message: component.diagnostic,
1649
+ }, env, options.cwd, liveState)
1650
+ : undefined;
1651
+ return {
1652
+ key: component.component.identity.artifactKey,
1653
+ state: component.state,
1654
+ ...(projectedError ? { error: projectedError } : {}),
1655
+ };
1656
+ }),
1657
+ ...(inspected.installedVersion
1658
+ ? { installedVersion: inspected.installedVersion }
1659
+ : {}),
1660
+ };
1661
+ }
1662
+ catch (error) {
1663
+ const message = error instanceof Error ? error.message : String(error);
1664
+ const configErrorCode = platform === 'codex' && codexConfigErrors.length > 0
1665
+ ? codexSurface.nativeKinds.length > 0
1666
+ ? 'codexSharedNativeCorrupt'
1667
+ : 'codexActivationDrift'
1668
+ : undefined;
1669
+ const code = configErrorCode
1670
+ ?? message.split(':', 1)[0]
1671
+ ?? 'targetInspectionFailed';
1672
+ states[platform][scope] = {
1673
+ state: 'error',
1674
+ components: [],
1675
+ errors: [finalizeTargetError({
1676
+ code,
1677
+ message: configErrorCode
1678
+ ? `${configErrorCode}: Codex activation state is unreadable.`
1679
+ : message,
1680
+ }, 'error')],
1681
+ };
1682
+ }
1683
+ }
1684
+ }
1685
+ let codexStatus;
1686
+ if (codex && codexSurface.ok) {
1687
+ const marketplaceName = marketplaceNameFor(entry.name, 'codex', 'user');
1688
+ const codexPluginId = `${entry.name}@${marketplaceName}`;
1689
+ const desiredCodexScopes = sourceDesired.get(desiredTargetKey(formatPluginId({ sourceId: item.resolution.sourceId, pluginName: entry.name }), 'codex'))?.scopes ?? [];
1690
+ const registrationScope = options.scope !== undefined
1691
+ ? scopes[0]
1692
+ : desiredCodexScopes.includes('project')
1693
+ ? 'project'
1694
+ : desiredCodexScopes.includes('user') ? 'user' : 'project';
1695
+ const pluginRegistration = codexSurface.nativeKinds.length > 0
1696
+ ? await inspectCodexRegistration(codexPluginId, registrationScope)
1697
+ : {
1698
+ observation: { state: 'unobserved' },
1699
+ observations: { user: false, project: false },
1700
+ activations: {},
1701
+ };
1702
+ let residueFailed = false;
1703
+ const hasNativeRenderTargets = (plugin.manifest.artifacts?.targets ?? []).some((target) => target.platform === 'codex'
1704
+ && target.target === 'codex.skill'
1705
+ && target.delivery?.mode === 'codex-native');
1706
+ const sharedInspection = codexSurface.nativeKinds.length > 0
1707
+ ? await inspectCodexSharedNativeLive({
1708
+ pluginName: entry.name,
1709
+ sourceId: item.resolution.sourceId,
1710
+ desiredVersion: entry.version,
1711
+ inspectionMode: hasNativeRenderTargets ? 'payload' : 'shallow',
1712
+ cwd: options.cwd,
1713
+ env,
1714
+ marketplaceName,
1715
+ marketplaceRoot,
1716
+ nativeCliRunner,
1717
+ pluginRegistration,
1718
+ ...(hasNativeRenderTargets ? { nativeRenderPlugin: plugin } : {}),
1719
+ }).catch(() => {
1720
+ residueFailed = true;
1721
+ return undefined;
1722
+ })
1723
+ : undefined;
1724
+ const nativeState = sharedInspection?.sharedNative;
1725
+ const sharedNative = residueFailed
1726
+ ? { pluginId: codexPluginId, state: 'blocked', reason: 'unreadable' }
1727
+ : !nativeState
1728
+ ? undefined
1729
+ : nativeState.state === 'unobserved'
1730
+ ? {
1731
+ pluginId: codexPluginId,
1732
+ state: 'unobserved',
1733
+ ...(nativeState.staleCacheObserved ? { staleCacheObserved: true } : {}),
1734
+ }
1735
+ : nativeState.state === 'missing'
1736
+ ? {
1737
+ pluginId: codexPluginId,
1738
+ state: 'missing',
1739
+ ...(nativeState.staleCacheObserved ? { staleCacheObserved: true } : {}),
1740
+ }
1741
+ : nativeState.state === 'usable'
1742
+ ? {
1743
+ pluginId: codexPluginId,
1744
+ state: 'usable',
1745
+ version: nativeState.version,
1746
+ }
1747
+ : nativeState.state === 'replaceable'
1748
+ ? {
1749
+ pluginId: codexPluginId,
1750
+ state: 'replaceable',
1751
+ reason: nativeState.reason,
1752
+ ...(nativeState.version ? { version: nativeState.version } : {}),
1753
+ ...(nativeState.desiredVersion
1754
+ ? { desiredVersion: nativeState.desiredVersion }
1755
+ : {}),
1756
+ ...(nativeState.diagnostic ? { diagnostic: nativeState.diagnostic } : {}),
1757
+ }
1758
+ : {
1759
+ pluginId: codexPluginId,
1760
+ state: 'blocked',
1761
+ reason: nativeState.reason,
1762
+ diagnostic: nativeState.diagnostic,
1763
+ };
1764
+ const configuredUserActivation = userCodexConfig
1765
+ ?.snapshot.plugins[codexPluginId]?.enabled;
1766
+ const configuredProjectActivation = projectCodexConfig
1767
+ ?.snapshot.plugins[codexPluginId]?.enabled;
1768
+ const userActivation = configuredUserActivation;
1769
+ const projectActivation = configuredProjectActivation;
1770
+ const activationObserved = registrationScope === 'project'
1771
+ ? userCodexConfig !== undefined && projectCodexConfig !== undefined
1772
+ : userCodexConfig !== undefined;
1773
+ codexStatus = {
1774
+ pluginId: codexPluginId,
1775
+ nativeKinds: codexSurface.nativeKinds,
1776
+ extensionKinds: codexSurface.extensionKinds,
1777
+ ...(sharedNative ? { sharedNative } : {}),
1778
+ activation: {
1779
+ ...(userActivation !== undefined ? { user: userActivation } : {}),
1780
+ ...(projectActivation !== undefined ? { project: projectActivation } : {}),
1781
+ ...((userActivation !== undefined || projectActivation !== undefined)
1782
+ ? { effective: (projectActivation ?? userActivation) === true }
1783
+ : {}),
1784
+ evidence: activationObserved ? 'observed' : 'assumed',
1785
+ },
1786
+ };
1787
+ }
1788
+ return {
1789
+ name: entry.name,
1790
+ version: entry.version,
1791
+ displayName: plugin.manifest.interface?.displayName ?? entry.name,
1792
+ shortDescription: plugin.manifest.interface?.shortDescription
1793
+ ?? plugin.manifest.description,
1794
+ description: plugin.manifest.description,
1795
+ ...(plugin.manifest.config?.fields
1796
+ ? { configSchema: plugin.manifest.config.fields }
1797
+ : {}),
1798
+ ...(configIssues?.length ? { configIssues } : {}),
1799
+ ...(configDiagnostic ? { configDiagnostic } : {}),
1800
+ targets: {
1801
+ claude: { user: claude, project: claude },
1802
+ codex: {
1803
+ user: codex,
1804
+ project: codex
1805
+ && codexSurface.ok
1806
+ && codexSurface.classification !== 'empty',
1807
+ },
1808
+ },
1809
+ states,
1810
+ dependencies: plugin.manifest.dependencies ?? [],
1811
+ ...(codexStatus ? { codex: codexStatus } : {}),
1812
+ };
1813
+ }));
1814
+ return {
1815
+ ...base,
1816
+ resolvedCommit: item.resolution.resolvedCommit,
1817
+ catalogVersion: item.resolution.manifest.catalogVersion,
1818
+ channel: item.resolution.manifest.channel,
1819
+ freshness: 'active',
1820
+ plugins,
1821
+ };
1822
+ }
1823
+ catch (error) {
1824
+ const sanitized = sanitizeCatalogSourceError(error, env);
1825
+ return {
1826
+ ...base,
1827
+ error: sanitized.message,
1828
+ errorCode: catalogSourceErrorCode(sanitized),
1829
+ };
1830
+ }
1831
+ })),
1832
+ }),
1833
+ });
1834
+ const available = catalog.sources.flatMap((source) => 'plugins' in source
1835
+ ? source.plugins.map((plugin) => ({ ...plugin, source }))
1836
+ : []);
1837
+ const removedProjectionReferences = [];
1838
+ for (const source of catalog.sources) {
1839
+ if (!('plugins' in source))
1840
+ continue;
1841
+ const marketplaceRoot = path.join(resolveAwHome(env), 'marketplaces', source.id);
1842
+ try {
1843
+ const root = await readStrictNamespacedMarketplaceRoot({
1844
+ rootDir: marketplaceRoot, sourceId: source.id, sourceIdentity: source.identity,
1845
+ });
1846
+ if (!root)
1847
+ continue;
1848
+ const currentNames = new Set(source.plugins.map((plugin) => plugin.name));
1849
+ const candidates = new Map();
1850
+ const add = (name, platform) => {
1851
+ if (typeof name !== 'string' || currentNames.has(name))
1852
+ return;
1853
+ try {
1854
+ if (parsePluginId(name).sourceId !== undefined)
1855
+ return;
1856
+ }
1857
+ catch {
1858
+ return;
1859
+ }
1860
+ const supported = candidates.get(name) ?? new Set();
1861
+ supported.add(platform);
1862
+ candidates.set(name, supported);
1863
+ };
1864
+ for (const [platform, manifest] of [
1865
+ ['codex', root.agentsManifest], ['claude', root.claudeManifest],
1866
+ ]) {
1867
+ if (!Array.isArray(manifest?.plugins))
1868
+ continue;
1869
+ for (const plugin of manifest.plugins) {
1870
+ if (plugin && typeof plugin === 'object')
1871
+ add(plugin.name, platform);
1872
+ }
1873
+ }
1874
+ const pluginsRoot = path.join(root.rootDir, 'plugins');
1875
+ const pluginsStats = await fs.promises.lstat(pluginsRoot).catch((error) => {
1876
+ if (error.code === 'ENOENT')
1877
+ return undefined;
1878
+ throw error;
1879
+ });
1880
+ if (pluginsStats && (!pluginsStats.isDirectory() || pluginsStats.isSymbolicLink())) {
1881
+ throw new Error('marketplaceRootInvalid: plugin projection directory is unsafe.');
1882
+ }
1883
+ if (pluginsStats) {
1884
+ for (const entry of await fs.promises.readdir(pluginsRoot, { withFileTypes: true })) {
1885
+ if (!candidates.has(entry.name))
1886
+ add(entry.name, 'codex');
1887
+ }
1888
+ }
1889
+ const registration = userCodexConfig?.snapshot.marketplaces[root.config.marketplaceName];
1890
+ if (platforms.includes('codex')
1891
+ && registration?.sourceType === 'local'
1892
+ && !registration.sourcePointsToManifest
1893
+ && path.resolve(registration.source ?? '') === path.resolve(root.rootDir)
1894
+ && (await inspectCodexSystemConsumer(options.scope === 'project' ? 'project' : 'user')).state === 'compatible') {
1895
+ const observed = await options.codexObservationSession.snapshot(root.config.marketplaceName, options.scope === 'user' ? 'user' : 'both');
1896
+ const suffix = `@${root.config.marketplaceName}`;
1897
+ for (const pluginId of [...(observed.exact?.keys() ?? []), ...(observed.neutral?.keys() ?? [])]) {
1898
+ if (pluginId.endsWith(suffix))
1899
+ add(pluginId.slice(0, -suffix.length), 'codex');
1900
+ }
1901
+ }
1902
+ for (const [pluginName, supported] of candidates) {
1903
+ for (const platform of supported)
1904
+ removedProjectionReferences.push({
1905
+ kind: 'namespacedMarketplace', location: path.join(root.rootDir, 'config.json'),
1906
+ sourceId: source.id, sourceIdentity: source.identity,
1907
+ marketplaceName: root.config.marketplaceName, pluginName, platform, scope: 'user',
1908
+ });
1909
+ }
1910
+ }
1911
+ catch (error) {
1912
+ const projected = projectStateInventoryError(error, env, options.cwd);
1913
+ selectedInventoryErrors.push({ ...projected, relevance: { sourceId: source.id, global: false } });
1914
+ }
1915
+ }
1916
+ const statusReferences = [...ownerInventory.references, ...removedProjectionReferences];
1917
+ const desiredTargetStates = calculateDesiredTargetStates({
1918
+ userIntent,
1919
+ projectIntent,
1920
+ available,
1921
+ codexProjectAllowed: !codexScopePathsAlias,
1922
+ });
1923
+ const failedSourceIds = new Set(catalog.sources.filter((source) => 'error' in source).map((source) => source.id));
1924
+ const selectedById = new Map();
1925
+ if (requested.length === 0) {
1926
+ for (const entry of available) {
1927
+ selectedById.set(formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }), entry);
1928
+ }
1929
+ }
1930
+ else {
1931
+ for (const selector of plannedSelectors) {
1932
+ if (selector.parsed.sourceId === undefined && failedSourceIds.size > 0) {
1933
+ selectorErrors.push({
1934
+ code: 'catalogSourceUnavailable',
1935
+ message: `Cannot resolve bare plugin selector "${selector.raw}" while catalog sources are unavailable: ${[...failedSourceIds].join(', ')}.`,
1936
+ });
1937
+ continue;
1938
+ }
1939
+ if (selector.parsed.sourceId !== undefined && failedSourceIds.has(selector.parsed.sourceId)) {
1940
+ selectorErrors.push({
1941
+ code: 'catalogSourceUnavailable',
1942
+ message: `Cannot resolve plugin selector "${selector.raw}" because catalog source "${selector.parsed.sourceId}" is unavailable.`,
1943
+ });
1944
+ continue;
1945
+ }
1946
+ const matches = available.filter((entry) => entry.name === selector.parsed.pluginName
1947
+ && (selector.parsed.sourceId === undefined || entry.source.id === selector.parsed.sourceId));
1948
+ if (matches.length === 0) {
1949
+ const selectorHasInventoryError = selectedInventoryErrors.some((error) => inventoryErrorMatchesSelection({
1950
+ error,
1951
+ selectors: [selector],
1952
+ platformExplicit: options.platform !== undefined,
1953
+ scopeExplicit: options.scope !== undefined,
1954
+ platforms,
1955
+ scopes,
1956
+ currentProjectLocationKey,
1957
+ }));
1958
+ const selectorHasLiveOrIntent = statusReferences.some((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
1959
+ && reference.pluginName === selector.parsed.pluginName
1960
+ && reference.sourceId !== undefined
1961
+ && (selector.parsed.sourceId === undefined || reference.sourceId === selector.parsed.sourceId)
1962
+ && platforms.some((platform) => platform === reference.platform)
1963
+ && scopes.some((scope) => scope === reference.scope)
1964
+ && (reference.scope !== 'project' || reference.projectKey === currentProjectKey))
1965
+ || [userIntent, projectIntent].some((intent, index) => scopes.includes(index === 0 ? 'user' : 'project')
1966
+ && intent.roots.some((root) => {
1967
+ const parsed = parsePluginId(root.pluginId);
1968
+ return parsed.pluginName === selector.parsed.pluginName
1969
+ && (selector.parsed.sourceId === undefined || parsed.sourceId === selector.parsed.sourceId)
1970
+ && root.platforms.some((platform) => platforms.includes(platform));
1971
+ }));
1972
+ if (!selectorHasInventoryError && !selectorHasLiveOrIntent) {
1973
+ selectorErrors.push({
1974
+ code: 'pluginNotFound',
1975
+ message: `Plugin "${selector.raw}" was not found in the selected catalog source set.`,
1976
+ });
1977
+ }
1978
+ continue;
1979
+ }
1980
+ if (selector.parsed.sourceId === undefined && matches.length > 1) {
1981
+ selectorErrors.push({
1982
+ code: 'ambiguousPlugin',
1983
+ message: `Plugin "${selector.raw}" is ambiguous across sources: ${matches.map((entry) => entry.source.id).join(', ')}.`,
1984
+ });
1985
+ continue;
1986
+ }
1987
+ for (const entry of matches) {
1988
+ selectedById.set(formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }), entry);
1989
+ }
1990
+ }
1991
+ }
1992
+ const selected = [...selectedById.values()];
1993
+ const explicitTargetFilter = requested.length > 0
1994
+ && (options.platform !== undefined || options.scope !== undefined);
1995
+ const targets = selected.flatMap((entry) => platforms.flatMap((platform) => scopes.flatMap((scope) => {
1996
+ const target = {
1997
+ pluginName: entry.name,
1998
+ sourceId: entry.source.id,
1999
+ sourceIdentity: entry.source.identity,
2000
+ pluginId: formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
2001
+ version: entry.version,
2002
+ platform,
2003
+ scope,
2004
+ cwd: path.resolve(options.cwd),
2005
+ components: [],
2006
+ };
2007
+ if (platform === 'codex'
2008
+ && scope === 'project'
2009
+ && codexScopePathsAlias
2010
+ && !hasCurrentCodexProjectOwner(entry.source.id, entry.name)) {
2011
+ if (options.scope !== 'project')
2012
+ return [];
2013
+ return [{
2014
+ ...target,
2015
+ state: 'error',
2016
+ errors: [finalizeTargetError({
2017
+ code: 'codexScopePathAlias',
2018
+ message: 'codexScopePathAlias: Codex project config resolves to the user config directory. Run this command from an actual project directory.',
2019
+ }, 'error')],
2020
+ }];
2021
+ }
2022
+ if (entry.targets[platform][scope]) {
2023
+ const live = entry.states[platform]?.[scope];
2024
+ const dependencyIssueCount = (live?.errors ?? []).filter((error) => error.code.startsWith('dependency')
2025
+ || error.code === 'awCapabilityUnsupported'
2026
+ || error.code === 'sourceChanged').length;
2027
+ return [{
2028
+ ...target,
2029
+ state: live?.state ?? 'error',
2030
+ components: live?.components ?? [],
2031
+ errors: live?.errors ?? [finalizeTargetError({
2032
+ code: 'targetInspectionFailed',
2033
+ message: `No live inspection result exists for ${entry.source.id}/${entry.name}.`,
2034
+ }, 'error')],
2035
+ ...(live?.dependencyReadiness
2036
+ ? { dependencyReadiness: live.dependencyReadiness }
2037
+ : {}),
2038
+ ...(entry.dependencies.length > 0 || dependencyIssueCount > 0 ? {
2039
+ dependency: {
2040
+ directCount: entry.dependencies.length,
2041
+ issueCount: dependencyIssueCount,
2042
+ },
2043
+ } : {}),
2044
+ }];
2045
+ }
2046
+ const unsupportedLiveReference = ownerInventory.references.find((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
2047
+ && reference.sourceId === entry.source.id
2048
+ && reference.pluginName === entry.name
2049
+ && reference.platform === platform
2050
+ && reference.scope === scope
2051
+ && (scope === 'user' || reference.projectKey === currentProjectKey));
2052
+ if (unsupportedLiveReference) {
2053
+ const sourceChanged = Boolean(unsupportedLiveReference.sourceIdentity
2054
+ && unsupportedLiveReference.sourceIdentity !== entry.source.identity);
2055
+ return [{
2056
+ ...target,
2057
+ state: 'error',
2058
+ errors: [finalizeTargetError({
2059
+ code: sourceChanged ? 'sourceChanged' : 'noLongerSupported',
2060
+ message: sourceChanged
2061
+ ? `sourceChanged: live state for ${target.pluginId} has a different source identity.`
2062
+ : `noLongerSupported: ${target.pluginId} has live state for ${platform}/${scope}, but the current bundle no longer supports that target.`,
2063
+ }, 'error')],
2064
+ }];
2065
+ }
2066
+ if (!explicitTargetFilter)
2067
+ return [];
2068
+ return [{
2069
+ ...target,
2070
+ state: 'error',
2071
+ errors: [finalizeTargetError({
2072
+ code: platform === 'codex' && scope === 'project'
2073
+ ? 'codexProjectPluginUnsupported'
2074
+ : 'unsupportedTarget',
2075
+ message: platform === 'codex' && scope === 'project'
2076
+ ? `codexProjectPluginUnsupported: ${entry.source.id}/${entry.name} cannot use the current Codex project plugin contract.`
2077
+ : `${entry.source.id}/${entry.name} does not support ${platform}/${scope}.`,
2078
+ }, 'error')],
2079
+ }];
2080
+ })));
2081
+ const referenceSelectors = [...plannedSelectors, ...liveOnlySelectors];
2082
+ const referenceSelected = (reference) => (reference.pluginName !== undefined
2083
+ && reference.platform !== undefined
2084
+ && reference.scope !== undefined
2085
+ && platforms.includes(reference.platform)
2086
+ && scopes.includes(reference.scope)
2087
+ && (reference.scope !== 'project' || reference.projectKey === currentProjectKey)
2088
+ && (requested.length === 0 || referenceSelectors.some((selector) => selector.parsed.pluginName === reference.pluginName
2089
+ && (selector.parsed.sourceId === undefined || selector.parsed.sourceId === reference.sourceId))));
2090
+ const legacyOwners = ownerInventory.references.filter((reference) => (reference.kind === 'legacyOwner' || reference.kind === 'legacyMarketplace')
2091
+ && reference.pluginName !== undefined
2092
+ && reference.platform !== undefined
2093
+ && reference.scope !== undefined
2094
+ && platforms.includes(reference.platform)
2095
+ && scopes.includes(reference.scope)
2096
+ && (requested.length === 0 || plannedSelectors.some((selector) => selector.parsed.pluginName === reference.pluginName)));
2097
+ const missingSourceOwners = ownerInventory.references.filter((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
2098
+ && reference.sourceId
2099
+ && !configured.has(reference.sourceId)
2100
+ && referenceSelected(reference));
2101
+ const missingTargets = [...new Map(missingSourceOwners.flatMap((reference) => {
2102
+ if (!reference.sourceId || !reference.pluginName
2103
+ || (reference.platform !== 'codex' && reference.platform !== 'claude')
2104
+ || (reference.scope !== 'user' && reference.scope !== 'project'))
2105
+ return [];
2106
+ const pluginId = formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName });
2107
+ const target = {
2108
+ pluginName: reference.pluginName,
2109
+ sourceId: reference.sourceId,
2110
+ sourceIdentity: reference.sourceIdentity ?? 'unavailable',
2111
+ pluginId,
2112
+ platform: reference.platform,
2113
+ scope: reference.scope,
2114
+ cwd: path.resolve(options.cwd),
2115
+ state: 'error',
2116
+ components: [],
2117
+ errors: [finalizeTargetError({
2118
+ code: 'sourceMissing',
2119
+ message: `sourceMissing: catalog source "${reference.sourceId}" is not configured for ${pluginId}.`,
2120
+ }, 'error')],
2121
+ };
2122
+ return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
2123
+ })).values()];
2124
+ targets.push(...missingTargets);
2125
+ const unavailableSourceReferences = ownerInventory.references.filter((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
2126
+ && reference.sourceId
2127
+ && configured.has(reference.sourceId)
2128
+ && failedSourceIds.has(reference.sourceId)
2129
+ && referenceSelected(reference));
2130
+ const unavailableSourceTargets = [...new Map(unavailableSourceReferences.flatMap((reference) => {
2131
+ if (!reference.sourceId || !reference.pluginName
2132
+ || (reference.platform !== 'codex' && reference.platform !== 'claude')
2133
+ || (reference.scope !== 'user' && reference.scope !== 'project'))
2134
+ return [];
2135
+ const pluginId = formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName });
2136
+ const target = {
2137
+ pluginName: reference.pluginName,
2138
+ sourceId: reference.sourceId,
2139
+ sourceIdentity: reference.sourceIdentity ?? 'unavailable',
2140
+ pluginId,
2141
+ platform: reference.platform,
2142
+ scope: reference.scope,
2143
+ cwd: path.resolve(options.cwd),
2144
+ state: 'error',
2145
+ components: [],
2146
+ errors: [finalizeTargetError({
2147
+ code: 'catalogSourceUnavailable',
2148
+ message: `catalogSourceUnavailable: catalog source "${reference.sourceId}" is unavailable for ${pluginId}.`,
2149
+ }, 'error')],
2150
+ };
2151
+ return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
2152
+ })).values()];
2153
+ targets.push(...unavailableSourceTargets);
2154
+ const availablePluginIds = new Set(available.map((entry) => formatPluginId({ sourceId: entry.source.id, pluginName: entry.name })));
2155
+ const resolvedSourceIds = new Set(catalog.sources.flatMap((source) => 'plugins' in source ? [source.id] : []));
2156
+ const unavailableBundleReferences = statusReferences.filter((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
2157
+ && reference.sourceId
2158
+ && configured.has(reference.sourceId)
2159
+ && resolvedSourceIds.has(reference.sourceId)
2160
+ && reference.pluginName
2161
+ && referenceSelected(reference)
2162
+ && !availablePluginIds.has(formatPluginId({
2163
+ sourceId: reference.sourceId,
2164
+ pluginName: reference.pluginName,
2165
+ })));
2166
+ const unavailableBundleTargets = [...new Map((await Promise.all(unavailableBundleReferences.map(async (reference) => {
2167
+ if (!reference.sourceId || !reference.pluginName
2168
+ || (reference.platform !== 'codex' && reference.platform !== 'claude')
2169
+ || (reference.scope !== 'user' && reference.scope !== 'project'))
2170
+ return [];
2171
+ const pluginId = formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName });
2172
+ if (requested.length > 0 && !plannedSelectors.some((selector) => selector.parsed.pluginName === reference.pluginName
2173
+ && (selector.parsed.sourceId === undefined || selector.parsed.sourceId === reference.sourceId)))
2174
+ return [];
2175
+ const registration = reference.platform === 'codex' && reference.marketplaceName
2176
+ ? await inspectCodexRegistration(`${reference.pluginName}@${reference.marketplaceName}`, reference.scope)
2177
+ : undefined;
2178
+ const nativeUnknown = registration && registration.observation.state !== 'observed';
2179
+ const target = {
2180
+ pluginName: reference.pluginName,
2181
+ sourceId: reference.sourceId,
2182
+ sourceIdentity: reference.sourceIdentity ?? 'unavailable',
2183
+ pluginId,
2184
+ platform: reference.platform,
2185
+ scope: reference.scope,
2186
+ cwd: path.resolve(options.cwd),
2187
+ state: 'error',
2188
+ components: registration ? [{
2189
+ key: 'native',
2190
+ state: registration.observation.state !== 'observed' ? 'error'
2191
+ : registration.observation.value === 'installed' ? 'present' : 'absent',
2192
+ }] : [],
2193
+ errors: [finalizeTargetError({
2194
+ code: 'bundleUnavailable',
2195
+ message: `bundleUnavailable: ${pluginId} has live state but is not present in the current source snapshot.`,
2196
+ }, 'error'), finalizeTargetError({
2197
+ code: 'removedPluginCleanupRequired',
2198
+ message: `removedPluginCleanupRequired: ${pluginId} was removed from the current Catalog and has remaining local state.`,
2199
+ }, 'error'), ...(nativeUnknown ? [finalizeTargetError({
2200
+ code: 'codexNativeObservationFailed',
2201
+ message: 'codexNativeObservationFailed: the remaining native installation could not be observed.',
2202
+ }, 'error')] : [])],
2203
+ };
2204
+ return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
2205
+ }))).flat()).values()];
2206
+ targets.push(...unavailableBundleTargets);
2207
+ const targetKeys = new Set(targets.map((target) => `${target.pluginId}\0${target.platform}\0${target.scope}`));
2208
+ for (const [scope, intent] of [
2209
+ ['user', userIntent],
2210
+ ['project', projectIntent],
2211
+ ]) {
2212
+ for (const root of intent.roots) {
2213
+ const parsed = parsePluginId(root.pluginId);
2214
+ if (!parsed.sourceId)
2215
+ continue;
2216
+ if (requested.length > 0 && !parsedSelectors.some((selector) => selector.parsed.pluginName === parsed.pluginName
2217
+ && (selector.parsed.sourceId === undefined || selector.parsed.sourceId === parsed.sourceId))) {
2218
+ continue;
2219
+ }
2220
+ for (const platform of root.platforms.filter((candidate) => platforms.includes(candidate))) {
2221
+ if (!scopes.includes(scope))
2222
+ continue;
2223
+ const key = `${root.pluginId}\0${platform}\0${scope}`;
2224
+ if (targetKeys.has(key))
2225
+ continue;
2226
+ targets.push({
2227
+ pluginName: parsed.pluginName,
2228
+ sourceId: parsed.sourceId,
2229
+ sourceIdentity: identities.get(parsed.sourceId)?.identity ?? 'unavailable',
2230
+ pluginId: root.pluginId,
2231
+ platform,
2232
+ scope,
2233
+ cwd: path.resolve(options.cwd),
2234
+ state: 'error',
2235
+ components: [],
2236
+ errors: [finalizeTargetError({
2237
+ code: 'codexIntentSourceUnavailable',
2238
+ message: `codexIntentSourceUnavailable: desired intent for ${root.pluginId} cannot be resolved from the current Catalog.`,
2239
+ }, 'partial')],
2240
+ });
2241
+ targetKeys.add(key);
2242
+ }
2243
+ }
2244
+ }
2245
+ const projectedInventoryErrors = [...new Map(selectedInventoryErrors.map((error) => [
2246
+ `${error.code}\0${error.message}`,
2247
+ { code: error.code, message: error.message },
2248
+ ])).values()];
2249
+ const errors = [
2250
+ ...projectedInventoryErrors,
2251
+ ...selectorErrors,
2252
+ ...intentErrors,
2253
+ ...legacyOwners.map((reference) => projectTargetError({
2254
+ code: 'legacyStateUnsupported',
2255
+ message: `legacyStateUnsupported: legacy live ${reference.kind} at ${reference.location}`,
2256
+ }, env, options.cwd, 'error')),
2257
+ ];
2258
+ const draftTargets = targets.map((target) => ({
2259
+ ...target,
2260
+ errors: target.errors.map((error) => projectTargetError(error, env, options.cwd, target.state)),
2261
+ }));
2262
+ const selectedByPluginId = new Map(selected.map((entry) => [
2263
+ formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
2264
+ entry,
2265
+ ]));
2266
+ const explicitScope = options.scope === undefined ? undefined : scopes[0];
2267
+ const warning = (code, message) => ({
2268
+ code,
2269
+ message: `${code}: ${message}`,
2270
+ severity: 'warning',
2271
+ });
2272
+ const blocking = (code, message) => ({
2273
+ code,
2274
+ message: `${code}: ${message}`,
2275
+ severity: 'blocking',
2276
+ });
2277
+ const decorateTarget = async (target, groupedScopes, groupedTargets) => {
2278
+ const entry = selectedByPluginId.get(target.pluginId);
2279
+ const codex = target.platform === 'codex' ? entry?.codex : undefined;
2280
+ const desiredAll = desiredTargetStates.get(desiredTargetKey(target.pluginId, target.platform))
2281
+ ?? { scopes: [], relation: 'none' };
2282
+ const desired = {
2283
+ scopes: desiredAll.scopes.includes(target.scope) ? [target.scope] : [],
2284
+ relation: desiredAll.relation,
2285
+ };
2286
+ const sharedNative = codex?.sharedNative ?? target.sharedNative;
2287
+ const baseActivation = codex?.activation ?? target.activation;
2288
+ const consumerScope = desired.scopes.includes('project')
2289
+ ? 'project'
2290
+ : desired.scopes.includes('user')
2291
+ ? 'user'
2292
+ : explicitScope ?? (groupedScopes.includes('project') ? 'project' : 'user');
2293
+ const inspectSystemConsumer = target.platform === 'codex'
2294
+ && baseActivation !== undefined
2295
+ && ((codex?.nativeKinds.length ?? 0) > 0 || target.sharedNative !== undefined);
2296
+ const systemConsumer = inspectSystemConsumer
2297
+ ? await inspectCodexSystemConsumer(consumerScope)
2298
+ : undefined;
2299
+ const activation = baseActivation && systemConsumer
2300
+ ? {
2301
+ ...baseActivation,
2302
+ evidence: systemConsumer.state === 'compatible'
2303
+ ? 'observed'
2304
+ : systemConsumer.state === 'missing' ? 'assumed' : 'unobserved',
2305
+ systemConsumer,
2306
+ }
2307
+ : baseActivation;
2308
+ const observationScopes = [target.scope];
2309
+ const scopedTargets = groupedTargets.filter((candidate) => observationScopes.includes(candidate.scope));
2310
+ const observedTargets = scopedTargets.length > 0 ? scopedTargets : groupedTargets;
2311
+ const ownershipState = observedTargets.some((candidate) => candidate.state === 'error')
2312
+ ? 'error'
2313
+ : observedTargets.some((candidate) => candidate.state === 'partial')
2314
+ ? 'partial'
2315
+ : observedTargets.some((candidate) => candidate.state === 'present')
2316
+ ? 'present'
2317
+ : sharedNative?.staleCacheObserved
2318
+ ? 'partial'
2319
+ : 'absent';
2320
+ const actualScopeEnabled = target.platform === 'codex'
2321
+ && baseActivation?.[target.scope] === true;
2322
+ const hasSourceError = observedTargets.some((candidate) => candidate.errors.some((error) => error.code === 'sourceMissing'
2323
+ || error.code === 'catalogSourceUnavailable'
2324
+ || error.code === 'bundleUnavailable'
2325
+ || error.code === 'codexIntentSourceUnavailable'));
2326
+ const desiredOverlapConflict = target.platform === 'codex'
2327
+ && (codex?.extensionKinds.length ?? 0) > 0
2328
+ && desired.scopes.includes('user')
2329
+ && desired.scopes.includes('project');
2330
+ const expectedEnabled = desired.scopes.includes(target.scope);
2331
+ const inheritedUserActivation = target.platform === 'codex'
2332
+ && target.scope === 'project'
2333
+ && !expectedEnabled
2334
+ && desiredAll.scopes.includes('user')
2335
+ && activation?.user === true
2336
+ && (codex?.nativeKinds.length ?? 0) > 0;
2337
+ const projectDisablesUserActivation = inheritedUserActivation && activation?.project === false;
2338
+ const redundantProjectActivation = inheritedUserActivation && activation?.project === true
2339
+ && (codex?.extensionKinds.length ?? 0) === 0;
2340
+ const activationDrift = target.platform === 'codex'
2341
+ && (codexConfigErrors.some((error) => error.scope === 'user' || observationScopes.includes(error.scope))
2342
+ || ((codex?.nativeKinds.length ?? 0) > 0
2343
+ && (expectedEnabled && activation?.[target.scope] !== true
2344
+ || !expectedEnabled && activation?.[target.scope] === true && !redundantProjectActivation
2345
+ || projectDisablesUserActivation)));
2346
+ const extensionComponents = observedTargets.flatMap((candidate) => candidate.components).filter((component) => component.key !== 'native'
2347
+ && !component.key.startsWith('activation-')
2348
+ && !component.key.startsWith('marketplace-'));
2349
+ const hasScopedExtensionResidue = extensionComponents.some((component) => component.state !== 'absent' || component.error !== undefined);
2350
+ const extensions = target.platform !== 'codex'
2351
+ || (codex?.extensionKinds.length ?? 0) === 0
2352
+ ? undefined
2353
+ : {
2354
+ state: desiredOverlapConflict
2355
+ ? 'conflict'
2356
+ : extensionComponents.some((component) => component.error?.code === 'artifactCollision')
2357
+ ? 'conflict'
2358
+ : extensionComponents.some((component) => component.state === 'partial' || component.state === 'error')
2359
+ ? 'drifted'
2360
+ : desired.scopes.length > 0 && (extensionComponents.length === 0
2361
+ || extensionComponents.every((component) => component.state === 'absent'))
2362
+ ? 'missing'
2363
+ : 'ready',
2364
+ kinds: codex.extensionKinds,
2365
+ };
2366
+ const desiredEnabled = desired.scopes.length > 0;
2367
+ const projectDependencyIds = projectIntent.roots.some((root) => root.pluginId === target.pluginId && root.platforms.includes(target.platform))
2368
+ ? projectDependencyClosureForTarget({
2369
+ pluginId: target.pluginId,
2370
+ platform: target.platform,
2371
+ available,
2372
+ })
2373
+ : new Set();
2374
+ const dependencyMoves = projectIntent.dependencyScopeOverrides.flatMap((override) => {
2375
+ if (override.scope !== 'project'
2376
+ || (override.platform !== undefined && override.platform !== target.platform)
2377
+ || !projectDependencyIds.has(override.pluginId)) {
2378
+ return [];
2379
+ }
2380
+ const dependencyDesired = desiredTargetStates.get(desiredTargetKey(override.pluginId, target.platform));
2381
+ if (!dependencyDesired?.scopes.includes('project')
2382
+ || dependencyDesired.scopes.includes('user')) {
2383
+ return [];
2384
+ }
2385
+ const parsed = parsePluginId(override.pluginId);
2386
+ const hasPreservedUserActual = ownerInventory.references.some((reference) => reference.kind === 'namespacedOwner'
2387
+ && reference.sourceId === parsed.sourceId
2388
+ && reference.pluginName === parsed.pluginName
2389
+ && reference.platform === target.platform
2390
+ && reference.scope === 'user');
2391
+ return hasPreservedUserActual
2392
+ ? [{ pluginId: override.pluginId, fromScope: 'user', toScope: 'project' }]
2393
+ : [];
2394
+ }).sort((left, right) => left.pluginId.localeCompare(right.pluginId, 'en'));
2395
+ const consumerIssue = activation?.systemConsumer?.state === 'incompatible'
2396
+ || activation?.systemConsumer?.state === 'unresolved'
2397
+ ? activation.systemConsumer
2398
+ : undefined;
2399
+ const consumerBlocking = consumerIssue !== undefined;
2400
+ const baseTargetErrors = observedTargets.flatMap((candidate) => candidate.errors);
2401
+ const hasBlockingBaseReason = baseTargetErrors.some((reason) => reason.severity === 'blocking');
2402
+ const capabilityUnsupported = baseTargetErrors.some((reason) => reason.code === 'awCapabilityUnsupported');
2403
+ const dependencyNotReady = (target.dependencyReadiness ?? []).some((dependency) => dependency.state !== 'ready');
2404
+ const state = hasSourceError && desiredEnabled
2405
+ ? 'blocked'
2406
+ : consumerBlocking && desiredEnabled
2407
+ ? 'blocked'
2408
+ : desiredOverlapConflict
2409
+ ? 'blocked'
2410
+ : sharedNative?.state === 'blocked' || hasBlockingBaseReason || capabilityUnsupported
2411
+ ? 'blocked'
2412
+ : sharedNative?.state === 'replaceable' && sharedNative.reason === 'damaged'
2413
+ ? 'needsSync'
2414
+ : projectDisablesUserActivation
2415
+ ? 'needsSync'
2416
+ : redundantProjectActivation && sharedNative?.state === 'usable' && !hasScopedExtensionResidue
2417
+ ? 'ready'
2418
+ : !desiredEnabled
2419
+ ? (target.platform === 'codex'
2420
+ ? actualScopeEnabled || hasScopedExtensionResidue
2421
+ : ownershipState !== 'absent')
2422
+ || desired.relation === 'managed'
2423
+ ? 'orphaned'
2424
+ : 'absent'
2425
+ : dependencyMoves.length > 0
2426
+ ? 'needsSync'
2427
+ : dependencyNotReady
2428
+ ? 'needsSync'
2429
+ : sharedNative?.state === 'missing'
2430
+ || sharedNative?.state === 'replaceable'
2431
+ || sharedNative?.state === 'unobserved'
2432
+ ? 'needsSync'
2433
+ : activationDrift || extensions?.state === 'drifted'
2434
+ ? 'needsSync'
2435
+ : extensions?.state === 'missing'
2436
+ || (target.platform !== 'codex' && ownershipState === 'absent')
2437
+ ? 'needsSync'
2438
+ : ownershipState === 'partial' || ownershipState === 'error'
2439
+ ? 'needsSync'
2440
+ : 'ready';
2441
+ const stableErrors = [
2442
+ ...projectStatusSharedNativeReasons(sharedNative, baseTargetErrors.map((error) => error.code), desiredEnabled),
2443
+ ...(desiredOverlapConflict
2444
+ ? [blocking('codexExtensionScopeConflict', `${target.pluginId} has AW extensions desired at user and project scope.`)]
2445
+ : []),
2446
+ ...(activationDrift && sharedNative?.state !== 'missing' && sharedNative?.state !== 'unobserved'
2447
+ ? [warning('codexActivationDrift', projectDisablesUserActivation
2448
+ ? `${target.pluginId} is enabled for the user but disabled by the current project.`
2449
+ : `${target.pluginId} activation differs from desired intent: `
2450
+ + `${target.scope} expected=${expectedEnabled}, `
2451
+ + `actual=${activation?.[target.scope] ?? 'unset'}.`)]
2452
+ : []),
2453
+ ...(extensions?.state === 'drifted'
2454
+ ? [warning('codexExtensionDrift', `${target.pluginId} extension projection has drifted.`)]
2455
+ : []),
2456
+ ...dependencyMoves.map((move) => ({
2457
+ ...warning('dependencyScopeMigrationCleanupRequired', `${move.pluginId} has preserved user-scope output after moving to project scope.`),
2458
+ dependencyPluginId: move.pluginId,
2459
+ dependencyPlatform: target.platform,
2460
+ dependencyScope: move.toScope,
2461
+ dependencyProject: 'current',
2462
+ })),
2463
+ ...(target.platform === 'codex' && hasSourceError && desiredEnabled
2464
+ ? [warning('codexIntentSourceUnavailable', `${target.pluginId} desired intent cannot be resolved from the current Catalog.`)]
2465
+ : []),
2466
+ ...(target.platform === 'codex' && consumerBlocking && desiredEnabled
2467
+ ? [blocking(consumerIssue.code, consumerIssue.diagnostic)]
2468
+ : []),
2469
+ ];
2470
+ const targetErrors = [...baseTargetErrors, ...stableErrors];
2471
+ const dedupedErrors = [...new Map(targetErrors.map((error) => [
2472
+ `${error.code}\0${error.message}`,
2473
+ error,
2474
+ ])).values()];
2475
+ const ownershipComponents = [...new Map(observedTargets.flatMap((candidate) => candidate.components)
2476
+ .map((component) => [component.key, component])).values()];
2477
+ const representativeScope = target.scope;
2478
+ const representativeTarget = observedTargets.find((candidate) => candidate.scope === representativeScope) ?? target;
2479
+ const components = [
2480
+ {
2481
+ kind: 'intent',
2482
+ key: 'desired',
2483
+ state: desiredEnabled ? 'desired' : 'absent',
2484
+ metadata: {
2485
+ enabled: desiredEnabled,
2486
+ scopes: desired.scopes,
2487
+ relation: desired.relation,
2488
+ },
2489
+ },
2490
+ ...ownershipComponents.map((component) => ({
2491
+ kind: 'ownership',
2492
+ key: component.key,
2493
+ state: component.key === 'native'
2494
+ && component.state === 'absent'
2495
+ && sharedNative?.staleCacheObserved
2496
+ ? 'partial'
2497
+ : component.state,
2498
+ ...(component.error ? { metadata: { errorCode: component.error.code } } : {}),
2499
+ })),
2500
+ ...(sharedNative ? [{
2501
+ kind: 'sharedNative',
2502
+ key: sharedNative.pluginId,
2503
+ state: sharedNative.state,
2504
+ metadata: {
2505
+ shared: true,
2506
+ ...(sharedNative.reason ? { reason: sharedNative.reason } : {}),
2507
+ ...(sharedNative.version ? { version: sharedNative.version } : {}),
2508
+ ...(sharedNative.desiredVersion ? { desiredVersion: sharedNative.desiredVersion } : {}),
2509
+ ...(sharedNative.diagnostic ? { diagnostic: sharedNative.diagnostic } : {}),
2510
+ ...(sharedNative.staleCacheObserved ? { staleCacheObserved: true } : {}),
2511
+ },
2512
+ }] : []),
2513
+ ...['user', 'project'].flatMap((scope) => activation?.[scope] === undefined ? [] : [{
2514
+ kind: 'activation',
2515
+ key: scope,
2516
+ state: activation[scope] ? 'enabled' : 'disabled',
2517
+ metadata: {
2518
+ evidence: activation.evidence,
2519
+ ...(activation.effective !== undefined ? { effective: activation.effective } : {}),
2520
+ },
2521
+ }]),
2522
+ ...(activation?.systemConsumer ? [{
2523
+ kind: 'systemConsumer',
2524
+ key: `codex:${representativeScope}`,
2525
+ state: activation.systemConsumer.state,
2526
+ metadata: {
2527
+ evidence: activation.evidence,
2528
+ requiredMinVersion: activation.systemConsumer.requiredMinVersion,
2529
+ ...('detectedVersion' in activation.systemConsumer
2530
+ ? { detectedVersion: activation.systemConsumer.detectedVersion }
2531
+ : {}),
2532
+ ...('code' in activation.systemConsumer ? { code: activation.systemConsumer.code } : {}),
2533
+ ...('diagnostic' in activation.systemConsumer
2534
+ ? { diagnostic: activation.systemConsumer.diagnostic }
2535
+ : {}),
2536
+ },
2537
+ }] : []),
2538
+ ...(extensions ? [{
2539
+ kind: 'extension',
2540
+ key: 'aw',
2541
+ state: extensions.state,
2542
+ metadata: { kinds: extensions.kinds },
2543
+ }] : []),
2544
+ ...(representativeTarget.dependencyReadiness ?? []).map((dependency) => ({
2545
+ kind: 'dependency',
2546
+ key: dependency.dependencyPluginId,
2547
+ state: dependency.state,
2548
+ metadata: {
2549
+ platform: dependency.dependencyPlatform,
2550
+ scope: dependency.dependencyScope,
2551
+ project: dependency.dependencyProject ?? 'none',
2552
+ ...(dependency.rootIssueId ? { rootIssueId: dependency.rootIssueId } : {}),
2553
+ ...(dependency.rootIssueCode ? { rootIssueCode: dependency.rootIssueCode } : {}),
2554
+ },
2555
+ })),
2556
+ ];
2557
+ const { state: _ownershipState, components: _ownershipComponents, errors: _errors, sharedNative: _sharedNative, activation: _activation, extensions: _extensions, dependency: _dependency, dependencyReadiness: _dependencyReadiness, ...identity } = target;
2558
+ return {
2559
+ ...identity,
2560
+ scope: representativeScope,
2561
+ state,
2562
+ components,
2563
+ reasons: dedupedErrors,
2564
+ recoveryActions: projectDisablesUserActivation && state === 'needsSync' ? [{
2565
+ command: 'sync', scope: 'user',
2566
+ description: '移除当前项目的关闭设置,恢复使用所有项目已启用的插件。',
2567
+ }] : statusRecovery({
2568
+ state,
2569
+ desired,
2570
+ platform: target.platform,
2571
+ pluginId: target.pluginId,
2572
+ ...(dependencyMoves.length > 0 ? { dependencyMoves } : {}),
2573
+ ...(sharedNative ? { sharedNative } : {}),
2574
+ scope: target.scope,
2575
+ actualEnabled: actualScopeEnabled,
2576
+ conflictRoots: rootIntentsForTarget({
2577
+ pluginId: target.pluginId,
2578
+ platform: target.platform,
2579
+ userIntent,
2580
+ projectIntent,
2581
+ available,
2582
+ }),
2583
+ errorCodes: dedupedErrors.map((error) => error.code),
2584
+ }).map((action) => action.command === 'manual' || action.scope
2585
+ ? action
2586
+ : { ...action, scope: representativeScope }),
2587
+ };
2588
+ };
2589
+ const codexGroups = new Map();
2590
+ const projectedTargets = [];
2591
+ for (const target of draftTargets) {
2592
+ if (target.platform !== 'codex') {
2593
+ projectedTargets.push(await decorateTarget(target, [target.scope], [target]));
2594
+ continue;
2595
+ }
2596
+ const group = codexGroups.get(target.pluginId) ?? [];
2597
+ group.push(target);
2598
+ codexGroups.set(target.pluginId, group);
2599
+ }
2600
+ for (const group of codexGroups.values()) {
2601
+ const decorated = await Promise.all(group.map((target) => decorateTarget(target, [target.scope], [target])));
2602
+ const first = decorated[0];
2603
+ const entry = selectedByPluginId.get(first.pluginId);
2604
+ const desired = desiredTargetStates.get(desiredTargetKey(first.pluginId, 'codex'))
2605
+ ?? { scopes: [], relation: 'none' };
2606
+ const returnedScopes = new Set(decorated.map((target) => target.scope));
2607
+ const desiredOverlapConflict = (entry?.codex?.extensionKinds.length ?? 0) > 0
2608
+ && desired.scopes.includes('user')
2609
+ && desired.scopes.includes('project')
2610
+ && returnedScopes.has('user')
2611
+ && returnedScopes.has('project');
2612
+ const sharedComponents = [...new Map(decorated.flatMap((target) => target.components)
2613
+ .filter((component) => component.kind === 'sharedNative' || component.kind === 'systemConsumer')
2614
+ .map((component) => [`${component.kind}\0${component.key}`, component])).values()];
2615
+ const sharedReason = (reason) => reason.code.startsWith('codexSharedNative') || reason.code === 'staleCacheObserved';
2616
+ const sharedReasons = decorated.flatMap((target) => target.reasons.filter(sharedReason));
2617
+ const placements = decorated.map((target) => ({
2618
+ scope: target.scope,
2619
+ state: target.state,
2620
+ components: target.components.filter((component) => component.kind !== 'sharedNative' && component.kind !== 'systemConsumer'),
2621
+ reasons: target.reasons.filter((reason) => !sharedReason(reason)),
2622
+ recoveryActions: target.recoveryActions,
2623
+ })).sort((left, right) => left.scope.localeCompare(right.scope, 'en'));
2624
+ const reasons = [...new Map([
2625
+ ...placements.flatMap((placement) => placement.reasons),
2626
+ ...sharedReasons,
2627
+ ...(desiredOverlapConflict ? [blocking('codexExtensionScopeConflict', `${first.pluginId} has AW extensions desired at user and project scope.`)] : []),
2628
+ ]
2629
+ .map((reason) => [`${reason.code}\0${reason.message}`, reason])).values()];
2630
+ const conflictRecovery = desiredOverlapConflict ? statusRecovery({
2631
+ state: 'blocked',
2632
+ desired,
2633
+ platform: 'codex',
2634
+ pluginId: first.pluginId,
2635
+ conflictRoots: rootIntentsForTarget({
2636
+ pluginId: first.pluginId,
2637
+ platform: 'codex',
2638
+ userIntent,
2639
+ projectIntent,
2640
+ available,
2641
+ }),
2642
+ errorCodes: ['codexExtensionScopeConflict'],
2643
+ }) : [];
2644
+ const recoveryActions = [...new Map((desiredOverlapConflict
2645
+ ? conflictRecovery
2646
+ : placements.flatMap((placement) => placement.recoveryActions))
2647
+ .map((action) => [
2648
+ `${action.command}\0${action.scope ?? ''}\0${action.description}`,
2649
+ action,
2650
+ ])).values()];
2651
+ const state = desiredOverlapConflict ? 'blocked'
2652
+ : ['blocked', 'needsSync', 'orphaned', 'ready', 'absent']
2653
+ .find((candidate) => placements.some((placement) => placement.state === candidate));
2654
+ projectedTargets.push({
2655
+ pluginName: first.pluginName,
2656
+ sourceId: first.sourceId,
2657
+ sourceIdentity: first.sourceIdentity,
2658
+ pluginId: first.pluginId,
2659
+ ...(first.version ? { version: first.version } : {}),
2660
+ platform: 'codex',
2661
+ cwd: first.cwd,
2662
+ state,
2663
+ components: sharedComponents,
2664
+ reasons,
2665
+ recoveryActions,
2666
+ placements,
2667
+ });
2668
+ }
2669
+ projectedTargets.sort((left, right) => `${left.pluginId}\0${left.platform}`.localeCompare(`${right.pluginId}\0${right.platform}`, 'en'));
2670
+ const targetRevisions = projectedTargets.flatMap((target) => {
2671
+ const entry = selectedByPluginId.get(target.pluginId);
2672
+ const placements = target.platform === 'codex' ? target.placements : [target];
2673
+ return placements.map((placement) => ({
2674
+ pluginId: target.pluginId,
2675
+ platform: target.platform,
2676
+ scope: placement.scope,
2677
+ revision: projectTargetRevision(entry?.version, entry?.states[target.platform]?.[placement.scope]?.installedVersion),
2678
+ }));
2679
+ });
2680
+ const publicConfigIssues = available.flatMap((entry) => (entry.configIssues ?? [])
2681
+ .filter((issue) => issue.type === 'configLayerUnsupported')
2682
+ .map((issue) => ({
2683
+ pluginId: formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
2684
+ pluginName: entry.name,
2685
+ ...issue,
2686
+ })));
2687
+ const payload = {
2688
+ schemaVersion: 8,
2689
+ catalog: {
2690
+ primarySourceId: catalog.primarySourceId,
2691
+ configDigest: catalog.configDigest,
2692
+ compositeDigest: catalog.compositeDigest,
2693
+ ...(options.catalogOperationContext
2694
+ ? { generationSetDigest: options.catalogOperationContext.generationSetDigest }
2695
+ : {}),
2696
+ sources: catalog.sources.map((source) => {
2697
+ if (!('plugins' in source))
2698
+ return source;
2699
+ const { plugins: _plugins, ...projected } = source;
2700
+ return projected;
2701
+ }),
2702
+ },
2703
+ filters: {
2704
+ plugins: requested,
2705
+ platform: options.platform === undefined ? 'both' : parsePlatformValue(options.platform),
2706
+ ...(options.scope === undefined ? {} : { scope: parseScopeValue(options.scope) }),
2707
+ cwd: path.resolve(options.cwd),
2708
+ },
2709
+ targets: projectedTargets,
2710
+ ...(publicConfigIssues.length > 0 ? { configIssues: publicConfigIssues } : {}),
2711
+ errors,
2712
+ };
2713
+ const hasErrors = payload.catalog.sources.some((source) => source.error !== undefined)
2714
+ || payload.errors.length > 0
2715
+ || payload.targets.some((target) => target.reasons.some((reason) => reason.severity === 'blocking'));
2716
+ return {
2717
+ payload,
2718
+ output: options.json ? JSON.stringify(payload) : renderStatusV8(payload, options.verbose === true),
2719
+ hasErrors,
2720
+ targetRevisions,
2721
+ ...(projectRoot ? { projectRoot } : {}),
2722
+ projectIntentObservation,
2723
+ pluginSummaries: available.map((entry) => {
2724
+ const sourceEntries = available.filter((candidate) => candidate.source.id === entry.source.id);
2725
+ const byName = new Map(sourceEntries.map((candidate) => [candidate.name, candidate]));
2726
+ const transitive = new Set();
2727
+ const visit = (name) => {
2728
+ const candidate = byName.get(name);
2729
+ for (const dependency of candidate?.dependencies ?? []) {
2730
+ if (transitive.has(dependency))
2731
+ continue;
2732
+ transitive.add(dependency);
2733
+ visit(dependency);
2734
+ }
2735
+ };
2736
+ visit(entry.name);
2737
+ const dependencyIssueCount = targets.filter((target) => target.pluginId === formatPluginId({
2738
+ sourceId: entry.source.id,
2739
+ pluginName: entry.name,
2740
+ })).reduce((count, target) => count + target.errors.filter((error) => error.code.startsWith('dependency')
2741
+ || error.code === 'awCapabilityUnsupported'
2742
+ || error.code === 'sourceChanged').length, 0);
2743
+ return {
2744
+ pluginName: entry.name,
2745
+ pluginId: formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
2746
+ displayName: entry.displayName,
2747
+ description: entry.shortDescription,
2748
+ version: entry.version,
2749
+ supportedTargets: {
2750
+ codex: ['user', 'project'].filter((scope) => entry.targets.codex[scope]),
2751
+ claude: ['user', 'project'].filter((scope) => entry.targets.claude[scope]),
2752
+ },
2753
+ configFieldCount: Object.keys(entry.configSchema ?? {}).length,
2754
+ ...(entry.configSchema ? { configSchema: entry.configSchema } : {}),
2755
+ ...(entry.configIssues ? { configIssues: entry.configIssues } : {}),
2756
+ ...(entry.configDiagnostic ? { configDiagnostic: entry.configDiagnostic } : {}),
2757
+ dependencyDirectCount: entry.dependencies.length,
2758
+ dependencyTotalCount: transitive.size,
2759
+ dependencyIssueCount,
2760
+ ...(entry.missingCapabilities
2761
+ ? { missingCapabilities: entry.missingCapabilities }
2762
+ : {}),
2763
+ };
2764
+ }),
2765
+ };
2766
+ }
2767
+ export async function statusCommandV8(options) {
2768
+ if (options.codexObservationSession) {
2769
+ return statusCommandV8InSession({
2770
+ ...options,
2771
+ codexObservationSession: options.codexObservationSession,
2772
+ });
2773
+ }
2774
+ const env = options.env ?? process.env;
2775
+ const session = await createCodexNativeObservationSession({
2776
+ exactCwd: options.cwd,
2777
+ env,
2778
+ runner: options.nativeCliRunner ?? getDefaultNativeCliRunner(),
2779
+ });
2780
+ try {
2781
+ return await statusCommandV8InSession({ ...options, codexObservationSession: session });
2782
+ }
2783
+ finally {
2784
+ await session.dispose();
2785
+ }
2786
+ }
2787
+ //# sourceMappingURL=status-v6.js.map