@lesliechan721/aw 0.1.0-beta.7 → 0.1.0-beta.9

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 (341) hide show
  1. package/dist/authoring/scripts/add-skill.mjs +4 -4
  2. package/dist/authoring/scripts/add-skill.mjs.map +1 -1
  3. package/dist/authoring/scripts/init-plugin.mjs +8 -37
  4. package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
  5. package/dist/authoring/scripts/lib/plugin-version-check.mjs +1 -1
  6. package/dist/authoring/scripts/lib/skill-scaffold.d.mts +77 -90
  7. package/dist/authoring/scripts/lib/skill-scaffold.mjs +99 -120
  8. package/dist/authoring/scripts/lib/skill-scaffold.mjs.map +1 -1
  9. package/dist/authoring/scripts/plugin-status.mjs +8 -11
  10. package/dist/authoring/scripts/plugin-status.mjs.map +1 -1
  11. package/dist/authoring/scripts/remove-plugin.mjs +2 -1
  12. package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
  13. package/dist/authoring/scripts/validate-plugin.mjs +64 -758
  14. package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
  15. package/dist/scripts/aw-skill-eval-materializer.d.ts +24 -0
  16. package/dist/scripts/{plugin-eval-materializer.js → aw-skill-eval-materializer.js} +34 -145
  17. package/dist/scripts/aw-skill-eval-materializer.js.map +1 -0
  18. package/dist/scripts/bundle-plugins.d.ts +1 -0
  19. package/dist/scripts/bundle-plugins.js +2 -1
  20. package/dist/scripts/bundle-plugins.js.map +1 -1
  21. package/dist/scripts/plugin-staging.d.ts +6 -8
  22. package/dist/scripts/plugin-staging.js +15 -28
  23. package/dist/scripts/plugin-staging.js.map +1 -1
  24. package/dist/scripts/test-plugin-scripts.js +2 -33
  25. package/dist/scripts/test-plugin-scripts.js.map +1 -1
  26. package/dist/src/adapters/helpers.js +2 -2
  27. package/dist/src/adapters/helpers.js.map +1 -1
  28. package/dist/src/authoring/workspace-commands.d.ts +17 -1
  29. package/dist/src/authoring/workspace-commands.js +21 -4
  30. package/dist/src/authoring/workspace-commands.js.map +1 -1
  31. package/dist/src/commands/aw-capabilities.d.ts +78 -0
  32. package/dist/src/commands/aw-capabilities.js +254 -0
  33. package/dist/src/commands/aw-capabilities.js.map +1 -0
  34. package/dist/src/commands/catalog-dev-source.d.ts +118 -0
  35. package/dist/src/commands/catalog-dev-source.js +417 -0
  36. package/dist/src/commands/catalog-dev-source.js.map +1 -0
  37. package/dist/src/commands/catalog-generation.d.ts +13 -0
  38. package/dist/src/commands/catalog-generation.js +13 -0
  39. package/dist/src/commands/catalog-generation.js.map +1 -0
  40. package/dist/src/commands/catalog-publication-inspection.d.ts +29 -28
  41. package/dist/src/commands/catalog-publication-inspection.js +138 -50
  42. package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
  43. package/dist/src/commands/catalog-publication-journal.d.ts +49 -0
  44. package/dist/src/commands/catalog-publication-journal.js +147 -0
  45. package/dist/src/commands/catalog-publication-journal.js.map +1 -0
  46. package/dist/src/commands/catalog-publication-target.d.ts +18 -0
  47. package/dist/src/commands/catalog-publication-target.js +95 -0
  48. package/dist/src/commands/catalog-publication-target.js.map +1 -0
  49. package/dist/src/commands/catalog-publish.d.ts +58 -15
  50. package/dist/src/commands/catalog-publish.js +590 -210
  51. package/dist/src/commands/catalog-publish.js.map +1 -1
  52. package/dist/src/commands/catalog-source.d.ts +12 -15
  53. package/dist/src/commands/catalog-source.js +61 -86
  54. package/dist/src/commands/catalog-source.js.map +1 -1
  55. package/dist/src/commands/catalog-status.d.ts +18 -22
  56. package/dist/src/commands/catalog-status.js +81 -115
  57. package/dist/src/commands/catalog-status.js.map +1 -1
  58. package/dist/src/commands/catalog-workspace-resolution.d.ts +13 -0
  59. package/dist/src/commands/catalog-workspace-resolution.js +42 -0
  60. package/dist/src/commands/catalog-workspace-resolution.js.map +1 -0
  61. package/dist/src/commands/dependency-operation-plan.d.ts +88 -9
  62. package/dist/src/commands/dependency-operation-plan.js +331 -6
  63. package/dist/src/commands/dependency-operation-plan.js.map +1 -1
  64. package/dist/src/commands/init.d.ts +5 -11
  65. package/dist/src/commands/init.js +30 -51
  66. package/dist/src/commands/init.js.map +1 -1
  67. package/dist/src/commands/offline-cleanup-evidence.d.ts +43 -0
  68. package/dist/src/commands/offline-cleanup-evidence.js +116 -0
  69. package/dist/src/commands/offline-cleanup-evidence.js.map +1 -0
  70. package/dist/src/commands/options.d.ts +7 -1
  71. package/dist/src/commands/options.js +65 -6
  72. package/dist/src/commands/options.js.map +1 -1
  73. package/dist/src/commands/plugin-capabilities.js +5 -1
  74. package/dist/src/commands/plugin-capabilities.js.map +1 -1
  75. package/dist/src/commands/rebuild-command.d.ts +27 -13
  76. package/dist/src/commands/rebuild-command.js +1472 -471
  77. package/dist/src/commands/rebuild-command.js.map +1 -1
  78. package/dist/src/commands/rebuild-integration.d.ts +63 -8
  79. package/dist/src/commands/rebuild-integration.js +761 -439
  80. package/dist/src/commands/rebuild-integration.js.map +1 -1
  81. package/dist/src/commands/rebuild-operations.d.ts +2 -8
  82. package/dist/src/commands/rebuild-operations.js +48 -132
  83. package/dist/src/commands/rebuild-operations.js.map +1 -1
  84. package/dist/src/commands/runtime.js +21 -34
  85. package/dist/src/commands/runtime.js.map +1 -1
  86. package/dist/src/commands/skill-eval.d.ts +33 -0
  87. package/dist/src/commands/skill-eval.js +363 -0
  88. package/dist/src/commands/skill-eval.js.map +1 -0
  89. package/dist/src/commands/status-v6.d.ts +202 -0
  90. package/dist/src/commands/status-v6.js +1938 -0
  91. package/dist/src/commands/status-v6.js.map +1 -0
  92. package/dist/src/commands/sync-command.d.ts +21 -0
  93. package/dist/src/commands/sync-command.js +206 -0
  94. package/dist/src/commands/sync-command.js.map +1 -0
  95. package/dist/src/commands/wizard.d.ts +2 -2
  96. package/dist/src/commands/wizard.js +2 -2
  97. package/dist/src/commands/wizard.js.map +1 -1
  98. package/dist/src/commands/write-commands.js +33 -19
  99. package/dist/src/commands/write-commands.js.map +1 -1
  100. package/dist/src/constants.d.ts +7 -1
  101. package/dist/src/constants.js +7 -1
  102. package/dist/src/constants.js.map +1 -1
  103. package/dist/src/eval/manifest-v1.d.ts +66 -0
  104. package/dist/src/eval/manifest-v1.js +326 -0
  105. package/dist/src/eval/manifest-v1.js.map +1 -0
  106. package/dist/src/generators/local-plugin.d.ts +3 -0
  107. package/dist/src/generators/local-plugin.js +167 -45
  108. package/dist/src/generators/local-plugin.js.map +1 -1
  109. package/dist/src/index.d.ts +6 -1
  110. package/dist/src/index.js +863 -126
  111. package/dist/src/index.js.map +1 -1
  112. package/dist/src/output/command-receipt.d.ts +58 -8
  113. package/dist/src/output/command-receipt.js +141 -11
  114. package/dist/src/output/command-receipt.js.map +1 -1
  115. package/dist/src/output/model.d.ts +3 -44
  116. package/dist/src/output/model.js +1 -144
  117. package/dist/src/output/model.js.map +1 -1
  118. package/dist/src/output/rebuild-progress.js +0 -3
  119. package/dist/src/output/rebuild-progress.js.map +1 -1
  120. package/dist/src/portable/commands.d.ts +6 -2
  121. package/dist/src/portable/commands.js +57 -6
  122. package/dist/src/portable/commands.js.map +1 -1
  123. package/dist/src/portable/materializer.d.ts +4 -4
  124. package/dist/src/portable/materializer.js +61 -12
  125. package/dist/src/portable/materializer.js.map +1 -1
  126. package/dist/src/tui/catalog-generation.d.ts +35 -0
  127. package/dist/src/tui/catalog-generation.js +85 -0
  128. package/dist/src/tui/catalog-generation.js.map +1 -0
  129. package/dist/src/tui/components.js +1 -2
  130. package/dist/src/tui/components.js.map +1 -1
  131. package/dist/src/tui/console-app-v4.d.ts +1 -1
  132. package/dist/src/tui/console-app-v4.js +647 -196
  133. package/dist/src/tui/console-app-v4.js.map +1 -1
  134. package/dist/src/tui/controller-runtime.d.ts +6 -2
  135. package/dist/src/tui/controller-runtime.js +646 -137
  136. package/dist/src/tui/controller-runtime.js.map +1 -1
  137. package/dist/src/tui/controller.d.ts +77 -15
  138. package/dist/src/tui/controller.js +647 -306
  139. package/dist/src/tui/controller.js.map +1 -1
  140. package/dist/src/tui/diagnostics.d.ts +1 -2
  141. package/dist/src/tui/diagnostics.js.map +1 -1
  142. package/dist/src/tui/index.d.ts +1 -0
  143. package/dist/src/tui/index.js +1 -0
  144. package/dist/src/tui/index.js.map +1 -1
  145. package/dist/src/tui/input-display.d.ts +8 -0
  146. package/dist/src/tui/input-display.js +36 -0
  147. package/dist/src/tui/input-display.js.map +1 -0
  148. package/dist/src/tui/model.d.ts +102 -14
  149. package/dist/src/tui/model.js +630 -139
  150. package/dist/src/tui/model.js.map +1 -1
  151. package/dist/src/tui/router.d.ts +35 -0
  152. package/dist/src/tui/router.js.map +1 -1
  153. package/dist/src/tui/source-ref-presets.d.ts +3 -0
  154. package/dist/src/tui/source-ref-presets.js +11 -0
  155. package/dist/src/tui/source-ref-presets.js.map +1 -0
  156. package/dist/src/tui/views.js +31 -3
  157. package/dist/src/tui/views.js.map +1 -1
  158. package/dist/src/types.d.ts +104 -13
  159. package/dist/src/types.js.map +1 -1
  160. package/dist/src/utils/agent-version.d.ts +7 -1
  161. package/dist/src/utils/agent-version.js +41 -8
  162. package/dist/src/utils/agent-version.js.map +1 -1
  163. package/dist/src/utils/aw-home-mutation-lock.d.ts +1 -0
  164. package/dist/src/utils/aw-home-mutation-lock.js +32 -4
  165. package/dist/src/utils/aw-home-mutation-lock.js.map +1 -1
  166. package/dist/src/utils/bundle-integrity.d.ts +0 -1
  167. package/dist/src/utils/bundle-integrity.js +0 -25
  168. package/dist/src/utils/bundle-integrity.js.map +1 -1
  169. package/dist/src/utils/bundle-layout.js +8 -6
  170. package/dist/src/utils/bundle-layout.js.map +1 -1
  171. package/dist/src/utils/catalog-digests.d.ts +7 -0
  172. package/dist/src/utils/catalog-digests.js +40 -2
  173. package/dist/src/utils/catalog-digests.js.map +1 -1
  174. package/dist/src/utils/catalog-generation-control-snapshot.d.ts +11 -0
  175. package/dist/src/utils/catalog-generation-control-snapshot.js +45 -0
  176. package/dist/src/utils/catalog-generation-control-snapshot.js.map +1 -0
  177. package/dist/src/utils/catalog-generation-error.d.ts +13 -0
  178. package/dist/src/utils/catalog-generation-error.js +28 -0
  179. package/dist/src/utils/catalog-generation-error.js.map +1 -0
  180. package/dist/src/utils/catalog-generation-resolver.d.ts +20 -0
  181. package/dist/src/utils/catalog-generation-resolver.js +143 -0
  182. package/dist/src/utils/catalog-generation-resolver.js.map +1 -0
  183. package/dist/src/utils/catalog-generation-service.d.ts +43 -0
  184. package/dist/src/utils/catalog-generation-service.js +306 -0
  185. package/dist/src/utils/catalog-generation-service.js.map +1 -0
  186. package/dist/src/utils/catalog-generation-state.d.ts +17 -0
  187. package/dist/src/utils/catalog-generation-state.js +168 -0
  188. package/dist/src/utils/catalog-generation-state.js.map +1 -0
  189. package/dist/src/utils/catalog-generation-store.d.ts +34 -0
  190. package/dist/src/utils/catalog-generation-store.js +251 -0
  191. package/dist/src/utils/catalog-generation-store.js.map +1 -0
  192. package/dist/src/utils/catalog-manifest-v6.d.ts +5 -0
  193. package/dist/src/utils/{catalog-manifest-v4.js → catalog-manifest-v6.js} +35 -43
  194. package/dist/src/utils/catalog-manifest-v6.js.map +1 -0
  195. package/dist/src/utils/catalog-operation-context.d.ts +20 -0
  196. package/dist/src/utils/catalog-operation-context.js +141 -0
  197. package/dist/src/utils/catalog-operation-context.js.map +1 -0
  198. package/dist/src/utils/catalog-public-error.d.ts +7 -3
  199. package/dist/src/utils/catalog-public-error.js +21 -8
  200. package/dist/src/utils/catalog-public-error.js.map +1 -1
  201. package/dist/src/utils/catalog-runtime-projection.d.ts +3 -0
  202. package/dist/src/utils/catalog-runtime-projection.js +5 -40
  203. package/dist/src/utils/catalog-runtime-projection.js.map +1 -1
  204. package/dist/src/utils/catalog-snapshot.d.ts +5 -3
  205. package/dist/src/utils/catalog-snapshot.js +11 -3
  206. package/dist/src/utils/catalog-snapshot.js.map +1 -1
  207. package/dist/src/utils/catalog-source-identity.d.ts +1 -0
  208. package/dist/src/utils/catalog-source-identity.js +21 -2
  209. package/dist/src/utils/catalog-source-identity.js.map +1 -1
  210. package/dist/src/utils/catalog-source-references.d.ts +7 -0
  211. package/dist/src/utils/catalog-source-references.js +44 -55
  212. package/dist/src/utils/catalog-source-references.js.map +1 -1
  213. package/dist/src/utils/catalog-sources.d.ts +1 -0
  214. package/dist/src/utils/catalog-sources.js +55 -20
  215. package/dist/src/utils/catalog-sources.js.map +1 -1
  216. package/dist/src/utils/codex-config.d.ts +2 -0
  217. package/dist/src/utils/codex-config.js +26 -5
  218. package/dist/src/utils/codex-config.js.map +1 -1
  219. package/dist/src/utils/codex-manager.d.ts +81 -0
  220. package/dist/src/utils/codex-manager.js +810 -0
  221. package/dist/src/utils/codex-manager.js.map +1 -0
  222. package/dist/src/utils/codex-reconciler.d.ts +131 -0
  223. package/dist/src/utils/codex-reconciler.js +327 -0
  224. package/dist/src/utils/codex-reconciler.js.map +1 -0
  225. package/dist/src/utils/codex-shared-native.d.ts +56 -0
  226. package/dist/src/utils/codex-shared-native.js +87 -0
  227. package/dist/src/utils/codex-shared-native.js.map +1 -0
  228. package/dist/src/utils/codex-skill-staging.d.ts +2 -0
  229. package/dist/src/utils/codex-skill-staging.js.map +1 -1
  230. package/dist/src/utils/codex-surface-analysis.d.ts +44 -0
  231. package/dist/src/utils/codex-surface-analysis.js +247 -0
  232. package/dist/src/utils/codex-surface-analysis.js.map +1 -0
  233. package/dist/src/utils/dynamic-skill-tree.d.ts +4 -0
  234. package/dist/src/utils/dynamic-skill-tree.js +35 -5
  235. package/dist/src/utils/dynamic-skill-tree.js.map +1 -1
  236. package/dist/src/utils/git-catalog-provider.js +66 -140
  237. package/dist/src/utils/git-catalog-provider.js.map +1 -1
  238. package/dist/src/utils/lifecycle-active-store.d.ts +0 -28
  239. package/dist/src/utils/lifecycle-active-store.js +35 -247
  240. package/dist/src/utils/lifecycle-active-store.js.map +1 -1
  241. package/dist/src/utils/manifest.d.ts +1 -3
  242. package/dist/src/utils/manifest.js +1 -3
  243. package/dist/src/utils/manifest.js.map +1 -1
  244. package/dist/src/utils/multi-source-catalog.d.ts +3 -9
  245. package/dist/src/utils/multi-source-catalog.js +53 -110
  246. package/dist/src/utils/multi-source-catalog.js.map +1 -1
  247. package/dist/src/utils/native-cli.d.ts +49 -6
  248. package/dist/src/utils/native-cli.js +116 -33
  249. package/dist/src/utils/native-cli.js.map +1 -1
  250. package/dist/src/utils/orphan-marketplace-cleanup.js +1 -3
  251. package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
  252. package/dist/src/utils/ownership.d.ts +10 -11
  253. package/dist/src/utils/ownership.js +55 -112
  254. package/dist/src/utils/ownership.js.map +1 -1
  255. package/dist/src/utils/path-catalog-provider.d.ts +1 -1
  256. package/dist/src/utils/path-catalog-provider.js +52 -65
  257. package/dist/src/utils/path-catalog-provider.js.map +1 -1
  258. package/dist/src/utils/paths.d.ts +0 -1
  259. package/dist/src/utils/paths.js +0 -1
  260. package/dist/src/utils/paths.js.map +1 -1
  261. package/dist/src/utils/plugin-config-write.js +18 -40
  262. package/dist/src/utils/plugin-config-write.js.map +1 -1
  263. package/dist/src/utils/plugin-config.d.ts +1 -12
  264. package/dist/src/utils/plugin-config.js +107 -226
  265. package/dist/src/utils/plugin-config.js.map +1 -1
  266. package/dist/src/utils/plugin-intent-state.d.ts +39 -0
  267. package/dist/src/utils/plugin-intent-state.js +325 -0
  268. package/dist/src/utils/plugin-intent-state.js.map +1 -0
  269. package/dist/src/utils/plugin-scripts.d.ts +1 -1
  270. package/dist/src/utils/plugin-scripts.js +1 -1
  271. package/dist/src/utils/plugin-scripts.js.map +1 -1
  272. package/dist/src/utils/state-paths.js +7 -2
  273. package/dist/src/utils/state-paths.js.map +1 -1
  274. package/dist/src/utils/target-eligibility.d.ts +8 -2
  275. package/dist/src/utils/target-eligibility.js +9 -5
  276. package/dist/src/utils/target-eligibility.js.map +1 -1
  277. package/package.json +6 -4
  278. package/dist/authoring/scripts/check-plugin-versions.d.mts +0 -2
  279. package/dist/authoring/scripts/check-plugin-versions.mjs +0 -5
  280. package/dist/authoring/scripts/check-plugin-versions.mjs.map +0 -1
  281. package/dist/scripts/aw-skill-eval-engine.d.ts +0 -13
  282. package/dist/scripts/aw-skill-eval-engine.js +0 -31
  283. package/dist/scripts/aw-skill-eval-engine.js.map +0 -1
  284. package/dist/scripts/codex-eval-app-server.d.ts +0 -89
  285. package/dist/scripts/codex-eval-app-server.js +0 -1228
  286. package/dist/scripts/codex-eval-app-server.js.map +0 -1
  287. package/dist/scripts/codex-eval-isolation.d.ts +0 -61
  288. package/dist/scripts/codex-eval-isolation.js +0 -318
  289. package/dist/scripts/codex-eval-isolation.js.map +0 -1
  290. package/dist/scripts/codex-eval-process-management.d.ts +0 -8
  291. package/dist/scripts/codex-eval-process-management.js +0 -69
  292. package/dist/scripts/codex-eval-process-management.js.map +0 -1
  293. package/dist/scripts/codex-eval-process-tree.d.ts +0 -38
  294. package/dist/scripts/codex-eval-process-tree.js +0 -803
  295. package/dist/scripts/codex-eval-process-tree.js.map +0 -1
  296. package/dist/scripts/codex-eval-runtime-config.d.ts +0 -62
  297. package/dist/scripts/codex-eval-runtime-config.js +0 -843
  298. package/dist/scripts/codex-eval-runtime-config.js.map +0 -1
  299. package/dist/scripts/codex-trigger-eval.d.ts +0 -84
  300. package/dist/scripts/codex-trigger-eval.js +0 -968
  301. package/dist/scripts/codex-trigger-eval.js.map +0 -1
  302. package/dist/scripts/eval-plugin-skills-audited.d.ts +0 -6
  303. package/dist/scripts/eval-plugin-skills-audited.js +0 -261
  304. package/dist/scripts/eval-plugin-skills-audited.js.map +0 -1
  305. package/dist/scripts/eval-plugin-skills.d.ts +0 -45
  306. package/dist/scripts/eval-plugin-skills.js +0 -1586
  307. package/dist/scripts/eval-plugin-skills.js.map +0 -1
  308. package/dist/scripts/eval-run-layout.d.ts +0 -17
  309. package/dist/scripts/eval-run-layout.js +0 -26
  310. package/dist/scripts/eval-run-layout.js.map +0 -1
  311. package/dist/scripts/plugin-eval-contract.d.ts +0 -185
  312. package/dist/scripts/plugin-eval-contract.js +0 -695
  313. package/dist/scripts/plugin-eval-contract.js.map +0 -1
  314. package/dist/scripts/plugin-eval-materializer.d.ts +0 -13
  315. package/dist/scripts/plugin-eval-materializer.js.map +0 -1
  316. package/dist/scripts/skill-reporting.d.ts +0 -212
  317. package/dist/scripts/skill-reporting.js +0 -922
  318. package/dist/scripts/skill-reporting.js.map +0 -1
  319. package/dist/src/commands/status-v4.d.ts +0 -123
  320. package/dist/src/commands/status-v4.js +0 -905
  321. package/dist/src/commands/status-v4.js.map +0 -1
  322. package/dist/src/commands/status.d.ts +0 -93
  323. package/dist/src/commands/status.js +0 -442
  324. package/dist/src/commands/status.js.map +0 -1
  325. package/dist/src/utils/active-marketplace-runtime-lock.d.ts +0 -12
  326. package/dist/src/utils/active-marketplace-runtime-lock.js +0 -133
  327. package/dist/src/utils/active-marketplace-runtime-lock.js.map +0 -1
  328. package/dist/src/utils/catalog-manifest-v3.d.ts +0 -2
  329. package/dist/src/utils/catalog-manifest-v3.js +0 -3
  330. package/dist/src/utils/catalog-manifest-v3.js.map +0 -1
  331. package/dist/src/utils/catalog-manifest-v4.d.ts +0 -5
  332. package/dist/src/utils/catalog-manifest-v4.js.map +0 -1
  333. package/dist/src/utils/catalog-source-cache.d.ts +0 -62
  334. package/dist/src/utils/catalog-source-cache.js +0 -296
  335. package/dist/src/utils/catalog-source-cache.js.map +0 -1
  336. package/dist/src/utils/codex-project-surface.d.ts +0 -3
  337. package/dist/src/utils/codex-project-surface.js +0 -49
  338. package/dist/src/utils/codex-project-surface.js.map +0 -1
  339. package/dist/src/utils/plugin-release.d.ts +0 -2
  340. package/dist/src/utils/plugin-release.js +0 -2
  341. package/dist/src/utils/plugin-release.js.map +0 -1
