@lesliechan721/aw 0.1.0-beta.6 → 0.1.0-beta.60

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