@@ -0,0 +1,1938 @@
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 { readCatalogSourcesConfigSnapshot, resolveCatalogSourceRef } from '../utils/catalog-sources.js';
8
+ import { formatPluginId, parsePluginId, planPluginSelectorSourceIds, withResolvedMultiSourceCatalog, } from '../utils/multi-source-catalog.js';
9
+ import { assertStrictSemVer, checkAwCapabilitySupport, compareStrictSemVer, readPluginManifest, tryParseStrictSemVer, } from '../utils/manifest.js';
10
+ import { resolveCliPackageRoot, resolveCodexPaths } from '../utils/paths.js';
11
+ import { supportsPlatform } from '../utils/platform-support.js';
12
+ import { parsePlatformValue, parseScopeValue } from './options.js';
13
+ import { inspectCodexNativeResidue, inspectCodexSharedNativeLive, inspectRebuildTarget, } from './rebuild-integration.js';
14
+ import { createNoopReporter } from '../output/reporter.js';
15
+ import { createNoopDebugLogger } from '../output/debug-log.js';
16
+ import { getDefaultNativeCliRunner } from '../utils/native-cli.js';
17
+ import { resolveAwHome } from '../utils/paths.js';
18
+ import { codexProjectConfigAliasesUserHome, createProjectLocationKey, getClaudeHome, getCodexHome, resolveCanonicalRepoProjectKey, } from '../utils/state-paths.js';
19
+ import { resolveEffectivePluginConfig } from '../utils/plugin-config.js';
20
+ import { readCodexConfigFile } from '../utils/codex-config.js';
21
+ import { readPluginIntentState, } from '../utils/plugin-intent-state.js';
22
+ import { IMPLEMENTED_AW_CAPABILITIES } from './aw-capabilities.js';
23
+ import { createDependencyPlacementPlan } from './dependency-operation-plan.js';
24
+ import { calculateCodexSharedNativePayloadDigest } from '../utils/catalog-digests.js';
25
+ import { getCodexOperationRequirement } from '../utils/agent-version.js';
26
+ import { inspectSystemCodexFilesystem, } from '../utils/codex-manager.js';
27
+ let dependencyInspectionHookForTests;
28
+ export function setStatusDependencyInspectionHookForTests(hook) {
29
+ dependencyInspectionHookForTests = hook;
30
+ }
31
+ export async function loadConsoleItemsResult(options = {}, runtime = {}) {
32
+ const result = await statusCommandV6({
33
+ cwd: options.cwd ?? process.cwd(),
34
+ env: runtime.env,
35
+ platform: options.platform,
36
+ scope: options.scope,
37
+ verbose: options.verbose,
38
+ });
39
+ const groups = new Map();
40
+ const summaries = new Map(result.pluginSummaries.map((summary) => [summary.pluginId, summary]));
41
+ for (const target of result.payload.targets) {
42
+ const summary = summaries.get(target.pluginId);
43
+ let pluginSummary;
44
+ if (summary !== undefined) {
45
+ const { pluginName: _pluginName, pluginId: _pluginId, ...projected } = summary;
46
+ pluginSummary = projected;
47
+ }
48
+ const current = groups.get(target.pluginId) ?? {
49
+ pluginName: target.pluginId,
50
+ ...(target.version ? { version: target.version } : {}),
51
+ ...(pluginSummary ? { pluginSummary } : {}),
52
+ targets: [],
53
+ };
54
+ current.targets.push(target);
55
+ groups.set(target.pluginId, current);
56
+ }
57
+ const allSourcesFailed = result.payload.catalog.sources.length > 0
58
+ && result.payload.catalog.sources.every((source) => source.error !== undefined);
59
+ return {
60
+ items: [...groups.values()].sort((left, right) => left.pluginName.localeCompare(right.pluginName)),
61
+ catalogUnavailable: allSourcesFailed,
62
+ status: result.payload,
63
+ };
64
+ }
65
+ export async function loadConsoleItems(options = {}, runtime = {}) {
66
+ return (await loadConsoleItemsResult(options, runtime)).items;
67
+ }
68
+ function projectStateInventoryError(error, env, cwd) {
69
+ const sanitized = sanitizeCatalogSourceError(error, env, [
70
+ getCodexHome(env),
71
+ getClaudeHome(env),
72
+ path.resolve(cwd),
73
+ ]);
74
+ const native = /(?:Codex|Claude|config\.toml|settings|installed_plugins)/iu.test(sanitized.message);
75
+ const code = native ? 'nativeStateUnreadable' : 'stateInventoryFailed';
76
+ return { code, message: `${code}: ${sanitized.message}`, relevance: { global: true } };
77
+ }
78
+ function inventoryErrorMatchesSelection(options) {
79
+ const relevance = options.error.relevance;
80
+ if (relevance.global)
81
+ return true;
82
+ if (relevance.projectLocationKey
83
+ && relevance.projectLocationKey !== options.currentProjectLocationKey)
84
+ return false;
85
+ if (options.platformExplicit && relevance.platform
86
+ && !options.platforms.includes(relevance.platform))
87
+ return false;
88
+ if (options.scopeExplicit && relevance.scope
89
+ && !options.scopes.includes(relevance.scope))
90
+ return false;
91
+ if (options.selectors.length === 0 || (!relevance.sourceId && !relevance.pluginName))
92
+ return true;
93
+ return options.selectors.some((selector) => (!relevance.pluginName || selector.parsed.pluginName === relevance.pluginName)
94
+ && (!relevance.sourceId
95
+ || selector.parsed.sourceId === undefined
96
+ || selector.parsed.sourceId === relevance.sourceId));
97
+ }
98
+ function finalizeTargetError(error, targetState) {
99
+ return {
100
+ ...error,
101
+ severity: error.code === 'artifactCollision'
102
+ || (targetState === 'error'
103
+ && error.code !== 'awCapabilityUnsupported'
104
+ && error.dependencyPluginId === undefined)
105
+ ? 'blocking'
106
+ : 'warning',
107
+ };
108
+ }
109
+ function projectTargetError(error, env, cwd, targetState) {
110
+ const sanitized = sanitizeCatalogSourceError(new Error(error.message), env, [
111
+ getCodexHome(env),
112
+ getClaudeHome(env),
113
+ path.resolve(cwd),
114
+ ]);
115
+ return finalizeTargetError({ ...error, message: sanitized.message }, targetState);
116
+ }
117
+ function sourceRequestedRef(source, cliVersion) {
118
+ return source.type === 'git' ? resolveCatalogSourceRef(source.refPolicy, cliVersion) : 'path';
119
+ }
120
+ function selectedPlatforms(value) {
121
+ const selection = value === undefined ? 'both' : parsePlatformValue(value);
122
+ return selection === 'both' ? ['codex', 'claude'] : [selection];
123
+ }
124
+ function selectedScopes(value) {
125
+ return value === undefined ? ['user', 'project'] : [parseScopeValue(value)];
126
+ }
127
+ function emptyIntent() {
128
+ return {
129
+ schemaVersion: 1,
130
+ kind: 'aw-plugin-intents',
131
+ roots: [],
132
+ dependencyScopeOverrides: [],
133
+ managed: { codexPluginIds: [] },
134
+ };
135
+ }
136
+ function desiredTargetKey(pluginId, platform) {
137
+ return `${pluginId}\0${platform}`;
138
+ }
139
+ function calculateDesiredTargetStates(options) {
140
+ const desired = new Map();
141
+ const add = (pluginId, platform, scope, relation) => {
142
+ const key = desiredTargetKey(pluginId, platform);
143
+ const current = desired.get(key) ?? { scopes: new Set(), relation: 'none' };
144
+ current.scopes.add(scope);
145
+ if (relation === 'root' || (relation === 'dependency' && current.relation !== 'root')) {
146
+ current.relation = relation;
147
+ }
148
+ desired.set(key, current);
149
+ };
150
+ const byId = new Map(options.available.map((entry) => [
151
+ formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
152
+ entry,
153
+ ]));
154
+ for (const [scope, intent] of [
155
+ ['user', options.userIntent],
156
+ ['project', options.projectIntent],
157
+ ]) {
158
+ for (const root of intent.roots) {
159
+ for (const platform of root.platforms)
160
+ add(root.pluginId, platform, scope, 'root');
161
+ }
162
+ for (const platform of ['codex', 'claude']) {
163
+ const platformRoots = intent.roots.filter((root) => root.platforms.includes(platform) && byId.has(root.pluginId));
164
+ const closure = new Set();
165
+ const visit = (pluginId) => {
166
+ if (closure.has(pluginId))
167
+ return;
168
+ closure.add(pluginId);
169
+ const entry = byId.get(pluginId);
170
+ if (!entry)
171
+ return;
172
+ for (const dependency of entry.dependencies) {
173
+ visit(formatPluginId({ sourceId: entry.source.id, pluginName: dependency }));
174
+ }
175
+ };
176
+ for (const root of platformRoots)
177
+ visit(root.pluginId);
178
+ const nodes = [...closure].flatMap((pluginId) => {
179
+ const entry = byId.get(pluginId);
180
+ if (!entry || !entry.targets[platform].user && !entry.targets[platform].project)
181
+ return [];
182
+ const allowedScopes = [
183
+ ...(entry.targets[platform].project
184
+ && (platform !== 'codex' || options.codexProjectAllowed) ? ['project'] : []),
185
+ ...(entry.targets[platform].user ? ['user'] : []),
186
+ ];
187
+ return allowedScopes.length === 0 ? [] : [{
188
+ pluginId,
189
+ pluginName: entry.name,
190
+ platform,
191
+ relation: platformRoots.some((root) => root.pluginId === pluginId)
192
+ ? 'requested'
193
+ : 'dependency',
194
+ depth: platformRoots.some((root) => root.pluginId === pluginId) ? 0 : 1,
195
+ allowedScopes,
196
+ }];
197
+ });
198
+ const nodeIds = new Set(nodes.map((node) => node.pluginId));
199
+ const roots = platformRoots.flatMap((root) => nodeIds.has(root.pluginId)
200
+ ? [{ pluginId: root.pluginId, platform, scope }]
201
+ : []);
202
+ if (roots.length === 0)
203
+ continue;
204
+ const edges = nodes.flatMap((node) => {
205
+ const entry = byId.get(node.pluginId);
206
+ return entry.dependencies.flatMap((dependency) => {
207
+ const dependencyId = formatPluginId({
208
+ sourceId: entry.source.id,
209
+ pluginName: dependency,
210
+ });
211
+ return nodeIds.has(dependencyId)
212
+ ? [{ from: node.pluginId, to: dependencyId, platform }]
213
+ : [];
214
+ });
215
+ });
216
+ const plan = createDependencyPlacementPlan({
217
+ requestedPluginIds: roots.map((root) => root.pluginId),
218
+ nodes,
219
+ roots,
220
+ dependencyEdges: edges,
221
+ scopeOverrides: intent.dependencyScopeOverrides.filter((override) => nodeIds.has(override.pluginId)
222
+ && (override.platform === undefined || override.platform === platform)),
223
+ });
224
+ for (const target of plan.targets) {
225
+ add(target.pluginId, target.platform, target.resolvedScope, target.relation === 'requested' ? 'root' : 'dependency');
226
+ }
227
+ }
228
+ }
229
+ for (const intent of [options.userIntent, options.projectIntent]) {
230
+ for (const codexPluginId of intent.managed.codexPluginIds) {
231
+ for (const [pluginId, entry] of byId) {
232
+ if (entry.codex?.pluginId !== codexPluginId)
233
+ continue;
234
+ const key = desiredTargetKey(pluginId, 'codex');
235
+ if (!desired.has(key))
236
+ desired.set(key, { scopes: new Set(), relation: 'managed' });
237
+ }
238
+ }
239
+ }
240
+ return new Map([...desired].map(([key, value]) => [key, {
241
+ scopes: [...value.scopes].sort(),
242
+ relation: value.relation,
243
+ }]));
244
+ }
245
+ function statusRecovery(options) {
246
+ if (options.errorCodes?.some((code) => code === 'codexProjectPluginVersionTooLow'
247
+ || code === 'codexProjectPluginUnsupported'
248
+ || code === 'codexSystemCliUnsupported')) {
249
+ return [{
250
+ command: 'manual',
251
+ description: '升级或修复官方 system Codex CLI 后重试原操作。',
252
+ }];
253
+ }
254
+ if (options.actual === 'ready' || options.actual === 'absent')
255
+ return [];
256
+ if (options.actual === 'orphaned') {
257
+ return [{ command: 'cleanup', description: '清理可证明属于 AW 的遗留输出。' }];
258
+ }
259
+ if (options.actual === 'unresolved') {
260
+ return [
261
+ { command: 'sync', description: '来源恢复后同步 desired intent。' },
262
+ { command: 'cleanup', description: '来源无法恢复时清理可证明属于 AW 的输出。' },
263
+ ];
264
+ }
265
+ if (options.actual === 'conflict') {
266
+ if (options.desired.scopes.includes('user') && options.desired.scopes.includes('project')) {
267
+ return ['user', 'project'].flatMap((scope) => (options.conflictRoots?.[scope] ?? []).map((rootPluginId) => ({
268
+ command: 'uninstall',
269
+ scope,
270
+ description: `运行 aw uninstall ${rootPluginId} --platform ${options.platform} --scope ${scope},再运行 aw sync ${options.pluginId} --platform ${options.platform} --scope ${scope === 'user' ? 'project' : 'user'}。`,
271
+ })));
272
+ }
273
+ const collision = options.sharedNative?.state === 'foreign'
274
+ ? `Codex shared native ${options.sharedNative.pluginId}`
275
+ : `${options.pluginId} 的 foreign extension`;
276
+ return [
277
+ {
278
+ command: 'sync',
279
+ description: `先移除或重命名 ${collision},再运行 aw sync ${options.pluginId} --platform ${options.platform}。cleanup 会保留 foreign 内容,不会删除该冲突。`,
280
+ },
281
+ ];
282
+ }
283
+ return [{
284
+ command: options.actual === 'drifted' ? 'reinstall' : 'sync',
285
+ ...(options.desired.scopes.length === 1 ? { scope: options.desired.scopes[0] } : {}),
286
+ description: options.actual === 'drifted'
287
+ ? '重新安装以修复手动修改或损坏的现场。'
288
+ : '同步 desired intent 和当前现场。',
289
+ }];
290
+ }
291
+ function rootIntentsForTarget(options) {
292
+ const byId = new Map(options.available.map((entry) => [
293
+ formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
294
+ entry,
295
+ ]));
296
+ const result = {};
297
+ for (const [scope, intent] of [
298
+ ['user', options.userIntent],
299
+ ['project', options.projectIntent],
300
+ ]) {
301
+ const roots = intent.roots.filter((root) => {
302
+ if (!root.platforms.includes(options.platform))
303
+ return false;
304
+ const seen = new Set();
305
+ const reaches = (pluginId) => {
306
+ if (pluginId === options.pluginId)
307
+ return true;
308
+ if (seen.has(pluginId))
309
+ return false;
310
+ seen.add(pluginId);
311
+ const entry = byId.get(pluginId);
312
+ return entry?.dependencies.some((dependency) => reaches(formatPluginId({
313
+ sourceId: entry.source.id,
314
+ pluginName: dependency,
315
+ }))) === true;
316
+ };
317
+ return reaches(root.pluginId);
318
+ }).map((root) => root.pluginId).sort();
319
+ if (roots.length > 0)
320
+ result[scope] = roots;
321
+ }
322
+ return result;
323
+ }
324
+ function projectedLiveState(options) {
325
+ if (options.inspection.state === 'error'
326
+ || options.inspection.components.some((entry) => entry.state === 'error'))
327
+ return 'error';
328
+ const owned = options.inspection.components.filter((entry) => (entry.state === 'present' || entry.state === 'partial'));
329
+ if (owned.length === 0)
330
+ return 'absent';
331
+ if (owned.some((entry) => entry.state === 'partial'))
332
+ return 'partial';
333
+ const required = new Set(options.required);
334
+ const optional = new Set(options.optional);
335
+ if (options.inspection.components.some((entry) => entry.state === 'present' && !required.has(entry.component) && !optional.has(entry.component))) {
336
+ return 'partial';
337
+ }
338
+ if (!options.required.every((component) => options.inspection.components.some((entry) => entry.component === component && entry.state === 'present')))
339
+ return 'partial';
340
+ if (options.required.length > 0)
341
+ return 'present';
342
+ return options.optional.some((component) => options.inspection.components.some((entry) => entry.component === component && entry.state === 'present')) ? 'present' : 'absent';
343
+ }
344
+ export function projectTargetRevision(availableVersion, installedVersion) {
345
+ if (!availableVersion || !installedVersion
346
+ || !tryParseStrictSemVer(availableVersion)
347
+ || !tryParseStrictSemVer(installedVersion)) {
348
+ return {
349
+ state: 'unknown',
350
+ ...(availableVersion ? { availableVersion } : {}),
351
+ ...(installedVersion ? { installedVersion } : {}),
352
+ };
353
+ }
354
+ const relation = compareStrictSemVer(installedVersion, availableVersion);
355
+ if (relation === 0)
356
+ return { state: 'current', availableVersion, installedVersion };
357
+ if (relation < 0)
358
+ return { state: 'upgradeAvailable', availableVersion, installedVersion };
359
+ return { state: 'unknown', availableVersion, installedVersion };
360
+ }
361
+ function renderStatusV6(payload, verbose) {
362
+ const lines = [`Catalog sources: ${payload.catalog.sources.length}`];
363
+ for (const source of payload.catalog.sources) {
364
+ lines.push(`${source.primary ? '*' : '-'} ${source.id}: ${source.error ?? source.freshness ?? 'unavailable'}`);
365
+ }
366
+ for (const target of payload.targets) {
367
+ const errors = target.errors.length > 0
368
+ ? ` [${target.errors.map((error) => `${error.code}: ${error.message}`).join('; ')}]`
369
+ : '';
370
+ const desired = target.desired.enabled ? target.desired.scopes.join('+') : 'absent';
371
+ lines.push(`${target.pluginId} ${target.platform}: desired=${desired} actual=${target.actual.state}${errors}`);
372
+ if (target.sharedNative) {
373
+ lines.push(` shared native ${target.sharedNative.pluginId}: ${target.sharedNative.state}`);
374
+ }
375
+ if (target.activation) {
376
+ lines.push(` activation user=${String(target.activation.user)} project=${String(target.activation.project)} (${target.activation.evidence})`);
377
+ if (target.activation.systemConsumer) {
378
+ const version = 'detectedVersion' in target.activation.systemConsumer
379
+ ? ` ${target.activation.systemConsumer.detectedVersion}`
380
+ : '';
381
+ lines.push(` system Codex consumer: ${target.activation.systemConsumer.state}${version}`);
382
+ }
383
+ }
384
+ if (target.extensions) {
385
+ lines.push(` extensions ${target.extensions.kinds.join(',')}: ${target.extensions.state}`);
386
+ }
387
+ if (verbose) {
388
+ for (const component of target.components) {
389
+ const error = component.error
390
+ ? ` [${component.error.code}: ${component.error.message}]`
391
+ : '';
392
+ lines.push(` component ${component.key}: ${component.state}${error}`);
393
+ }
394
+ }
395
+ }
396
+ for (const error of payload.errors)
397
+ lines.push(`Error: ${error.message}`);
398
+ return lines.join('\n');
399
+ }
400
+ function collisionMessage(collision) {
401
+ const reason = {
402
+ ownerMismatch: '已有内容属于其他 owner',
403
+ unownedContent: '已有内容没有 AW owner 标记',
404
+ typeMismatch: '已有内容类型与目标不匹配',
405
+ }[collision.reason];
406
+ return `artifactCollision: ${collision.artifactKind} ${collision.artifactKey}: ${reason}。请移除或迁移冲突内容后重试。`;
407
+ }
408
+ function collisionRootIssueId(options) {
409
+ return [
410
+ 'artifactCollision',
411
+ options.pluginId,
412
+ options.platform,
413
+ options.scope,
414
+ options.collision.artifactKind,
415
+ options.collision.artifactKey,
416
+ ].join(':');
417
+ }
418
+ export async function statusCommandV6(options) {
419
+ const env = options.env ?? process.env;
420
+ const dependencyPluginCache = new Map();
421
+ const dependencyInspectionCache = new Map();
422
+ const cliVersion = options.cliVersion ?? assertStrictSemVer(JSON.parse(fs.readFileSync(path.join(resolveCliPackageRoot(), 'package.json'), 'utf8')).version, 'packages/cli/package.json version');
423
+ const snapshot = await readCatalogSourcesConfigSnapshot(env);
424
+ const intentErrors = [];
425
+ const readIntent = async (scope) => {
426
+ try {
427
+ return await readPluginIntentState({ scope, cwd: options.cwd, env });
428
+ }
429
+ catch {
430
+ intentErrors.push({
431
+ code: 'pluginIntentStateInvalid',
432
+ message: `pluginIntentStateInvalid: ${scope} plugin intent state is invalid.`,
433
+ });
434
+ return emptyIntent();
435
+ }
436
+ };
437
+ const [userIntent, projectIntent] = await Promise.all([
438
+ readIntent('user'),
439
+ readIntent('project'),
440
+ ]);
441
+ const codexConfigErrors = [];
442
+ const readActivationConfig = async (scope) => {
443
+ try {
444
+ return await readCodexConfigFile(resolveCodexPaths(options.cwd, scope, env).configTomlPath);
445
+ }
446
+ catch {
447
+ codexConfigErrors.push({
448
+ scope,
449
+ code: 'codexActivationDrift',
450
+ message: `codexActivationDrift: ${scope} Codex activation config is unreadable.`,
451
+ });
452
+ return undefined;
453
+ }
454
+ };
455
+ const [userCodexConfig, projectCodexConfig] = await Promise.all([
456
+ readActivationConfig('user'),
457
+ readActivationConfig('project'),
458
+ ]);
459
+ const currentProjectKey = await resolveCanonicalRepoProjectKey(options.cwd);
460
+ const currentProjectLocationKey = createProjectLocationKey(currentProjectKey);
461
+ const codexScopePathsAlias = codexProjectConfigAliasesUserHome(options.cwd, env);
462
+ const inventoryErrors = [];
463
+ const readInventory = options.inventoryCatalogSourceReferences
464
+ ?? inventoryCatalogSourceReferences;
465
+ const ownerInventory = await readInventory({ cwd: options.cwd, env }).catch(async (error) => {
466
+ inventoryErrors.push(projectStateInventoryError(error, env, options.cwd));
467
+ return inventoryLegacyOwnerReferences({ cwd: options.cwd, env }).catch((fallbackError) => {
468
+ inventoryErrors.push(projectStateInventoryError(fallbackError, env, options.cwd));
469
+ return { inventorySchemaVersion: 1, references: [], errors: [] };
470
+ });
471
+ });
472
+ for (const error of ownerInventory.errors ?? []) {
473
+ const code = error.kind === 'nativeStateRead' ? 'nativeStateUnreadable' : 'stateInventoryFailed';
474
+ inventoryErrors.push({
475
+ code,
476
+ message: `${code}: ${error.kind}@${error.location}: ${error.message}`,
477
+ relevance: error.relevance,
478
+ });
479
+ }
480
+ const nativeProbeCache = new Map();
481
+ const codexDesiredUserActivationIds = new Set();
482
+ const readOnlyNativeProbe = (probe) => async () => {
483
+ const key = [
484
+ probe.sourceIdentity,
485
+ probe.pluginName,
486
+ probe.platform,
487
+ probe.scope,
488
+ probe.marketplaceName,
489
+ ].join('\0');
490
+ let value = nativeProbeCache.get(key);
491
+ if (!value) {
492
+ value = probe.platform === 'codex'
493
+ ? inspectCodexNativeResidue({
494
+ pluginName: probe.pluginName,
495
+ cwd: options.cwd,
496
+ env,
497
+ marketplaceName: probe.marketplaceName,
498
+ marketplaceRoot: probe.marketplaceRoot,
499
+ }).then((residue) => residue.state)
500
+ : Promise.resolve(ownerInventory.references.some((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
501
+ && reference.sourceId === probe.sourceId
502
+ && reference.sourceIdentity === probe.sourceIdentity
503
+ && reference.pluginName === probe.pluginName
504
+ && reference.platform === probe.platform
505
+ && reference.scope === probe.scope
506
+ && (probe.scope === 'user' || reference.projectKey === currentProjectKey))
507
+ ? 'present'
508
+ : 'absent');
509
+ nativeProbeCache.set(key, value);
510
+ }
511
+ return value;
512
+ };
513
+ const hasCurrentCodexProjectOwner = (sourceId, pluginName) => ownerInventory.references.some((reference) => reference.kind === 'namespacedOwner'
514
+ && reference.sourceId === sourceId
515
+ && reference.pluginName === pluginName
516
+ && reference.platform === 'codex'
517
+ && reference.scope === 'project'
518
+ && reference.projectKey === currentProjectKey);
519
+ const configured = new Map(snapshot.config.sources.map((source) => [source.id, source]));
520
+ const requested = options.plugins ?? [];
521
+ const platforms = selectedPlatforms(options.platform);
522
+ const scopes = selectedScopes(options.scope);
523
+ const codexSystemConsumerInspections = new Map();
524
+ const inspectCodexSystemConsumer = (scope) => {
525
+ let inspection = codexSystemConsumerInspections.get(scope);
526
+ if (!inspection) {
527
+ inspection = inspectSystemCodexFilesystem({
528
+ cwd: options.cwd,
529
+ env,
530
+ operationRequirement: getCodexOperationRequirement(scope),
531
+ });
532
+ codexSystemConsumerInspections.set(scope, inspection);
533
+ }
534
+ return inspection;
535
+ };
536
+ const selectorErrors = [];
537
+ const parsedSelectors = [];
538
+ const plannedSelectors = [];
539
+ const liveOnlySelectors = [];
540
+ for (const selector of requested) {
541
+ let parsed;
542
+ try {
543
+ parsed = parsePluginId(selector);
544
+ }
545
+ catch (error) {
546
+ selectorErrors.push({
547
+ code: 'invalidPluginSelector',
548
+ message: error instanceof Error ? error.message : String(error),
549
+ });
550
+ continue;
551
+ }
552
+ parsedSelectors.push({ raw: selector, parsed });
553
+ if (parsed.sourceId !== undefined && !configured.has(parsed.sourceId)) {
554
+ const hasLiveReference = ownerInventory.references.some((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
555
+ && reference.sourceId === parsed.sourceId
556
+ && reference.pluginName === parsed.pluginName
557
+ && platforms.includes(reference.platform)
558
+ && scopes.includes(reference.scope)
559
+ && (reference.scope !== 'project' || reference.projectKey === currentProjectKey));
560
+ if (hasLiveReference) {
561
+ liveOnlySelectors.push({ raw: selector, parsed });
562
+ }
563
+ else if (!inventoryErrors.some((error) => inventoryErrorMatchesSelection({
564
+ error,
565
+ selectors: [{ raw: selector, parsed }],
566
+ platformExplicit: options.platform !== undefined,
567
+ scopeExplicit: options.scope !== undefined,
568
+ platforms,
569
+ scopes,
570
+ currentProjectLocationKey,
571
+ }))) {
572
+ selectorErrors.push({
573
+ code: 'pluginNotFound',
574
+ message: `Plugin "${selector}" was not found because catalog source "${parsed.sourceId}" is not configured.`,
575
+ });
576
+ }
577
+ continue;
578
+ }
579
+ plannedSelectors.push({ raw: selector, parsed });
580
+ }
581
+ const selectedInventoryErrors = inventoryErrors.filter((error) => inventoryErrorMatchesSelection({
582
+ error,
583
+ selectors: parsedSelectors,
584
+ platformExplicit: options.platform !== undefined,
585
+ scopeExplicit: options.scope !== undefined,
586
+ platforms,
587
+ scopes,
588
+ currentProjectLocationKey,
589
+ }));
590
+ const plannedSourceIds = requested.length === 0
591
+ ? undefined
592
+ : planPluginSelectorSourceIds(plannedSelectors.map((selector) => selector.parsed));
593
+ const selectedConfiguredSources = plannedSourceIds === undefined
594
+ ? snapshot.config.sources
595
+ : plannedSourceIds.map((sourceId) => configured.get(sourceId));
596
+ const identityEntries = await Promise.all(selectedConfiguredSources.map(async (source) => {
597
+ try {
598
+ return [source.id, { identity: await calculateCatalogSourceIdentity(source) }];
599
+ }
600
+ catch (error) {
601
+ const sanitized = sanitizeCatalogSourceError(error, env);
602
+ return [source.id, {
603
+ error: sanitized.message,
604
+ }];
605
+ }
606
+ }));
607
+ const identities = new Map(identityEntries);
608
+ const catalog = await withResolvedMultiSourceCatalog({
609
+ cliVersion,
610
+ configSnapshot: snapshot,
611
+ ...(plannedSourceIds === undefined ? {} : { sourceIds: plannedSourceIds }),
612
+ ...(options.catalogOperationContext
613
+ ? { operationContext: options.catalogOperationContext }
614
+ : {}),
615
+ env,
616
+ consume: async (resolution) => ({
617
+ primarySourceId: resolution.primarySourceId,
618
+ configDigest: resolution.configDigest,
619
+ compositeDigest: resolution.compositeDigest,
620
+ sources: await Promise.all(resolution.sources.map(async (item) => {
621
+ const source = configured.get(item.sourceId);
622
+ const identity = identities.get(item.sourceId);
623
+ const base = {
624
+ id: item.sourceId,
625
+ identity: identity.identity ?? 'unavailable',
626
+ type: source.type,
627
+ primary: source.primary,
628
+ requestedRef: item.resolution?.requestedRef ?? sourceRequestedRef(source, cliVersion),
629
+ };
630
+ if (identity.error || item.error) {
631
+ const error = item.error ?? new Error(identity.error);
632
+ return {
633
+ ...base,
634
+ error: [identity.error, item.error?.message].filter(Boolean).join('; '),
635
+ errorCode: catalogSourceErrorCode(error),
636
+ };
637
+ }
638
+ try {
639
+ const placementEntries = item.resolution.manifest.entries.map((entry) => {
640
+ const products = entry.policy.products;
641
+ const supports = (platform) => products === undefined
642
+ || products.includes(platform === 'codex' ? 'CODEX' : 'CLAUDE');
643
+ return {
644
+ name: entry.name,
645
+ dependencies: entry.dependencies,
646
+ source: { id: item.resolution.sourceId },
647
+ targets: {
648
+ codex: { user: supports('codex'), project: supports('codex') },
649
+ claude: { user: supports('claude'), project: supports('claude') },
650
+ },
651
+ };
652
+ });
653
+ const sourceDesired = calculateDesiredTargetStates({
654
+ userIntent,
655
+ projectIntent,
656
+ available: placementEntries,
657
+ codexProjectAllowed: !codexScopePathsAlias,
658
+ });
659
+ const registeredNames = canonicalMarketplaceRegistrationNames(ownerInventory.references, item.resolution.sourceId);
660
+ if (registeredNames.length > 1) {
661
+ throw new Error('marketplaceIdentityUnavailable: Multiple canonical native marketplace registrations match the source.');
662
+ }
663
+ const desiredMarketplaceName = registeredNames[0]
664
+ ?? (item.resolution.sourceId === resolution.primarySourceId
665
+ ? 'aw'
666
+ : `aw-${item.resolution.sourceId}`);
667
+ for (const entry of placementEntries) {
668
+ const pluginId = formatPluginId({
669
+ sourceId: item.resolution.sourceId,
670
+ pluginName: entry.name,
671
+ });
672
+ if (sourceDesired.get(desiredTargetKey(pluginId, 'codex'))?.scopes.includes('user')) {
673
+ codexDesiredUserActivationIds.add(`${entry.name}@${desiredMarketplaceName}`);
674
+ }
675
+ }
676
+ const plugins = await Promise.all(item.resolution.manifest.entries.map(async (entry) => {
677
+ const capabilitySupport = checkAwCapabilitySupport(entry.requires.aw.capabilities ?? [], IMPLEMENTED_AW_CAPABILITIES);
678
+ if (!capabilitySupport.supported) {
679
+ const products = entry.policy.products;
680
+ const supports = (platform) => products === undefined
681
+ || products.includes(platform === 'codex' ? 'CODEX' : 'CLAUDE');
682
+ const states = {};
683
+ const message = `awCapabilityUnsupported: ${item.resolution.sourceId}/${entry.name} requires unsupported AW capabilities: ${capabilitySupport.missing.join(', ')}.`;
684
+ for (const platform of ['codex', 'claude']) {
685
+ if (!supports(platform))
686
+ continue;
687
+ states[platform] = {};
688
+ for (const scope of ['user', 'project']) {
689
+ states[platform][scope] = {
690
+ state: 'error',
691
+ components: [],
692
+ errors: [finalizeTargetError({ code: 'awCapabilityUnsupported', message }, 'error')],
693
+ };
694
+ }
695
+ }
696
+ return {
697
+ name: entry.name,
698
+ version: entry.version,
699
+ sharedNativePayloadDigest: entry.contentDigest,
700
+ displayName: entry.interface?.displayName ?? entry.name,
701
+ shortDescription: entry.interface?.shortDescription ?? entry.description,
702
+ description: entry.description,
703
+ targets: {
704
+ claude: { user: supports('claude'), project: supports('claude') },
705
+ codex: { user: supports('codex'), project: supports('codex') },
706
+ },
707
+ states,
708
+ dependencies: entry.dependencies,
709
+ missingCapabilities: capabilitySupport.missing,
710
+ };
711
+ }
712
+ const plugin = await readPluginManifest(path.join(item.resolution.rootDir, 'plugins', entry.name), { mode: 'bundle' });
713
+ const claude = supportsPlatform(plugin.manifest, 'claude');
714
+ const codex = supportsPlatform(plugin.manifest, 'codex');
715
+ const codexSurface = analyzeCodexSurface(plugin.manifest);
716
+ const sharedNativePayloadDigest = codexSurface.nativeKinds.length > 0
717
+ ? await calculateCodexSharedNativePayloadDigest(plugin.rootDir)
718
+ : entry.contentDigest;
719
+ plugin.sourceId = item.resolution.sourceId;
720
+ plugin.sourceIdentity = item.resolution.sourceIdentity;
721
+ plugin.pluginId = formatPluginId({ sourceId: item.resolution.sourceId, pluginName: entry.name });
722
+ let effectiveConfig;
723
+ let configDiagnostic;
724
+ if (plugin.manifest.config?.schema) {
725
+ try {
726
+ effectiveConfig = await resolveEffectivePluginConfig({
727
+ sourceId: plugin.sourceId,
728
+ sourceIdentity: plugin.sourceIdentity,
729
+ pluginName: plugin.manifest.name,
730
+ manifest: plugin.manifest,
731
+ cwd: options.cwd,
732
+ env,
733
+ });
734
+ }
735
+ catch {
736
+ configDiagnostic = {
737
+ code: 'configReadFailed',
738
+ message: '插件设置当前不可读。未读取或显示设置值。',
739
+ };
740
+ }
741
+ }
742
+ const states = {};
743
+ const defaultMarketplaceName = item.resolution.sourceId === resolution.primarySourceId
744
+ ? 'aw'
745
+ : `aw-${item.resolution.sourceId}`;
746
+ const marketplaceNameFor = (pluginName, platform, scope) => {
747
+ const liveName = ownerInventory.references.find((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
748
+ && reference.sourceId === item.resolution.sourceId
749
+ && reference.sourceIdentity === item.resolution.sourceIdentity
750
+ && reference.pluginName === pluginName
751
+ && reference.platform === platform
752
+ && reference.scope === scope
753
+ && (scope === 'user' || reference.projectKey === currentProjectKey)
754
+ && reference.marketplaceName)?.marketplaceName;
755
+ if (liveName)
756
+ return liveName;
757
+ const registeredNames = canonicalMarketplaceRegistrationNames(ownerInventory.references, item.resolution.sourceId);
758
+ if (registeredNames.length > 1) {
759
+ throw new Error('marketplaceIdentityUnavailable: Multiple canonical native marketplace registrations match the source.');
760
+ }
761
+ return registeredNames[0] ?? defaultMarketplaceName;
762
+ };
763
+ const marketplaceRoot = path.join(resolveAwHome(env), 'marketplaces', item.resolution.sourceId);
764
+ for (const platform of ['codex', 'claude']) {
765
+ states[platform] = {};
766
+ for (const scope of ['user', 'project']) {
767
+ if (platform === 'codex'
768
+ && scope === 'project'
769
+ && codexScopePathsAlias
770
+ && !hasCurrentCodexProjectOwner(item.resolution.sourceId, entry.name))
771
+ continue;
772
+ const supported = platform === 'claude'
773
+ ? claude
774
+ : codex && codexSurface.ok;
775
+ if (!supported)
776
+ continue;
777
+ const changedOwner = ownerInventory.references.find((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
778
+ && reference.sourceId === item.resolution.sourceId
779
+ && reference.pluginName === entry.name
780
+ && reference.platform === platform
781
+ && reference.scope === scope
782
+ && (scope === 'user' || reference.projectKey === currentProjectKey)
783
+ && reference.sourceIdentity
784
+ && reference.sourceIdentity !== item.resolution.sourceIdentity);
785
+ if (changedOwner) {
786
+ states[platform][scope] = {
787
+ state: 'error',
788
+ components: [],
789
+ errors: [finalizeTargetError({
790
+ code: 'sourceChanged',
791
+ message: `sourceChanged: owner at ${changedOwner.location} has a different source identity.`,
792
+ }, 'error')],
793
+ };
794
+ continue;
795
+ }
796
+ try {
797
+ const marketplaceName = marketplaceNameFor(entry.name, platform, scope);
798
+ const inspected = await inspectRebuildTarget({
799
+ sourceId: item.resolution.sourceId,
800
+ sourceIdentity: item.resolution.sourceIdentity,
801
+ pluginId: plugin.pluginId,
802
+ marketplaceName,
803
+ marketplaceRoot,
804
+ plugin,
805
+ platform,
806
+ scope,
807
+ cwd: options.cwd,
808
+ catalog: {
809
+ rootDir: item.resolution.rootDir,
810
+ source: 'local',
811
+ },
812
+ context: {
813
+ env,
814
+ nativeCliRunner: getDefaultNativeCliRunner(),
815
+ reporter: createNoopReporter(),
816
+ debugLogger: createNoopDebugLogger(),
817
+ },
818
+ userActivationDesired: codexDesiredUserActivationIds,
819
+ nativeProbe: readOnlyNativeProbe({
820
+ pluginName: entry.name,
821
+ sourceId: item.resolution.sourceId,
822
+ sourceIdentity: item.resolution.sourceIdentity,
823
+ platform,
824
+ scope,
825
+ marketplaceName,
826
+ marketplaceRoot,
827
+ }),
828
+ });
829
+ const liveState = projectedLiveState({
830
+ inspection: inspected.inspection,
831
+ required: inspected.target.desiredOwnedComponents ?? inspected.target.ownedComponents,
832
+ optional: inspected.target.optionalOwnedComponents ?? [],
833
+ });
834
+ const collisionErrors = inspected.inspection.components.flatMap((component) => component.collision ? [finalizeTargetError({
835
+ code: 'artifactCollision',
836
+ message: collisionMessage(component.collision),
837
+ collision: component.collision,
838
+ rootIssueId: collisionRootIssueId({
839
+ pluginId: formatPluginId({
840
+ sourceId: item.resolution.sourceId,
841
+ pluginName: entry.name,
842
+ }),
843
+ platform,
844
+ scope,
845
+ collision: component.collision,
846
+ }),
847
+ rootIssueCode: 'artifactCollision',
848
+ }, liveState)] : []);
849
+ const dependencyErrors = [];
850
+ const dependencyReadiness = [];
851
+ const directDependencies = plugin.manifest.dependencies ?? [];
852
+ if (directDependencies.length > 0
853
+ && (liveState === 'present' || liveState === 'partial')) {
854
+ for (const dependencyName of directDependencies) {
855
+ const dependencyId = formatPluginId({
856
+ sourceId: item.resolution.sourceId,
857
+ pluginName: dependencyName,
858
+ });
859
+ const dependencyEntry = item.resolution.manifest.entries.find((candidate) => candidate.name === dependencyName);
860
+ if (!dependencyEntry) {
861
+ const rootIssueId = `dependencyMissing:${dependencyId}:${platform}:${scope}`;
862
+ dependencyReadiness.push({
863
+ dependencyPluginId: dependencyId,
864
+ state: 'absent',
865
+ rootIssueId,
866
+ rootIssueCode: 'dependencyMissing',
867
+ });
868
+ dependencyErrors.push(finalizeTargetError({
869
+ code: 'dependencyMissing',
870
+ message: `dependencyMissing: ${dependencyId} is not available in the current source snapshot.`,
871
+ dependencyPluginId: dependencyId,
872
+ rootIssueId,
873
+ rootIssueCode: 'dependencyMissing',
874
+ }, 'partial'));
875
+ continue;
876
+ }
877
+ const dependencySupport = checkAwCapabilitySupport(dependencyEntry.requires.aw.capabilities ?? [], IMPLEMENTED_AW_CAPABILITIES);
878
+ if (!dependencySupport.supported) {
879
+ const rootIssueId = `awCapabilityUnsupported:${dependencyId}`;
880
+ dependencyReadiness.push({
881
+ dependencyPluginId: dependencyId,
882
+ state: 'error',
883
+ rootIssueId,
884
+ rootIssueCode: 'awCapabilityUnsupported',
885
+ });
886
+ dependencyErrors.push(finalizeTargetError({
887
+ code: 'awCapabilityUnsupported',
888
+ message: `awCapabilityUnsupported: ${dependencyId} requires unsupported AW capabilities: ${dependencySupport.missing.join(', ')}.`,
889
+ dependencyPluginId: dependencyId,
890
+ rootIssueId,
891
+ rootIssueCode: 'awCapabilityUnsupported',
892
+ }, 'partial'));
893
+ continue;
894
+ }
895
+ const pluginCacheKey = [item.resolution.sourceIdentity, dependencyId].join('\0');
896
+ let dependencyPluginPromise = dependencyPluginCache.get(pluginCacheKey);
897
+ if (!dependencyPluginPromise) {
898
+ dependencyPluginPromise = readPluginManifest(path.join(item.resolution.rootDir, 'plugins', dependencyName), { mode: 'bundle' }).then((dependencyPlugin) => {
899
+ dependencyPlugin.sourceId = item.resolution.sourceId;
900
+ dependencyPlugin.sourceIdentity = item.resolution.sourceIdentity;
901
+ dependencyPlugin.pluginId = dependencyId;
902
+ return dependencyPlugin;
903
+ });
904
+ dependencyPluginCache.set(pluginCacheKey, dependencyPluginPromise);
905
+ }
906
+ const placements = scope === 'project' ? ['project', 'user'] : ['user'];
907
+ let dependencyResult = {
908
+ state: 'absent',
909
+ };
910
+ for (const dependencyScope of placements) {
911
+ const inspectionCacheKey = [
912
+ item.resolution.sourceIdentity,
913
+ dependencyId,
914
+ platform,
915
+ dependencyScope,
916
+ dependencyScope === 'project' ? currentProjectKey : '',
917
+ ].join('\0');
918
+ let dependencyInspection = dependencyInspectionCache.get(inspectionCacheKey);
919
+ if (!dependencyInspection) {
920
+ dependencyInspection = dependencyPluginPromise.then(async (dependencyPlugin) => {
921
+ dependencyInspectionHookForTests?.();
922
+ const dependencyMarketplaceName = marketplaceNameFor(dependencyName, platform, dependencyScope);
923
+ const dependencyInspected = await inspectRebuildTarget({
924
+ sourceId: item.resolution.sourceId,
925
+ sourceIdentity: item.resolution.sourceIdentity,
926
+ pluginId: dependencyId,
927
+ marketplaceName: dependencyMarketplaceName,
928
+ marketplaceRoot,
929
+ plugin: dependencyPlugin,
930
+ platform,
931
+ scope: dependencyScope,
932
+ cwd: options.cwd,
933
+ catalog: { rootDir: item.resolution.rootDir, source: 'local' },
934
+ context: {
935
+ env,
936
+ nativeCliRunner: getDefaultNativeCliRunner(),
937
+ reporter: createNoopReporter(),
938
+ debugLogger: createNoopDebugLogger(),
939
+ },
940
+ userActivationDesired: codexDesiredUserActivationIds,
941
+ nativeProbe: readOnlyNativeProbe({
942
+ pluginName: dependencyName,
943
+ sourceId: item.resolution.sourceId,
944
+ sourceIdentity: item.resolution.sourceIdentity,
945
+ platform,
946
+ scope: dependencyScope,
947
+ marketplaceName: dependencyMarketplaceName,
948
+ marketplaceRoot,
949
+ }),
950
+ });
951
+ const dependencyLiveState = projectedLiveState({
952
+ inspection: dependencyInspected.inspection,
953
+ required: dependencyInspected.target.desiredOwnedComponents
954
+ ?? dependencyInspected.target.ownedComponents,
955
+ optional: dependencyInspected.target.optionalOwnedComponents ?? [],
956
+ });
957
+ const collision = dependencyInspected.inspection.components.find((component) => component.collision)?.collision;
958
+ if (collision) {
959
+ return {
960
+ state: 'blockedByCollision',
961
+ rootIssueId: collisionRootIssueId({
962
+ pluginId: dependencyId,
963
+ platform,
964
+ scope: dependencyScope,
965
+ collision,
966
+ }),
967
+ rootIssueCode: 'artifactCollision',
968
+ };
969
+ }
970
+ return {
971
+ state: dependencyLiveState === 'present' ? 'ready'
972
+ : dependencyLiveState === 'absent' ? 'absent'
973
+ : dependencyLiveState === 'partial' ? 'incomplete'
974
+ : 'error',
975
+ ...(dependencyLiveState === 'partial'
976
+ ? {
977
+ rootIssueId: `incompleteInstallation:${dependencyId}:${platform}:${dependencyScope}`,
978
+ rootIssueCode: 'incompleteInstallation',
979
+ }
980
+ : dependencyLiveState === 'error'
981
+ ? {
982
+ rootIssueId: `diagnostic:${dependencyId}:${platform}:${dependencyScope}`,
983
+ rootIssueCode: 'diagnostic',
984
+ }
985
+ : {}),
986
+ };
987
+ }).catch(() => ({
988
+ state: 'error',
989
+ rootIssueId: `diagnostic:${dependencyId}:${platform}:${dependencyScope}`,
990
+ rootIssueCode: 'diagnostic',
991
+ }));
992
+ dependencyInspectionCache.set(inspectionCacheKey, dependencyInspection);
993
+ }
994
+ const candidate = await dependencyInspection;
995
+ if (candidate.state === 'ready') {
996
+ dependencyResult = candidate;
997
+ break;
998
+ }
999
+ const priority = {
1000
+ ready: 5,
1001
+ blockedByCollision: 4,
1002
+ incomplete: 3,
1003
+ error: 2,
1004
+ absent: 1,
1005
+ };
1006
+ if (priority[candidate.state] > priority[dependencyResult.state]) {
1007
+ dependencyResult = candidate;
1008
+ }
1009
+ }
1010
+ if (dependencyResult.state === 'absent') {
1011
+ dependencyResult = {
1012
+ state: 'absent',
1013
+ rootIssueId: `dependencyMissing:${dependencyId}:${platform}:${scope}`,
1014
+ rootIssueCode: 'dependencyMissing',
1015
+ };
1016
+ }
1017
+ dependencyReadiness.push({
1018
+ dependencyPluginId: dependencyId,
1019
+ ...dependencyResult,
1020
+ });
1021
+ if (dependencyResult.state === 'absent') {
1022
+ dependencyErrors.push(finalizeTargetError({
1023
+ code: 'dependencyMissing',
1024
+ message: `dependencyMissing: ${dependencyId} is absent from its required live placement.`,
1025
+ dependencyPluginId: dependencyId,
1026
+ rootIssueId: dependencyResult.rootIssueId,
1027
+ rootIssueCode: dependencyResult.rootIssueCode,
1028
+ }, 'partial'));
1029
+ }
1030
+ else if (dependencyResult.state !== 'ready') {
1031
+ dependencyErrors.push(finalizeTargetError({
1032
+ code: 'dependencyNotReady',
1033
+ message: `dependencyNotReady: ${dependencyId} is not ready at its required live placement.`,
1034
+ dependencyPluginId: dependencyId,
1035
+ ...(dependencyResult.rootIssueId
1036
+ ? { rootIssueId: dependencyResult.rootIssueId }
1037
+ : {}),
1038
+ ...(dependencyResult.rootIssueCode
1039
+ ? { rootIssueCode: dependencyResult.rootIssueCode }
1040
+ : {}),
1041
+ }, 'partial'));
1042
+ }
1043
+ }
1044
+ }
1045
+ states[platform][scope] = {
1046
+ state: liveState,
1047
+ errors: [...inspected.inspection.errors.map((error) => finalizeTargetError({
1048
+ code: 'componentInspectionFailed',
1049
+ message: `${error.label}: ${error.message}`,
1050
+ }, liveState)), ...collisionErrors, ...dependencyErrors],
1051
+ ...(dependencyReadiness.length > 0 ? { dependencyReadiness } : {}),
1052
+ components: inspected.inspection.components.map((component) => {
1053
+ const projectedError = component.collision
1054
+ ? projectTargetError({
1055
+ code: 'artifactCollision',
1056
+ message: collisionMessage(component.collision),
1057
+ collision: component.collision,
1058
+ }, env, options.cwd, liveState)
1059
+ : component.diagnostic
1060
+ ? projectTargetError({
1061
+ code: 'componentInspectionFailed',
1062
+ message: component.diagnostic,
1063
+ }, env, options.cwd, liveState)
1064
+ : undefined;
1065
+ return {
1066
+ key: component.component.identity.artifactKey,
1067
+ state: component.state,
1068
+ ...(projectedError ? { error: projectedError } : {}),
1069
+ };
1070
+ }),
1071
+ ...(inspected.installedVersion
1072
+ ? { installedVersion: inspected.installedVersion }
1073
+ : {}),
1074
+ };
1075
+ }
1076
+ catch (error) {
1077
+ const message = error instanceof Error ? error.message : String(error);
1078
+ const configErrorCode = platform === 'codex' && codexConfigErrors.length > 0
1079
+ ? codexSurface.nativeKinds.length > 0
1080
+ ? 'codexSharedNativeCorrupt'
1081
+ : 'codexActivationDrift'
1082
+ : undefined;
1083
+ const code = configErrorCode
1084
+ ?? message.split(':', 1)[0]
1085
+ ?? 'targetInspectionFailed';
1086
+ states[platform][scope] = {
1087
+ state: 'error',
1088
+ components: [],
1089
+ errors: [finalizeTargetError({
1090
+ code,
1091
+ message: configErrorCode
1092
+ ? `${configErrorCode}: Codex activation state is unreadable.`
1093
+ : message,
1094
+ }, 'error')],
1095
+ };
1096
+ }
1097
+ }
1098
+ }
1099
+ let codexStatus;
1100
+ if (codex && codexSurface.ok) {
1101
+ const marketplaceName = marketplaceNameFor(entry.name, 'codex', 'user');
1102
+ const codexPluginId = `${entry.name}@${marketplaceName}`;
1103
+ let residueFailed = false;
1104
+ const managedByCurrentIntent = userIntent.managed.codexPluginIds.includes(codexPluginId)
1105
+ || projectIntent.managed.codexPluginIds.includes(codexPluginId);
1106
+ const sharedInspection = codexSurface.nativeKinds.length > 0
1107
+ ? await inspectCodexSharedNativeLive({
1108
+ pluginName: entry.name,
1109
+ desiredVersion: entry.version,
1110
+ expectedPayloadDigest: sharedNativePayloadDigest,
1111
+ cwd: options.cwd,
1112
+ env,
1113
+ managedByCurrentIntent,
1114
+ marketplaceName,
1115
+ marketplaceRoot,
1116
+ }).catch(() => {
1117
+ residueFailed = true;
1118
+ return undefined;
1119
+ })
1120
+ : undefined;
1121
+ const nativeState = sharedInspection?.sharedNative;
1122
+ const sharedNative = residueFailed
1123
+ ? { pluginId: codexPluginId, state: 'corrupt', shared: true }
1124
+ : !nativeState
1125
+ ? undefined
1126
+ : nativeState.state === 'foreign'
1127
+ ? { pluginId: codexPluginId, state: 'foreign', shared: true }
1128
+ : nativeState.state === 'absent'
1129
+ ? { pluginId: codexPluginId, state: 'missing', shared: true }
1130
+ : nativeState.state === 'corrupt'
1131
+ ? { pluginId: codexPluginId, state: 'corrupt', shared: true }
1132
+ : nativeState.state === 'outdated'
1133
+ ? {
1134
+ pluginId: codexPluginId,
1135
+ state: 'outdated',
1136
+ version: nativeState.version,
1137
+ shared: true,
1138
+ }
1139
+ : nativeState.state === 'present' || nativeState.state === 'claimable'
1140
+ ? {
1141
+ pluginId: codexPluginId,
1142
+ state: 'present',
1143
+ version: nativeState.version,
1144
+ shared: true,
1145
+ }
1146
+ : undefined;
1147
+ const userActivation = userCodexConfig?.snapshot.plugins[codexPluginId]?.enabled;
1148
+ const projectActivation = projectCodexConfig?.snapshot.plugins[codexPluginId]?.enabled;
1149
+ codexStatus = {
1150
+ pluginId: codexPluginId,
1151
+ nativeKinds: codexSurface.nativeKinds,
1152
+ extensionKinds: codexSurface.extensionKinds,
1153
+ ...(sharedNative ? { sharedNative } : {}),
1154
+ activation: {
1155
+ ...(userActivation !== undefined ? { user: userActivation } : {}),
1156
+ ...(projectActivation !== undefined ? { project: projectActivation } : {}),
1157
+ ...((userActivation !== undefined || projectActivation !== undefined)
1158
+ ? { effective: projectActivation === true || userActivation === true }
1159
+ : {}),
1160
+ evidence: 'assumed',
1161
+ },
1162
+ };
1163
+ }
1164
+ return {
1165
+ name: entry.name,
1166
+ version: entry.version,
1167
+ sharedNativePayloadDigest,
1168
+ displayName: plugin.manifest.interface?.displayName ?? entry.name,
1169
+ shortDescription: plugin.manifest.interface?.shortDescription
1170
+ ?? plugin.manifest.description,
1171
+ description: plugin.manifest.description,
1172
+ ...(plugin.manifest.config?.schema
1173
+ ? { configSchema: plugin.manifest.config.schema }
1174
+ : {}),
1175
+ ...(effectiveConfig?.issues.length
1176
+ ? {
1177
+ configIssues: effectiveConfig.issues.map((issue) => ({
1178
+ type: issue.type,
1179
+ key: issue.key,
1180
+ title: plugin.manifest.config.schema[issue.key]?.title ?? issue.key,
1181
+ source: issue.source ?? 'missing',
1182
+ })),
1183
+ }
1184
+ : {}),
1185
+ ...(configDiagnostic ? { configDiagnostic } : {}),
1186
+ targets: {
1187
+ claude: { user: claude, project: claude },
1188
+ codex: {
1189
+ user: codex,
1190
+ project: codex
1191
+ && codexSurface.ok
1192
+ && codexSurface.classification !== 'empty',
1193
+ },
1194
+ },
1195
+ states,
1196
+ dependencies: plugin.manifest.dependencies ?? [],
1197
+ ...(codexStatus ? { codex: codexStatus } : {}),
1198
+ };
1199
+ }));
1200
+ return {
1201
+ ...base,
1202
+ resolvedCommit: item.resolution.resolvedCommit,
1203
+ catalogVersion: item.resolution.manifest.catalogVersion,
1204
+ channel: item.resolution.manifest.channel,
1205
+ freshness: 'active',
1206
+ plugins,
1207
+ };
1208
+ }
1209
+ catch (error) {
1210
+ const sanitized = sanitizeCatalogSourceError(error, env);
1211
+ return {
1212
+ ...base,
1213
+ error: sanitized.message,
1214
+ errorCode: catalogSourceErrorCode(sanitized),
1215
+ };
1216
+ }
1217
+ })),
1218
+ }),
1219
+ });
1220
+ const available = catalog.sources.flatMap((source) => 'plugins' in source
1221
+ ? source.plugins.map((plugin) => ({ ...plugin, source }))
1222
+ : []);
1223
+ const desiredTargetStates = calculateDesiredTargetStates({
1224
+ userIntent,
1225
+ projectIntent,
1226
+ available,
1227
+ codexProjectAllowed: !codexScopePathsAlias,
1228
+ });
1229
+ const failedSourceIds = new Set(catalog.sources.filter((source) => 'error' in source).map((source) => source.id));
1230
+ const selectedById = new Map();
1231
+ if (requested.length === 0) {
1232
+ for (const entry of available) {
1233
+ selectedById.set(formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }), entry);
1234
+ }
1235
+ }
1236
+ else {
1237
+ for (const selector of plannedSelectors) {
1238
+ if (selector.parsed.sourceId === undefined && failedSourceIds.size > 0) {
1239
+ selectorErrors.push({
1240
+ code: 'catalogSourceUnavailable',
1241
+ message: `Cannot resolve bare plugin selector "${selector.raw}" while catalog sources are unavailable: ${[...failedSourceIds].join(', ')}.`,
1242
+ });
1243
+ continue;
1244
+ }
1245
+ if (selector.parsed.sourceId !== undefined && failedSourceIds.has(selector.parsed.sourceId)) {
1246
+ selectorErrors.push({
1247
+ code: 'catalogSourceUnavailable',
1248
+ message: `Cannot resolve plugin selector "${selector.raw}" because catalog source "${selector.parsed.sourceId}" is unavailable.`,
1249
+ });
1250
+ continue;
1251
+ }
1252
+ const matches = available.filter((entry) => entry.name === selector.parsed.pluginName
1253
+ && (selector.parsed.sourceId === undefined || entry.source.id === selector.parsed.sourceId));
1254
+ if (matches.length === 0) {
1255
+ const selectorHasInventoryError = selectedInventoryErrors.some((error) => inventoryErrorMatchesSelection({
1256
+ error,
1257
+ selectors: [selector],
1258
+ platformExplicit: options.platform !== undefined,
1259
+ scopeExplicit: options.scope !== undefined,
1260
+ platforms,
1261
+ scopes,
1262
+ currentProjectLocationKey,
1263
+ }));
1264
+ if (!selectorHasInventoryError) {
1265
+ selectorErrors.push({
1266
+ code: 'pluginNotFound',
1267
+ message: `Plugin "${selector.raw}" was not found in the selected catalog source set.`,
1268
+ });
1269
+ }
1270
+ continue;
1271
+ }
1272
+ if (selector.parsed.sourceId === undefined && matches.length > 1) {
1273
+ selectorErrors.push({
1274
+ code: 'ambiguousPlugin',
1275
+ message: `Plugin "${selector.raw}" is ambiguous across sources: ${matches.map((entry) => entry.source.id).join(', ')}.`,
1276
+ });
1277
+ continue;
1278
+ }
1279
+ for (const entry of matches) {
1280
+ selectedById.set(formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }), entry);
1281
+ }
1282
+ }
1283
+ }
1284
+ const selected = [...selectedById.values()];
1285
+ const explicitTargetFilter = requested.length > 0
1286
+ && (options.platform !== undefined || options.scope !== undefined);
1287
+ const targets = selected.flatMap((entry) => platforms.flatMap((platform) => scopes.flatMap((scope) => {
1288
+ const target = {
1289
+ pluginName: entry.name,
1290
+ sourceId: entry.source.id,
1291
+ sourceIdentity: entry.source.identity,
1292
+ pluginId: formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
1293
+ version: entry.version,
1294
+ platform,
1295
+ scope,
1296
+ cwd: path.resolve(options.cwd),
1297
+ components: [],
1298
+ };
1299
+ if (platform === 'codex'
1300
+ && scope === 'project'
1301
+ && codexScopePathsAlias
1302
+ && !hasCurrentCodexProjectOwner(entry.source.id, entry.name)) {
1303
+ if (options.scope !== 'project')
1304
+ return [];
1305
+ return [{
1306
+ ...target,
1307
+ state: 'error',
1308
+ errors: [finalizeTargetError({
1309
+ code: 'codexScopePathAlias',
1310
+ message: 'codexScopePathAlias: Codex project config resolves to the user config directory. Run this command from an actual project directory.',
1311
+ }, 'error')],
1312
+ }];
1313
+ }
1314
+ if (entry.targets[platform][scope]) {
1315
+ const live = entry.states[platform]?.[scope];
1316
+ const dependencyIssueCount = (live?.errors ?? []).filter((error) => error.code.startsWith('dependency')
1317
+ || error.code === 'awCapabilityUnsupported'
1318
+ || error.code === 'sourceChanged').length;
1319
+ return [{
1320
+ ...target,
1321
+ state: live?.state ?? 'error',
1322
+ components: live?.components ?? [],
1323
+ errors: live?.errors ?? [finalizeTargetError({
1324
+ code: 'targetInspectionFailed',
1325
+ message: `No live inspection result exists for ${entry.source.id}/${entry.name}.`,
1326
+ }, 'error')],
1327
+ ...(live?.dependencyReadiness
1328
+ ? { dependencyReadiness: live.dependencyReadiness }
1329
+ : {}),
1330
+ ...(entry.dependencies.length > 0 || dependencyIssueCount > 0 ? {
1331
+ dependency: {
1332
+ directCount: entry.dependencies.length,
1333
+ issueCount: dependencyIssueCount,
1334
+ },
1335
+ } : {}),
1336
+ }];
1337
+ }
1338
+ const unsupportedLiveReference = ownerInventory.references.find((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
1339
+ && reference.sourceId === entry.source.id
1340
+ && reference.pluginName === entry.name
1341
+ && reference.platform === platform
1342
+ && reference.scope === scope
1343
+ && (scope === 'user' || reference.projectKey === currentProjectKey));
1344
+ if (unsupportedLiveReference) {
1345
+ const sourceChanged = Boolean(unsupportedLiveReference.sourceIdentity
1346
+ && unsupportedLiveReference.sourceIdentity !== entry.source.identity);
1347
+ return [{
1348
+ ...target,
1349
+ state: 'error',
1350
+ errors: [finalizeTargetError({
1351
+ code: sourceChanged ? 'sourceChanged' : 'noLongerSupported',
1352
+ message: sourceChanged
1353
+ ? `sourceChanged: live state for ${target.pluginId} has a different source identity.`
1354
+ : `noLongerSupported: ${target.pluginId} has live state for ${platform}/${scope}, but the current bundle no longer supports that target.`,
1355
+ }, 'error')],
1356
+ }];
1357
+ }
1358
+ if (!explicitTargetFilter)
1359
+ return [];
1360
+ return [{
1361
+ ...target,
1362
+ state: 'error',
1363
+ errors: [finalizeTargetError({
1364
+ code: platform === 'codex' && scope === 'project'
1365
+ ? 'codexProjectPluginUnsupported'
1366
+ : 'unsupportedTarget',
1367
+ message: platform === 'codex' && scope === 'project'
1368
+ ? `codexProjectPluginUnsupported: ${entry.source.id}/${entry.name} cannot use the current Codex project plugin contract.`
1369
+ : `${entry.source.id}/${entry.name} does not support ${platform}/${scope}.`,
1370
+ }, 'error')],
1371
+ }];
1372
+ })));
1373
+ const referenceSelectors = [...plannedSelectors, ...liveOnlySelectors];
1374
+ const referenceSelected = (reference) => (reference.pluginName !== undefined
1375
+ && reference.platform !== undefined
1376
+ && reference.scope !== undefined
1377
+ && platforms.includes(reference.platform)
1378
+ && scopes.includes(reference.scope)
1379
+ && (reference.scope !== 'project' || reference.projectKey === currentProjectKey)
1380
+ && (requested.length === 0 || referenceSelectors.some((selector) => selector.parsed.pluginName === reference.pluginName
1381
+ && (selector.parsed.sourceId === undefined || selector.parsed.sourceId === reference.sourceId))));
1382
+ const legacyOwners = ownerInventory.references.filter((reference) => (reference.kind === 'legacyOwner' || reference.kind === 'legacyMarketplace')
1383
+ && reference.pluginName !== undefined
1384
+ && reference.platform !== undefined
1385
+ && reference.scope !== undefined
1386
+ && platforms.includes(reference.platform)
1387
+ && scopes.includes(reference.scope)
1388
+ && (requested.length === 0 || plannedSelectors.some((selector) => selector.parsed.pluginName === reference.pluginName)));
1389
+ const missingSourceOwners = ownerInventory.references.filter((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
1390
+ && reference.sourceId
1391
+ && !configured.has(reference.sourceId)
1392
+ && referenceSelected(reference));
1393
+ const missingTargets = [...new Map(missingSourceOwners.flatMap((reference) => {
1394
+ if (!reference.sourceId || !reference.pluginName
1395
+ || (reference.platform !== 'codex' && reference.platform !== 'claude')
1396
+ || (reference.scope !== 'user' && reference.scope !== 'project'))
1397
+ return [];
1398
+ const pluginId = formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName });
1399
+ const target = {
1400
+ pluginName: reference.pluginName,
1401
+ sourceId: reference.sourceId,
1402
+ sourceIdentity: reference.sourceIdentity ?? 'unavailable',
1403
+ pluginId,
1404
+ platform: reference.platform,
1405
+ scope: reference.scope,
1406
+ cwd: path.resolve(options.cwd),
1407
+ state: 'error',
1408
+ components: [],
1409
+ errors: [finalizeTargetError({
1410
+ code: 'sourceMissing',
1411
+ message: `sourceMissing: catalog source "${reference.sourceId}" is not configured for ${pluginId}.`,
1412
+ }, 'error')],
1413
+ };
1414
+ return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
1415
+ })).values()];
1416
+ targets.push(...missingTargets);
1417
+ const unavailableSourceReferences = ownerInventory.references.filter((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
1418
+ && reference.sourceId
1419
+ && configured.has(reference.sourceId)
1420
+ && failedSourceIds.has(reference.sourceId)
1421
+ && referenceSelected(reference));
1422
+ const unavailableSourceTargets = [...new Map(unavailableSourceReferences.flatMap((reference) => {
1423
+ if (!reference.sourceId || !reference.pluginName
1424
+ || (reference.platform !== 'codex' && reference.platform !== 'claude')
1425
+ || (reference.scope !== 'user' && reference.scope !== 'project'))
1426
+ return [];
1427
+ const pluginId = formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName });
1428
+ const target = {
1429
+ pluginName: reference.pluginName,
1430
+ sourceId: reference.sourceId,
1431
+ sourceIdentity: reference.sourceIdentity ?? 'unavailable',
1432
+ pluginId,
1433
+ platform: reference.platform,
1434
+ scope: reference.scope,
1435
+ cwd: path.resolve(options.cwd),
1436
+ state: 'error',
1437
+ components: [],
1438
+ errors: [finalizeTargetError({
1439
+ code: 'catalogSourceUnavailable',
1440
+ message: `catalogSourceUnavailable: catalog source "${reference.sourceId}" is unavailable for ${pluginId}.`,
1441
+ }, 'error')],
1442
+ };
1443
+ return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
1444
+ })).values()];
1445
+ targets.push(...unavailableSourceTargets);
1446
+ const availablePluginIds = new Set(available.map((entry) => formatPluginId({ sourceId: entry.source.id, pluginName: entry.name })));
1447
+ const resolvedSourceIds = new Set(catalog.sources.flatMap((source) => 'plugins' in source ? [source.id] : []));
1448
+ const unavailableBundleReferences = ownerInventory.references.filter((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
1449
+ && reference.sourceId
1450
+ && configured.has(reference.sourceId)
1451
+ && resolvedSourceIds.has(reference.sourceId)
1452
+ && reference.pluginName
1453
+ && referenceSelected(reference)
1454
+ && !availablePluginIds.has(formatPluginId({
1455
+ sourceId: reference.sourceId,
1456
+ pluginName: reference.pluginName,
1457
+ })));
1458
+ const unavailableBundleTargets = [...new Map(unavailableBundleReferences.flatMap((reference) => {
1459
+ if (!reference.sourceId || !reference.pluginName
1460
+ || (reference.platform !== 'codex' && reference.platform !== 'claude')
1461
+ || (reference.scope !== 'user' && reference.scope !== 'project'))
1462
+ return [];
1463
+ const pluginId = formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName });
1464
+ if (requested.length > 0 && !plannedSelectors.some((selector) => selector.parsed.pluginName === reference.pluginName
1465
+ && (selector.parsed.sourceId === undefined || selector.parsed.sourceId === reference.sourceId)))
1466
+ return [];
1467
+ const target = {
1468
+ pluginName: reference.pluginName,
1469
+ sourceId: reference.sourceId,
1470
+ sourceIdentity: reference.sourceIdentity ?? 'unavailable',
1471
+ pluginId,
1472
+ platform: reference.platform,
1473
+ scope: reference.scope,
1474
+ cwd: path.resolve(options.cwd),
1475
+ state: 'error',
1476
+ components: [],
1477
+ errors: [finalizeTargetError({
1478
+ code: 'bundleUnavailable',
1479
+ message: `bundleUnavailable: ${pluginId} has live state but is not present in the current source snapshot.`,
1480
+ }, 'error')],
1481
+ };
1482
+ return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
1483
+ })).values()];
1484
+ targets.push(...unavailableBundleTargets);
1485
+ const targetKeys = new Set(targets.map((target) => `${target.pluginId}\0${target.platform}\0${target.scope}`));
1486
+ for (const [scope, intent] of [
1487
+ ['user', userIntent],
1488
+ ['project', projectIntent],
1489
+ ]) {
1490
+ for (const root of intent.roots) {
1491
+ const parsed = parsePluginId(root.pluginId);
1492
+ if (!parsed.sourceId)
1493
+ continue;
1494
+ if (requested.length > 0 && !parsedSelectors.some((selector) => selector.parsed.pluginName === parsed.pluginName
1495
+ && (selector.parsed.sourceId === undefined || selector.parsed.sourceId === parsed.sourceId))) {
1496
+ continue;
1497
+ }
1498
+ for (const platform of root.platforms.filter((candidate) => platforms.includes(candidate))) {
1499
+ if (!scopes.includes(scope))
1500
+ continue;
1501
+ const key = `${root.pluginId}\0${platform}\0${scope}`;
1502
+ if (targetKeys.has(key))
1503
+ continue;
1504
+ targets.push({
1505
+ pluginName: parsed.pluginName,
1506
+ sourceId: parsed.sourceId,
1507
+ sourceIdentity: identities.get(parsed.sourceId)?.identity ?? 'unavailable',
1508
+ pluginId: root.pluginId,
1509
+ platform,
1510
+ scope,
1511
+ cwd: path.resolve(options.cwd),
1512
+ state: 'error',
1513
+ components: [],
1514
+ errors: [finalizeTargetError({
1515
+ code: 'codexIntentSourceUnavailable',
1516
+ message: `codexIntentSourceUnavailable: desired intent for ${root.pluginId} cannot be resolved from the current Catalog.`,
1517
+ }, 'partial')],
1518
+ });
1519
+ targetKeys.add(key);
1520
+ }
1521
+ }
1522
+ }
1523
+ if (platforms.includes('codex')) {
1524
+ for (const [scope, intent] of [
1525
+ ['user', userIntent],
1526
+ ['project', projectIntent],
1527
+ ]) {
1528
+ if (!scopes.includes(scope))
1529
+ continue;
1530
+ for (const codexPluginId of intent.managed.codexPluginIds) {
1531
+ const separator = codexPluginId.lastIndexOf('@');
1532
+ if (separator <= 0 || separator === codexPluginId.length - 1)
1533
+ continue;
1534
+ const pluginName = codexPluginId.slice(0, separator);
1535
+ const marketplaceName = codexPluginId.slice(separator + 1);
1536
+ const registration = ownerInventory.references.find((reference) => reference.kind === 'namespacedMarketplace'
1537
+ && reference.marketplaceName === marketplaceName
1538
+ && reference.sourceId);
1539
+ const inferredSourceId = registration?.sourceId
1540
+ ?? (marketplaceName.startsWith('aw-') ? marketplaceName.slice(3) : undefined)
1541
+ ?? (snapshot.config.sources.length === 1
1542
+ ? snapshot.config.sources[0].id
1543
+ : undefined);
1544
+ const sourceId = inferredSourceId || 'unavailable';
1545
+ const pluginId = formatPluginId({ sourceId, pluginName });
1546
+ if (requested.length > 0 && !parsedSelectors.some((selector) => selector.parsed.pluginName === pluginName
1547
+ && (selector.parsed.sourceId === undefined || selector.parsed.sourceId === sourceId))) {
1548
+ continue;
1549
+ }
1550
+ const key = `${pluginId}\0codex\0${scope}`;
1551
+ if (targetKeys.has(key))
1552
+ continue;
1553
+ const marketplaceRoot = path.join(resolveAwHome(env), 'marketplaces', sourceId);
1554
+ const residue = await inspectCodexNativeResidue({
1555
+ pluginName,
1556
+ cwd: options.cwd,
1557
+ env,
1558
+ marketplaceName,
1559
+ marketplaceRoot,
1560
+ }).catch(() => undefined);
1561
+ const versions = [...new Set(residue?.versions ?? [])];
1562
+ const sharedNative = residue?.state === 'foreign'
1563
+ ? { pluginId: codexPluginId, state: 'foreign', shared: true }
1564
+ : residue?.state === 'present' && versions.length === 0
1565
+ ? { pluginId: codexPluginId, state: 'corrupt', shared: true }
1566
+ : residue?.state === 'present'
1567
+ ? {
1568
+ pluginId: codexPluginId,
1569
+ state: 'present',
1570
+ version: versions[0],
1571
+ shared: true,
1572
+ }
1573
+ : { pluginId: codexPluginId, state: 'missing', shared: true };
1574
+ const sourceErrorCode = configured.has(sourceId)
1575
+ ? 'catalogSourceUnavailable'
1576
+ : 'sourceMissing';
1577
+ const userActivation = userCodexConfig?.snapshot.plugins[codexPluginId]?.enabled;
1578
+ const projectActivation = projectCodexConfig?.snapshot.plugins[codexPluginId]?.enabled;
1579
+ targets.push({
1580
+ pluginName,
1581
+ sourceId,
1582
+ sourceIdentity: registration?.sourceIdentity
1583
+ ?? identities.get(sourceId)?.identity
1584
+ ?? 'unavailable',
1585
+ pluginId,
1586
+ platform: 'codex',
1587
+ scope,
1588
+ cwd: path.resolve(options.cwd),
1589
+ state: residue?.state === 'absent' || residue === undefined ? 'absent' : 'present',
1590
+ components: [],
1591
+ errors: [finalizeTargetError({
1592
+ code: sourceErrorCode,
1593
+ message: `${sourceErrorCode}: managed Codex inventory for ${codexPluginId} cannot be resolved from the current Catalog.`,
1594
+ }, 'partial')],
1595
+ sharedNative,
1596
+ activation: {
1597
+ ...(userActivation !== undefined
1598
+ ? { user: userActivation }
1599
+ : {}),
1600
+ ...(projectActivation !== undefined
1601
+ ? { project: projectActivation }
1602
+ : {}),
1603
+ ...((userActivation !== undefined || projectActivation !== undefined)
1604
+ ? { effective: projectActivation === true || userActivation === true }
1605
+ : {}),
1606
+ evidence: 'assumed',
1607
+ },
1608
+ });
1609
+ targetKeys.add(key);
1610
+ }
1611
+ }
1612
+ }
1613
+ const projectedInventoryErrors = [...new Map(selectedInventoryErrors.map((error) => [
1614
+ `${error.code}\0${error.message}`,
1615
+ { code: error.code, message: error.message },
1616
+ ])).values()];
1617
+ const errors = [
1618
+ ...projectedInventoryErrors,
1619
+ ...selectorErrors,
1620
+ ...intentErrors,
1621
+ ...legacyOwners.map((reference) => projectTargetError({
1622
+ code: 'legacyStateUnsupported',
1623
+ message: `legacyStateUnsupported: legacy live ${reference.kind} at ${reference.location}`,
1624
+ }, env, options.cwd, 'error')),
1625
+ ];
1626
+ const draftTargets = targets.map((target) => ({
1627
+ ...target,
1628
+ errors: target.errors.map((error) => projectTargetError(error, env, options.cwd, target.state)),
1629
+ }));
1630
+ const selectedByPluginId = new Map(selected.map((entry) => [
1631
+ formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
1632
+ entry,
1633
+ ]));
1634
+ const explicitScope = options.scope === undefined ? undefined : scopes[0];
1635
+ const warning = (code, message) => ({
1636
+ code,
1637
+ message: `${code}: ${message}`,
1638
+ severity: 'warning',
1639
+ });
1640
+ const decorateTarget = async (target, groupedScopes, groupedTargets) => {
1641
+ const entry = selectedByPluginId.get(target.pluginId);
1642
+ const codex = entry?.codex;
1643
+ const managedCodexPluginId = codex?.pluginId ?? target.sharedNative?.pluginId;
1644
+ const managedFallback = target.platform === 'codex'
1645
+ && managedCodexPluginId !== undefined
1646
+ && [...userIntent.managed.codexPluginIds, ...projectIntent.managed.codexPluginIds]
1647
+ .includes(managedCodexPluginId);
1648
+ const desiredAll = desiredTargetStates.get(desiredTargetKey(target.pluginId, target.platform))
1649
+ ?? { scopes: [], relation: managedFallback ? 'managed' : 'none' };
1650
+ const desired = target.platform === 'codex'
1651
+ ? desiredAll
1652
+ : {
1653
+ scopes: desiredAll.scopes.includes(target.scope) ? [target.scope] : [],
1654
+ relation: desiredAll.relation,
1655
+ };
1656
+ const sharedNative = codex?.sharedNative ?? target.sharedNative;
1657
+ const baseActivation = codex?.activation ?? target.activation;
1658
+ const consumerScope = desired.scopes.includes('project')
1659
+ ? 'project'
1660
+ : desired.scopes.includes('user')
1661
+ ? 'user'
1662
+ : explicitScope ?? (groupedScopes.includes('project') ? 'project' : 'user');
1663
+ const inspectSystemConsumer = target.platform === 'codex'
1664
+ && baseActivation !== undefined
1665
+ && ((codex?.nativeKinds.length ?? 0) > 0 || target.sharedNative !== undefined);
1666
+ const systemConsumer = inspectSystemConsumer
1667
+ ? await inspectCodexSystemConsumer(consumerScope)
1668
+ : undefined;
1669
+ const activation = baseActivation && systemConsumer
1670
+ ? {
1671
+ ...baseActivation,
1672
+ evidence: systemConsumer.state === 'missing' ? 'assumed' : 'unobserved',
1673
+ systemConsumer,
1674
+ }
1675
+ : baseActivation;
1676
+ const observationScopes = explicitScope
1677
+ ? [explicitScope]
1678
+ : desired.scopes.length > 0 ? desired.scopes : groupedScopes;
1679
+ const scopedTargets = groupedTargets.filter((candidate) => observationScopes.includes(candidate.scope));
1680
+ const observedTargets = scopedTargets.length > 0 ? scopedTargets : groupedTargets;
1681
+ const ownershipState = observedTargets.some((candidate) => candidate.state === 'error')
1682
+ ? 'error'
1683
+ : observedTargets.some((candidate) => candidate.state === 'partial')
1684
+ ? 'partial'
1685
+ : observedTargets.some((candidate) => candidate.state === 'present')
1686
+ ? 'present'
1687
+ : 'absent';
1688
+ const hasSourceError = observedTargets.some((candidate) => candidate.errors.some((error) => error.code === 'sourceMissing'
1689
+ || error.code === 'catalogSourceUnavailable'
1690
+ || error.code === 'bundleUnavailable'
1691
+ || error.code === 'codexIntentSourceUnavailable'));
1692
+ const desiredOverlapConflict = target.platform === 'codex'
1693
+ && (codex?.extensionKinds.length ?? 0) > 0
1694
+ && desired.scopes.includes('user')
1695
+ && desired.scopes.includes('project');
1696
+ const expectedUser = desired.scopes.includes('user');
1697
+ const expectedProject = desired.scopes.includes('project');
1698
+ const activationDrift = target.platform === 'codex'
1699
+ && (codexConfigErrors.some((error) => error.scope === 'user' || observationScopes.includes(error.scope))
1700
+ || ((codex?.nativeKinds.length ?? 0) > 0
1701
+ && ((expectedUser && activation?.user !== true)
1702
+ || (!expectedUser && activation?.user === true)
1703
+ || (expectedProject && activation?.project !== true)
1704
+ || (!expectedProject && activation?.project === true))));
1705
+ const extensionComponents = observedTargets.flatMap((candidate) => candidate.components).filter((component) => component.key !== 'native'
1706
+ && !component.key.startsWith('activation-')
1707
+ && !component.key.startsWith('marketplace-'));
1708
+ const extensions = target.platform !== 'codex'
1709
+ || (codex?.extensionKinds.length ?? 0) === 0
1710
+ ? undefined
1711
+ : {
1712
+ state: desiredOverlapConflict
1713
+ ? 'conflict'
1714
+ : extensionComponents.some((component) => component.error?.code === 'artifactCollision')
1715
+ ? 'conflict'
1716
+ : observedTargets.some((candidate) => candidate.state === 'partial' || candidate.state === 'error')
1717
+ ? 'drifted'
1718
+ : extensionComponents.some((component) => component.state === 'partial' || component.state === 'error')
1719
+ ? 'drifted'
1720
+ : desired.scopes.length > 0 && (extensionComponents.length === 0
1721
+ || extensionComponents.every((component) => component.state === 'absent'))
1722
+ ? 'missing'
1723
+ : 'ready',
1724
+ kinds: codex.extensionKinds,
1725
+ };
1726
+ const desiredEnabled = desired.scopes.length > 0;
1727
+ const consumerIssue = activation?.systemConsumer?.state === 'incompatible'
1728
+ || activation?.systemConsumer?.state === 'unresolved'
1729
+ ? activation.systemConsumer
1730
+ : undefined;
1731
+ const consumerBlocking = consumerIssue !== undefined;
1732
+ const managedCodexIds = [
1733
+ ...(desired.scopes.includes('user') ? userIntent.managed.codexPluginIds : []),
1734
+ ...(desired.scopes.includes('project') ? projectIntent.managed.codexPluginIds : []),
1735
+ ];
1736
+ const claimMissing = target.platform === 'codex'
1737
+ && sharedNative?.state === 'present'
1738
+ && desiredEnabled
1739
+ && !managedCodexIds.includes(sharedNative.pluginId);
1740
+ const actual = hasSourceError && desiredEnabled
1741
+ ? 'unresolved'
1742
+ : consumerBlocking && desiredEnabled
1743
+ ? 'unresolved'
1744
+ : desiredOverlapConflict
1745
+ ? 'conflict'
1746
+ : !desiredEnabled
1747
+ ? ownershipState !== 'absent' || desired.relation === 'managed'
1748
+ ? 'orphaned'
1749
+ : 'absent'
1750
+ : sharedNative?.state === 'foreign'
1751
+ ? 'conflict'
1752
+ : sharedNative?.state === 'corrupt'
1753
+ ? 'drifted'
1754
+ : sharedNative?.state === 'missing' || sharedNative?.state === 'outdated' || claimMissing
1755
+ ? 'needsSync'
1756
+ : activationDrift || extensions?.state === 'drifted'
1757
+ ? 'drifted'
1758
+ : extensions?.state === 'missing' || ownershipState === 'absent'
1759
+ ? 'needsSync'
1760
+ : ownershipState === 'partial' || ownershipState === 'error'
1761
+ ? 'drifted'
1762
+ : 'ready';
1763
+ const baseTargetErrors = observedTargets.flatMap((candidate) => candidate.errors);
1764
+ const stableErrors = [
1765
+ ...(sharedNative?.state === 'foreign'
1766
+ && !baseTargetErrors.some((error) => error.code === 'codexSharedNativeForeign')
1767
+ ? [warning('codexSharedNativeForeign', `${sharedNative.pluginId} is foreign and was preserved.`)]
1768
+ : []),
1769
+ ...(sharedNative?.state === 'corrupt'
1770
+ && !baseTargetErrors.some((error) => error.code === 'codexSharedNativeCorrupt')
1771
+ ? [warning('codexSharedNativeCorrupt', `${sharedNative.pluginId} is corrupt.`)]
1772
+ : []),
1773
+ ...(sharedNative?.state === 'outdated'
1774
+ ? [warning('codexSharedNativeUpdateRequired', `${sharedNative.pluginId} requires a shared update.`)]
1775
+ : []),
1776
+ ...(desiredOverlapConflict
1777
+ ? [warning('codexExtensionScopeConflict', `${target.pluginId} has AW extensions desired at user and project scope.`)]
1778
+ : []),
1779
+ ...(activationDrift && sharedNative?.state !== 'missing'
1780
+ ? [warning('codexActivationDrift', `${target.pluginId} activation differs from desired intent.`)]
1781
+ : []),
1782
+ ...(extensions?.state === 'drifted'
1783
+ ? [warning('codexExtensionDrift', `${target.pluginId} extension projection has drifted.`)]
1784
+ : []),
1785
+ ...(target.platform === 'codex' && hasSourceError && desiredEnabled
1786
+ ? [warning('codexIntentSourceUnavailable', `${target.pluginId} desired intent cannot be resolved from the current Catalog.`)]
1787
+ : []),
1788
+ ...(target.platform === 'codex' && consumerBlocking && desiredEnabled
1789
+ ? [warning(consumerIssue.code, consumerIssue.diagnostic)]
1790
+ : []),
1791
+ ];
1792
+ const targetErrors = [...baseTargetErrors, ...stableErrors];
1793
+ const dedupedErrors = [...new Map(targetErrors.map((error) => [
1794
+ `${error.code}\0${error.message}`,
1795
+ error,
1796
+ ])).values()];
1797
+ const components = [...new Map(observedTargets.flatMap((candidate) => candidate.components)
1798
+ .map((component) => [component.key, component])).values()];
1799
+ const representativeScope = explicitScope
1800
+ ?? (desired.scopes.length === 1
1801
+ ? desired.scopes[0]
1802
+ : observedTargets.find((candidate) => candidate.state !== 'absent')?.scope
1803
+ ?? (groupedScopes.includes('user') ? 'user' : groupedScopes[0] ?? target.scope));
1804
+ return {
1805
+ ...target,
1806
+ scope: representativeScope,
1807
+ state: ownershipState,
1808
+ components,
1809
+ errors: dedupedErrors,
1810
+ desired: {
1811
+ enabled: desiredEnabled,
1812
+ scopes: desired.scopes,
1813
+ relation: desired.relation,
1814
+ },
1815
+ actual: { state: actual },
1816
+ recovery: statusRecovery({
1817
+ actual,
1818
+ desired,
1819
+ platform: target.platform,
1820
+ pluginId: target.pluginId,
1821
+ ...(sharedNative ? { sharedNative } : {}),
1822
+ conflictRoots: rootIntentsForTarget({
1823
+ pluginId: target.pluginId,
1824
+ platform: target.platform,
1825
+ userIntent,
1826
+ projectIntent,
1827
+ available,
1828
+ }),
1829
+ errorCodes: dedupedErrors.map((error) => error.code),
1830
+ }),
1831
+ ...(sharedNative ? { sharedNative } : {}),
1832
+ ...(activation ? { activation } : {}),
1833
+ ...(extensions ? { extensions } : {}),
1834
+ };
1835
+ };
1836
+ const codexGroups = new Map();
1837
+ const projectedTargets = [];
1838
+ for (const target of draftTargets) {
1839
+ if (target.platform !== 'codex') {
1840
+ projectedTargets.push(await decorateTarget(target, [target.scope], [target]));
1841
+ continue;
1842
+ }
1843
+ const group = codexGroups.get(target.pluginId) ?? [];
1844
+ group.push(target);
1845
+ codexGroups.set(target.pluginId, group);
1846
+ }
1847
+ for (const group of codexGroups.values()) {
1848
+ const scopes = [...new Set(group.map((target) => target.scope))].sort();
1849
+ projectedTargets.push(await decorateTarget(group[0], scopes, group));
1850
+ }
1851
+ projectedTargets.sort((left, right) => `${left.pluginId}\0${left.platform}\0${left.scope}`.localeCompare(`${right.pluginId}\0${right.platform}\0${right.scope}`, 'en'));
1852
+ const targetRevisions = projectedTargets.map((target) => {
1853
+ const entry = selectedByPluginId.get(target.pluginId);
1854
+ return {
1855
+ pluginId: target.pluginId,
1856
+ platform: target.platform,
1857
+ scope: target.scope,
1858
+ revision: projectTargetRevision(entry?.version, entry?.states[target.platform]?.[target.scope]?.installedVersion),
1859
+ };
1860
+ });
1861
+ const payload = {
1862
+ schemaVersion: 6,
1863
+ catalog: {
1864
+ primarySourceId: catalog.primarySourceId,
1865
+ configDigest: catalog.configDigest,
1866
+ compositeDigest: catalog.compositeDigest,
1867
+ ...(options.catalogOperationContext
1868
+ ? { generationSetDigest: options.catalogOperationContext.generationSetDigest }
1869
+ : {}),
1870
+ sources: catalog.sources.map((source) => {
1871
+ if (!('plugins' in source))
1872
+ return source;
1873
+ const { plugins: _plugins, ...projected } = source;
1874
+ return projected;
1875
+ }),
1876
+ },
1877
+ filters: {
1878
+ plugins: requested,
1879
+ platform: options.platform === undefined ? 'both' : parsePlatformValue(options.platform),
1880
+ ...(options.scope === undefined ? {} : { scope: parseScopeValue(options.scope) }),
1881
+ cwd: path.resolve(options.cwd),
1882
+ },
1883
+ targets: projectedTargets,
1884
+ errors,
1885
+ };
1886
+ const hasErrors = payload.catalog.sources.some((source) => source.error !== undefined)
1887
+ || payload.errors.length > 0
1888
+ || payload.targets.some((target) => target.errors.some((error) => error.severity === 'blocking'));
1889
+ return {
1890
+ payload,
1891
+ output: options.json ? JSON.stringify(payload) : renderStatusV6(payload, options.verbose === true),
1892
+ hasErrors,
1893
+ targetRevisions,
1894
+ pluginSummaries: available.map((entry) => {
1895
+ const sourceEntries = available.filter((candidate) => candidate.source.id === entry.source.id);
1896
+ const byName = new Map(sourceEntries.map((candidate) => [candidate.name, candidate]));
1897
+ const transitive = new Set();
1898
+ const visit = (name) => {
1899
+ const candidate = byName.get(name);
1900
+ for (const dependency of candidate?.dependencies ?? []) {
1901
+ if (transitive.has(dependency))
1902
+ continue;
1903
+ transitive.add(dependency);
1904
+ visit(dependency);
1905
+ }
1906
+ };
1907
+ visit(entry.name);
1908
+ const dependencyIssueCount = targets.filter((target) => target.pluginId === formatPluginId({
1909
+ sourceId: entry.source.id,
1910
+ pluginName: entry.name,
1911
+ })).reduce((count, target) => count + target.errors.filter((error) => error.code.startsWith('dependency')
1912
+ || error.code === 'awCapabilityUnsupported'
1913
+ || error.code === 'sourceChanged').length, 0);
1914
+ return {
1915
+ pluginName: entry.name,
1916
+ pluginId: formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
1917
+ displayName: entry.displayName,
1918
+ description: entry.shortDescription,
1919
+ version: entry.version,
1920
+ supportedTargets: {
1921
+ codex: ['user', 'project'].filter((scope) => entry.targets.codex[scope]),
1922
+ claude: ['user', 'project'].filter((scope) => entry.targets.claude[scope]),
1923
+ },
1924
+ configFieldCount: Object.keys(entry.configSchema ?? {}).length,
1925
+ ...(entry.configSchema ? { configSchema: entry.configSchema } : {}),
1926
+ ...(entry.configIssues ? { configIssues: entry.configIssues } : {}),
1927
+ ...(entry.configDiagnostic ? { configDiagnostic: entry.configDiagnostic } : {}),
1928
+ dependencyDirectCount: entry.dependencies.length,
1929
+ dependencyTotalCount: transitive.size,
1930
+ dependencyIssueCount,
1931
+ ...(entry.missingCapabilities
1932
+ ? { missingCapabilities: entry.missingCapabilities }
1933
+ : {}),
1934
+ };
1935
+ }),
1936
+ };
1937
+ }
1938
+ //# sourceMappingURL=status-v6.js.map