@lesliechan721/aw 0.1.0-beta.8 → 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 (275) 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 +4 -4
  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/remove-plugin.mjs +1 -1
  10. package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
  11. package/dist/authoring/scripts/validate-plugin.mjs +34 -778
  12. package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
  13. package/dist/scripts/aw-skill-eval-materializer.d.ts +24 -0
  14. package/dist/scripts/{plugin-eval-materializer.js → aw-skill-eval-materializer.js} +34 -145
  15. package/dist/scripts/aw-skill-eval-materializer.js.map +1 -0
  16. package/dist/scripts/bundle-plugins.d.ts +1 -0
  17. package/dist/scripts/bundle-plugins.js +2 -1
  18. package/dist/scripts/bundle-plugins.js.map +1 -1
  19. package/dist/scripts/plugin-staging.d.ts +5 -6
  20. package/dist/scripts/plugin-staging.js +12 -13
  21. package/dist/scripts/plugin-staging.js.map +1 -1
  22. package/dist/src/authoring/workspace-commands.d.ts +2 -1
  23. package/dist/src/authoring/workspace-commands.js.map +1 -1
  24. package/dist/src/commands/aw-capabilities.d.ts +2 -2
  25. package/dist/src/commands/aw-capabilities.js +6 -11
  26. package/dist/src/commands/aw-capabilities.js.map +1 -1
  27. package/dist/src/commands/catalog-dev-source.d.ts +18 -12
  28. package/dist/src/commands/catalog-dev-source.js +241 -305
  29. package/dist/src/commands/catalog-dev-source.js.map +1 -1
  30. package/dist/src/commands/catalog-generation.d.ts +6 -19
  31. package/dist/src/commands/catalog-generation.js +10 -11
  32. package/dist/src/commands/catalog-generation.js.map +1 -1
  33. package/dist/src/commands/catalog-publication-inspection.d.ts +28 -27
  34. package/dist/src/commands/catalog-publication-inspection.js +139 -50
  35. package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
  36. package/dist/src/commands/catalog-publication-journal.d.ts +49 -0
  37. package/dist/src/commands/catalog-publication-journal.js +147 -0
  38. package/dist/src/commands/catalog-publication-journal.js.map +1 -0
  39. package/dist/src/commands/catalog-publication-target.d.ts +2 -1
  40. package/dist/src/commands/catalog-publication-target.js +37 -2
  41. package/dist/src/commands/catalog-publication-target.js.map +1 -1
  42. package/dist/src/commands/catalog-publish.d.ts +51 -15
  43. package/dist/src/commands/catalog-publish.js +576 -219
  44. package/dist/src/commands/catalog-publish.js.map +1 -1
  45. package/dist/src/commands/catalog-source.d.ts +3 -28
  46. package/dist/src/commands/catalog-source.js +29 -140
  47. package/dist/src/commands/catalog-source.js.map +1 -1
  48. package/dist/src/commands/catalog-status.d.ts +6 -26
  49. package/dist/src/commands/catalog-status.js +8 -146
  50. package/dist/src/commands/catalog-status.js.map +1 -1
  51. package/dist/src/commands/catalog-workspace-resolution.d.ts +13 -0
  52. package/dist/src/commands/catalog-workspace-resolution.js +42 -0
  53. package/dist/src/commands/catalog-workspace-resolution.js.map +1 -0
  54. package/dist/src/commands/dependency-operation-plan.d.ts +88 -9
  55. package/dist/src/commands/dependency-operation-plan.js +331 -6
  56. package/dist/src/commands/dependency-operation-plan.js.map +1 -1
  57. package/dist/src/commands/init.d.ts +5 -11
  58. package/dist/src/commands/init.js +30 -51
  59. package/dist/src/commands/init.js.map +1 -1
  60. package/dist/src/commands/offline-cleanup-evidence.d.ts +20 -0
  61. package/dist/src/commands/offline-cleanup-evidence.js +87 -9
  62. package/dist/src/commands/offline-cleanup-evidence.js.map +1 -1
  63. package/dist/src/commands/options.d.ts +6 -1
  64. package/dist/src/commands/options.js +64 -6
  65. package/dist/src/commands/options.js.map +1 -1
  66. package/dist/src/commands/plugin-capabilities.js +4 -0
  67. package/dist/src/commands/plugin-capabilities.js.map +1 -1
  68. package/dist/src/commands/rebuild-command.d.ts +10 -8
  69. package/dist/src/commands/rebuild-command.js +1217 -426
  70. package/dist/src/commands/rebuild-command.js.map +1 -1
  71. package/dist/src/commands/rebuild-integration.d.ts +54 -6
  72. package/dist/src/commands/rebuild-integration.js +691 -364
  73. package/dist/src/commands/rebuild-integration.js.map +1 -1
  74. package/dist/src/commands/rebuild-operations.d.ts +2 -0
  75. package/dist/src/commands/rebuild-operations.js +31 -17
  76. package/dist/src/commands/rebuild-operations.js.map +1 -1
  77. package/dist/src/commands/skill-eval.d.ts +33 -0
  78. package/dist/src/commands/skill-eval.js +363 -0
  79. package/dist/src/commands/skill-eval.js.map +1 -0
  80. package/dist/src/commands/{status-v5.d.ts → status-v6.d.ts} +59 -26
  81. package/dist/src/commands/{status-v5.js → status-v6.js} +882 -79
  82. package/dist/src/commands/status-v6.js.map +1 -0
  83. package/dist/src/commands/sync-command.d.ts +21 -0
  84. package/dist/src/commands/sync-command.js +206 -0
  85. package/dist/src/commands/sync-command.js.map +1 -0
  86. package/dist/src/commands/wizard.d.ts +2 -2
  87. package/dist/src/commands/write-commands.js +1 -43
  88. package/dist/src/commands/write-commands.js.map +1 -1
  89. package/dist/src/constants.d.ts +5 -4
  90. package/dist/src/constants.js +5 -4
  91. package/dist/src/constants.js.map +1 -1
  92. package/dist/src/eval/manifest-v1.d.ts +66 -0
  93. package/dist/src/eval/manifest-v1.js +326 -0
  94. package/dist/src/eval/manifest-v1.js.map +1 -0
  95. package/dist/src/generators/local-plugin.d.ts +3 -0
  96. package/dist/src/generators/local-plugin.js +123 -55
  97. package/dist/src/generators/local-plugin.js.map +1 -1
  98. package/dist/src/index.d.ts +2 -0
  99. package/dist/src/index.js +412 -152
  100. package/dist/src/index.js.map +1 -1
  101. package/dist/src/output/command-receipt.d.ts +58 -8
  102. package/dist/src/output/command-receipt.js +141 -11
  103. package/dist/src/output/command-receipt.js.map +1 -1
  104. package/dist/src/output/model.d.ts +3 -11
  105. package/dist/src/portable/commands.d.ts +2 -2
  106. package/dist/src/portable/commands.js +2 -8
  107. package/dist/src/portable/commands.js.map +1 -1
  108. package/dist/src/portable/materializer.d.ts +1 -4
  109. package/dist/src/portable/materializer.js +0 -2
  110. package/dist/src/portable/materializer.js.map +1 -1
  111. package/dist/src/tui/catalog-generation.d.ts +20 -41
  112. package/dist/src/tui/catalog-generation.js +65 -224
  113. package/dist/src/tui/catalog-generation.js.map +1 -1
  114. package/dist/src/tui/components.js +1 -2
  115. package/dist/src/tui/components.js.map +1 -1
  116. package/dist/src/tui/console-app-v4.js +461 -330
  117. package/dist/src/tui/console-app-v4.js.map +1 -1
  118. package/dist/src/tui/controller-runtime.d.ts +3 -5
  119. package/dist/src/tui/controller-runtime.js +182 -187
  120. package/dist/src/tui/controller-runtime.js.map +1 -1
  121. package/dist/src/tui/controller.d.ts +42 -45
  122. package/dist/src/tui/controller.js +454 -407
  123. package/dist/src/tui/controller.js.map +1 -1
  124. package/dist/src/tui/diagnostics.d.ts +1 -2
  125. package/dist/src/tui/diagnostics.js.map +1 -1
  126. package/dist/src/tui/index.d.ts +1 -1
  127. package/dist/src/tui/index.js +1 -1
  128. package/dist/src/tui/index.js.map +1 -1
  129. package/dist/src/tui/model.d.ts +81 -13
  130. package/dist/src/tui/model.js +378 -95
  131. package/dist/src/tui/model.js.map +1 -1
  132. package/dist/src/tui/router.d.ts +9 -0
  133. package/dist/src/tui/router.js.map +1 -1
  134. package/dist/src/types.d.ts +54 -47
  135. package/dist/src/types.js.map +1 -1
  136. package/dist/src/utils/agent-version.d.ts +4 -1
  137. package/dist/src/utils/agent-version.js +28 -3
  138. package/dist/src/utils/agent-version.js.map +1 -1
  139. package/dist/src/utils/catalog-digests.d.ts +7 -0
  140. package/dist/src/utils/catalog-digests.js +27 -0
  141. package/dist/src/utils/catalog-digests.js.map +1 -1
  142. package/dist/src/utils/catalog-generation-control-snapshot.d.ts +11 -0
  143. package/dist/src/utils/catalog-generation-control-snapshot.js +45 -0
  144. package/dist/src/utils/catalog-generation-control-snapshot.js.map +1 -0
  145. package/dist/src/utils/catalog-generation-error.d.ts +2 -1
  146. package/dist/src/utils/catalog-generation-error.js +12 -0
  147. package/dist/src/utils/catalog-generation-error.js.map +1 -1
  148. package/dist/src/utils/catalog-generation-resolver.d.ts +10 -3
  149. package/dist/src/utils/catalog-generation-resolver.js +90 -76
  150. package/dist/src/utils/catalog-generation-resolver.js.map +1 -1
  151. package/dist/src/utils/catalog-generation-service.d.ts +24 -33
  152. package/dist/src/utils/catalog-generation-service.js +253 -567
  153. package/dist/src/utils/catalog-generation-service.js.map +1 -1
  154. package/dist/src/utils/catalog-generation-state.d.ts +4 -0
  155. package/dist/src/utils/catalog-generation-state.js +73 -106
  156. package/dist/src/utils/catalog-generation-state.js.map +1 -1
  157. package/dist/src/utils/catalog-generation-store.d.ts +16 -26
  158. package/dist/src/utils/catalog-generation-store.js +154 -290
  159. package/dist/src/utils/catalog-generation-store.js.map +1 -1
  160. package/dist/src/utils/catalog-manifest-v6.d.ts +5 -0
  161. package/dist/src/utils/{catalog-manifest-v5.js → catalog-manifest-v6.js} +23 -35
  162. package/dist/src/utils/catalog-manifest-v6.js.map +1 -0
  163. package/dist/src/utils/catalog-operation-context.d.ts +6 -14
  164. package/dist/src/utils/catalog-operation-context.js +68 -169
  165. package/dist/src/utils/catalog-operation-context.js.map +1 -1
  166. package/dist/src/utils/catalog-public-error.js +1 -4
  167. package/dist/src/utils/catalog-public-error.js.map +1 -1
  168. package/dist/src/utils/catalog-runtime-projection.d.ts +3 -0
  169. package/dist/src/utils/catalog-runtime-projection.js +5 -40
  170. package/dist/src/utils/catalog-runtime-projection.js.map +1 -1
  171. package/dist/src/utils/catalog-snapshot.d.ts +2 -2
  172. package/dist/src/utils/catalog-source-references.d.ts +7 -0
  173. package/dist/src/utils/catalog-source-references.js +44 -55
  174. package/dist/src/utils/catalog-source-references.js.map +1 -1
  175. package/dist/src/utils/catalog-sources.js +25 -9
  176. package/dist/src/utils/catalog-sources.js.map +1 -1
  177. package/dist/src/utils/codex-config.d.ts +2 -0
  178. package/dist/src/utils/codex-config.js +22 -1
  179. package/dist/src/utils/codex-config.js.map +1 -1
  180. package/dist/src/utils/codex-manager.d.ts +50 -2
  181. package/dist/src/utils/codex-manager.js +160 -6
  182. package/dist/src/utils/codex-manager.js.map +1 -1
  183. package/dist/src/utils/codex-reconciler.d.ts +131 -0
  184. package/dist/src/utils/codex-reconciler.js +327 -0
  185. package/dist/src/utils/codex-reconciler.js.map +1 -0
  186. package/dist/src/utils/codex-shared-native.d.ts +56 -0
  187. package/dist/src/utils/codex-shared-native.js +87 -0
  188. package/dist/src/utils/codex-shared-native.js.map +1 -0
  189. package/dist/src/utils/codex-surface-analysis.d.ts +44 -0
  190. package/dist/src/utils/codex-surface-analysis.js +247 -0
  191. package/dist/src/utils/codex-surface-analysis.js.map +1 -0
  192. package/dist/src/utils/git-catalog-provider.js +56 -115
  193. package/dist/src/utils/git-catalog-provider.js.map +1 -1
  194. package/dist/src/utils/manifest.d.ts +1 -3
  195. package/dist/src/utils/manifest.js +1 -3
  196. package/dist/src/utils/manifest.js.map +1 -1
  197. package/dist/src/utils/multi-source-catalog.d.ts +1 -10
  198. package/dist/src/utils/multi-source-catalog.js +8 -175
  199. package/dist/src/utils/multi-source-catalog.js.map +1 -1
  200. package/dist/src/utils/native-cli.d.ts +34 -0
  201. package/dist/src/utils/native-cli.js +91 -0
  202. package/dist/src/utils/native-cli.js.map +1 -1
  203. package/dist/src/utils/orphan-marketplace-cleanup.js +1 -0
  204. package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
  205. package/dist/src/utils/ownership.d.ts +0 -10
  206. package/dist/src/utils/ownership.js +3 -88
  207. package/dist/src/utils/ownership.js.map +1 -1
  208. package/dist/src/utils/path-catalog-provider.d.ts +1 -1
  209. package/dist/src/utils/path-catalog-provider.js +45 -62
  210. package/dist/src/utils/path-catalog-provider.js.map +1 -1
  211. package/dist/src/utils/paths.d.ts +0 -1
  212. package/dist/src/utils/paths.js +0 -1
  213. package/dist/src/utils/paths.js.map +1 -1
  214. package/dist/src/utils/plugin-config-write.js +0 -5
  215. package/dist/src/utils/plugin-config-write.js.map +1 -1
  216. package/dist/src/utils/plugin-intent-state.d.ts +39 -0
  217. package/dist/src/utils/plugin-intent-state.js +325 -0
  218. package/dist/src/utils/plugin-intent-state.js.map +1 -0
  219. package/dist/src/utils/target-eligibility.d.ts +3 -2
  220. package/dist/src/utils/target-eligibility.js +4 -3
  221. package/dist/src/utils/target-eligibility.js.map +1 -1
  222. package/package.json +5 -4
  223. package/dist/scripts/aw-skill-eval-engine.d.ts +0 -13
  224. package/dist/scripts/aw-skill-eval-engine.js +0 -31
  225. package/dist/scripts/aw-skill-eval-engine.js.map +0 -1
  226. package/dist/scripts/codex-eval-app-server.d.ts +0 -91
  227. package/dist/scripts/codex-eval-app-server.js +0 -1334
  228. package/dist/scripts/codex-eval-app-server.js.map +0 -1
  229. package/dist/scripts/codex-eval-isolation.d.ts +0 -61
  230. package/dist/scripts/codex-eval-isolation.js +0 -318
  231. package/dist/scripts/codex-eval-isolation.js.map +0 -1
  232. package/dist/scripts/codex-eval-process-management.d.ts +0 -8
  233. package/dist/scripts/codex-eval-process-management.js +0 -69
  234. package/dist/scripts/codex-eval-process-management.js.map +0 -1
  235. package/dist/scripts/codex-eval-process-tree.d.ts +0 -38
  236. package/dist/scripts/codex-eval-process-tree.js +0 -803
  237. package/dist/scripts/codex-eval-process-tree.js.map +0 -1
  238. package/dist/scripts/codex-eval-runtime-config.d.ts +0 -62
  239. package/dist/scripts/codex-eval-runtime-config.js +0 -843
  240. package/dist/scripts/codex-eval-runtime-config.js.map +0 -1
  241. package/dist/scripts/codex-trigger-eval.d.ts +0 -84
  242. package/dist/scripts/codex-trigger-eval.js +0 -968
  243. package/dist/scripts/codex-trigger-eval.js.map +0 -1
  244. package/dist/scripts/eval-plugin-skills-audited.d.ts +0 -6
  245. package/dist/scripts/eval-plugin-skills-audited.js +0 -261
  246. package/dist/scripts/eval-plugin-skills-audited.js.map +0 -1
  247. package/dist/scripts/eval-plugin-skills.d.ts +0 -45
  248. package/dist/scripts/eval-plugin-skills.js +0 -1589
  249. package/dist/scripts/eval-plugin-skills.js.map +0 -1
  250. package/dist/scripts/eval-run-layout.d.ts +0 -17
  251. package/dist/scripts/eval-run-layout.js +0 -26
  252. package/dist/scripts/eval-run-layout.js.map +0 -1
  253. package/dist/scripts/plugin-eval-contract.d.ts +0 -189
  254. package/dist/scripts/plugin-eval-contract.js +0 -745
  255. package/dist/scripts/plugin-eval-contract.js.map +0 -1
  256. package/dist/scripts/plugin-eval-materializer.d.ts +0 -13
  257. package/dist/scripts/plugin-eval-materializer.js.map +0 -1
  258. package/dist/scripts/skill-reporting.d.ts +0 -212
  259. package/dist/scripts/skill-reporting.js +0 -922
  260. package/dist/scripts/skill-reporting.js.map +0 -1
  261. package/dist/src/commands/catalog-context.d.ts +0 -52
  262. package/dist/src/commands/catalog-context.js +0 -156
  263. package/dist/src/commands/catalog-context.js.map +0 -1
  264. package/dist/src/commands/status-v5.js.map +0 -1
  265. package/dist/src/utils/catalog-manifest-v5.d.ts +0 -5
  266. package/dist/src/utils/catalog-manifest-v5.js.map +0 -1
  267. package/dist/src/utils/catalog-source-cache.d.ts +0 -62
  268. package/dist/src/utils/catalog-source-cache.js +0 -321
  269. package/dist/src/utils/catalog-source-cache.js.map +0 -1
  270. package/dist/src/utils/codex-project-surface.d.ts +0 -3
  271. package/dist/src/utils/codex-project-surface.js +0 -49
  272. package/dist/src/utils/codex-project-surface.js.map +0 -1
  273. package/dist/src/utils/plugin-release.d.ts +0 -2
  274. package/dist/src/utils/plugin-release.js +0 -2
  275. package/dist/src/utils/plugin-release.js.map +0 -1
@@ -1,29 +1,35 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { hasCodexProjectManagedArtifacts } from '../utils/codex-project-surface.js';
3
+ import { analyzeCodexSurface } from '../utils/codex-surface-analysis.js';
4
4
  import { catalogSourceErrorCode, sanitizeCatalogSourceError, } from '../utils/catalog-public-error.js';
5
5
  import { calculateCatalogSourceIdentity } from '../utils/catalog-source-identity.js';
6
6
  import { canonicalMarketplaceRegistrationNames, inventoryCatalogSourceReferences, inventoryLegacyOwnerReferences, } from '../utils/catalog-source-references.js';
7
7
  import { readCatalogSourcesConfigSnapshot, resolveCatalogSourceRef } from '../utils/catalog-sources.js';
8
8
  import { formatPluginId, parsePluginId, planPluginSelectorSourceIds, withResolvedMultiSourceCatalog, } from '../utils/multi-source-catalog.js';
9
9
  import { assertStrictSemVer, checkAwCapabilitySupport, compareStrictSemVer, readPluginManifest, tryParseStrictSemVer, } from '../utils/manifest.js';
10
- import { resolveCliPackageRoot } from '../utils/paths.js';
10
+ import { resolveCliPackageRoot, resolveCodexPaths } from '../utils/paths.js';
11
11
  import { supportsPlatform } from '../utils/platform-support.js';
12
12
  import { parsePlatformValue, parseScopeValue } from './options.js';
13
- import { inspectRebuildTarget } from './rebuild-integration.js';
13
+ import { inspectCodexNativeResidue, inspectCodexSharedNativeLive, inspectRebuildTarget, } from './rebuild-integration.js';
14
14
  import { createNoopReporter } from '../output/reporter.js';
15
15
  import { createNoopDebugLogger } from '../output/debug-log.js';
16
16
  import { getDefaultNativeCliRunner } from '../utils/native-cli.js';
17
17
  import { resolveAwHome } from '../utils/paths.js';
18
18
  import { codexProjectConfigAliasesUserHome, createProjectLocationKey, getClaudeHome, getCodexHome, resolveCanonicalRepoProjectKey, } from '../utils/state-paths.js';
19
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';
20
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';
21
27
  let dependencyInspectionHookForTests;
22
28
  export function setStatusDependencyInspectionHookForTests(hook) {
23
29
  dependencyInspectionHookForTests = hook;
24
30
  }
25
31
  export async function loadConsoleItemsResult(options = {}, runtime = {}) {
26
- const result = await statusCommandV5({
32
+ const result = await statusCommandV6({
27
33
  cwd: options.cwd ?? process.cwd(),
28
34
  env: runtime.env,
29
35
  platform: options.platform,
@@ -89,13 +95,24 @@ function inventoryErrorMatchesSelection(options) {
89
95
  || selector.parsed.sourceId === undefined
90
96
  || selector.parsed.sourceId === relevance.sourceId));
91
97
  }
92
- function projectTargetError(error, env, cwd) {
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) {
93
110
  const sanitized = sanitizeCatalogSourceError(new Error(error.message), env, [
94
111
  getCodexHome(env),
95
112
  getClaudeHome(env),
96
113
  path.resolve(cwd),
97
114
  ]);
98
- return { ...error, message: sanitized.message };
115
+ return finalizeTargetError({ ...error, message: sanitized.message }, targetState);
99
116
  }
100
117
  function sourceRequestedRef(source, cliVersion) {
101
118
  return source.type === 'git' ? resolveCatalogSourceRef(source.refPolicy, cliVersion) : 'path';
@@ -107,6 +124,203 @@ function selectedPlatforms(value) {
107
124
  function selectedScopes(value) {
108
125
  return value === undefined ? ['user', 'project'] : [parseScopeValue(value)];
109
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
+ }
110
324
  function projectedLiveState(options) {
111
325
  if (options.inspection.state === 'error'
112
326
  || options.inspection.components.some((entry) => entry.state === 'error'))
@@ -144,7 +358,7 @@ export function projectTargetRevision(availableVersion, installedVersion) {
144
358
  return { state: 'upgradeAvailable', availableVersion, installedVersion };
145
359
  return { state: 'unknown', availableVersion, installedVersion };
146
360
  }
147
- function renderStatusV5(payload, verbose) {
361
+ function renderStatusV6(payload, verbose) {
148
362
  const lines = [`Catalog sources: ${payload.catalog.sources.length}`];
149
363
  for (const source of payload.catalog.sources) {
150
364
  lines.push(`${source.primary ? '*' : '-'} ${source.id}: ${source.error ?? source.freshness ?? 'unavailable'}`);
@@ -153,7 +367,23 @@ function renderStatusV5(payload, verbose) {
153
367
  const errors = target.errors.length > 0
154
368
  ? ` [${target.errors.map((error) => `${error.code}: ${error.message}`).join('; ')}]`
155
369
  : '';
156
- lines.push(`${target.pluginId} ${target.platform}/${target.scope}: ${target.state}${errors}`);
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
+ }
157
387
  if (verbose) {
158
388
  for (const component of target.components) {
159
389
  const error = component.error
@@ -185,12 +415,47 @@ function collisionRootIssueId(options) {
185
415
  options.collision.artifactKey,
186
416
  ].join(':');
187
417
  }
188
- export async function statusCommandV5(options) {
418
+ export async function statusCommandV6(options) {
189
419
  const env = options.env ?? process.env;
190
420
  const dependencyPluginCache = new Map();
191
421
  const dependencyInspectionCache = new Map();
192
422
  const cliVersion = options.cliVersion ?? assertStrictSemVer(JSON.parse(fs.readFileSync(path.join(resolveCliPackageRoot(), 'package.json'), 'utf8')).version, 'packages/cli/package.json version');
193
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
+ ]);
194
459
  const currentProjectKey = await resolveCanonicalRepoProjectKey(options.cwd);
195
460
  const currentProjectLocationKey = createProjectLocationKey(currentProjectKey);
196
461
  const codexScopePathsAlias = codexProjectConfigAliasesUserHome(options.cwd, env);
@@ -212,6 +477,39 @@ export async function statusCommandV5(options) {
212
477
  relevance: error.relevance,
213
478
  });
214
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
+ };
215
513
  const hasCurrentCodexProjectOwner = (sourceId, pluginName) => ownerInventory.references.some((reference) => reference.kind === 'namespacedOwner'
216
514
  && reference.sourceId === sourceId
217
515
  && reference.pluginName === pluginName
@@ -222,6 +520,19 @@ export async function statusCommandV5(options) {
222
520
  const requested = options.plugins ?? [];
223
521
  const platforms = selectedPlatforms(options.platform);
224
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
+ };
225
536
  const selectorErrors = [];
226
537
  const parsedSelectors = [];
227
538
  const plannedSelectors = [];
@@ -296,16 +607,11 @@ export async function statusCommandV5(options) {
296
607
  const identities = new Map(identityEntries);
297
608
  const catalog = await withResolvedMultiSourceCatalog({
298
609
  cliVersion,
299
- freshnessPolicy: 'cacheFirst',
300
610
  configSnapshot: snapshot,
301
611
  ...(plannedSourceIds === undefined ? {} : { sourceIds: plannedSourceIds }),
302
612
  ...(options.catalogOperationContext
303
613
  ? { operationContext: options.catalogOperationContext }
304
614
  : {}),
305
- ...(options.bootstrapMissingActive === false ? { bootstrapMissingActive: false } : {}),
306
- ...(options.catalogGenerationRuntime?.providers
307
- ? { providers: options.catalogGenerationRuntime.providers }
308
- : {}),
309
615
  env,
310
616
  consume: async (resolution) => ({
311
617
  primarySourceId: resolution.primarySourceId,
@@ -330,6 +636,43 @@ export async function statusCommandV5(options) {
330
636
  };
331
637
  }
332
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
+ }
333
676
  const plugins = await Promise.all(item.resolution.manifest.entries.map(async (entry) => {
334
677
  const capabilitySupport = checkAwCapabilitySupport(entry.requires.aw.capabilities ?? [], IMPLEMENTED_AW_CAPABILITIES);
335
678
  if (!capabilitySupport.supported) {
@@ -346,13 +689,14 @@ export async function statusCommandV5(options) {
346
689
  states[platform][scope] = {
347
690
  state: 'error',
348
691
  components: [],
349
- errors: [{ code: 'awCapabilityUnsupported', message }],
692
+ errors: [finalizeTargetError({ code: 'awCapabilityUnsupported', message }, 'error')],
350
693
  };
351
694
  }
352
695
  }
353
696
  return {
354
697
  name: entry.name,
355
698
  version: entry.version,
699
+ sharedNativePayloadDigest: entry.contentDigest,
356
700
  displayName: entry.interface?.displayName ?? entry.name,
357
701
  shortDescription: entry.interface?.shortDescription ?? entry.description,
358
702
  description: entry.description,
@@ -368,6 +712,10 @@ export async function statusCommandV5(options) {
368
712
  const plugin = await readPluginManifest(path.join(item.resolution.rootDir, 'plugins', entry.name), { mode: 'bundle' });
369
713
  const claude = supportsPlatform(plugin.manifest, 'claude');
370
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;
371
719
  plugin.sourceId = item.resolution.sourceId;
372
720
  plugin.sourceIdentity = item.resolution.sourceIdentity;
373
721
  plugin.pluginId = formatPluginId({ sourceId: item.resolution.sourceId, pluginName: entry.name });
@@ -423,7 +771,7 @@ export async function statusCommandV5(options) {
423
771
  continue;
424
772
  const supported = platform === 'claude'
425
773
  ? claude
426
- : codex && (scope === 'user' || hasCodexProjectManagedArtifacts(plugin));
774
+ : codex && codexSurface.ok;
427
775
  if (!supported)
428
776
  continue;
429
777
  const changedOwner = ownerInventory.references.find((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
@@ -438,10 +786,10 @@ export async function statusCommandV5(options) {
438
786
  states[platform][scope] = {
439
787
  state: 'error',
440
788
  components: [],
441
- errors: [{
789
+ errors: [finalizeTargetError({
442
790
  code: 'sourceChanged',
443
791
  message: `sourceChanged: owner at ${changedOwner.location} has a different source identity.`,
444
- }],
792
+ }, 'error')],
445
793
  };
446
794
  continue;
447
795
  }
@@ -467,13 +815,23 @@ export async function statusCommandV5(options) {
467
815
  reporter: createNoopReporter(),
468
816
  debugLogger: createNoopDebugLogger(),
469
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
+ }),
470
828
  });
471
829
  const liveState = projectedLiveState({
472
830
  inspection: inspected.inspection,
473
831
  required: inspected.target.desiredOwnedComponents ?? inspected.target.ownedComponents,
474
832
  optional: inspected.target.optionalOwnedComponents ?? [],
475
833
  });
476
- const collisionErrors = inspected.inspection.components.flatMap((component) => component.collision ? [{
834
+ const collisionErrors = inspected.inspection.components.flatMap((component) => component.collision ? [finalizeTargetError({
477
835
  code: 'artifactCollision',
478
836
  message: collisionMessage(component.collision),
479
837
  collision: component.collision,
@@ -487,7 +845,7 @@ export async function statusCommandV5(options) {
487
845
  collision: component.collision,
488
846
  }),
489
847
  rootIssueCode: 'artifactCollision',
490
- }] : []);
848
+ }, liveState)] : []);
491
849
  const dependencyErrors = [];
492
850
  const dependencyReadiness = [];
493
851
  const directDependencies = plugin.manifest.dependencies ?? [];
@@ -507,13 +865,13 @@ export async function statusCommandV5(options) {
507
865
  rootIssueId,
508
866
  rootIssueCode: 'dependencyMissing',
509
867
  });
510
- dependencyErrors.push({
868
+ dependencyErrors.push(finalizeTargetError({
511
869
  code: 'dependencyMissing',
512
870
  message: `dependencyMissing: ${dependencyId} is not available in the current source snapshot.`,
513
871
  dependencyPluginId: dependencyId,
514
872
  rootIssueId,
515
873
  rootIssueCode: 'dependencyMissing',
516
- });
874
+ }, 'partial'));
517
875
  continue;
518
876
  }
519
877
  const dependencySupport = checkAwCapabilitySupport(dependencyEntry.requires.aw.capabilities ?? [], IMPLEMENTED_AW_CAPABILITIES);
@@ -525,13 +883,13 @@ export async function statusCommandV5(options) {
525
883
  rootIssueId,
526
884
  rootIssueCode: 'awCapabilityUnsupported',
527
885
  });
528
- dependencyErrors.push({
886
+ dependencyErrors.push(finalizeTargetError({
529
887
  code: 'awCapabilityUnsupported',
530
888
  message: `awCapabilityUnsupported: ${dependencyId} requires unsupported AW capabilities: ${dependencySupport.missing.join(', ')}.`,
531
889
  dependencyPluginId: dependencyId,
532
890
  rootIssueId,
533
891
  rootIssueCode: 'awCapabilityUnsupported',
534
- });
892
+ }, 'partial'));
535
893
  continue;
536
894
  }
537
895
  const pluginCacheKey = [item.resolution.sourceIdentity, dependencyId].join('\0');
@@ -579,6 +937,16 @@ export async function statusCommandV5(options) {
579
937
  reporter: createNoopReporter(),
580
938
  debugLogger: createNoopDebugLogger(),
581
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
+ }),
582
950
  });
583
951
  const dependencyLiveState = projectedLiveState({
584
952
  inspection: dependencyInspected.inspection,
@@ -651,16 +1019,16 @@ export async function statusCommandV5(options) {
651
1019
  ...dependencyResult,
652
1020
  });
653
1021
  if (dependencyResult.state === 'absent') {
654
- dependencyErrors.push({
1022
+ dependencyErrors.push(finalizeTargetError({
655
1023
  code: 'dependencyMissing',
656
1024
  message: `dependencyMissing: ${dependencyId} is absent from its required live placement.`,
657
1025
  dependencyPluginId: dependencyId,
658
1026
  rootIssueId: dependencyResult.rootIssueId,
659
1027
  rootIssueCode: dependencyResult.rootIssueCode,
660
- });
1028
+ }, 'partial'));
661
1029
  }
662
1030
  else if (dependencyResult.state !== 'ready') {
663
- dependencyErrors.push({
1031
+ dependencyErrors.push(finalizeTargetError({
664
1032
  code: 'dependencyNotReady',
665
1033
  message: `dependencyNotReady: ${dependencyId} is not ready at its required live placement.`,
666
1034
  dependencyPluginId: dependencyId,
@@ -670,38 +1038,36 @@ export async function statusCommandV5(options) {
670
1038
  ...(dependencyResult.rootIssueCode
671
1039
  ? { rootIssueCode: dependencyResult.rootIssueCode }
672
1040
  : {}),
673
- });
1041
+ }, 'partial'));
674
1042
  }
675
1043
  }
676
1044
  }
677
1045
  states[platform][scope] = {
678
- state: dependencyErrors.length > 0 && liveState === 'present' ? 'partial' : liveState,
679
- errors: [...inspected.inspection.errors.map((error) => ({
1046
+ state: liveState,
1047
+ errors: [...inspected.inspection.errors.map((error) => finalizeTargetError({
680
1048
  code: 'componentInspectionFailed',
681
1049
  message: `${error.label}: ${error.message}`,
682
- })), ...collisionErrors, ...dependencyErrors],
1050
+ }, liveState)), ...collisionErrors, ...dependencyErrors],
683
1051
  ...(dependencyReadiness.length > 0 ? { dependencyReadiness } : {}),
684
- components: options.verbose === true
685
- ? inspected.inspection.components.map((component) => {
686
- const projectedError = component.collision
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
687
1060
  ? projectTargetError({
688
- code: 'artifactCollision',
689
- message: collisionMessage(component.collision),
690
- collision: component.collision,
691
- }, env, options.cwd)
692
- : component.diagnostic
693
- ? projectTargetError({
694
- code: 'componentInspectionFailed',
695
- message: component.diagnostic,
696
- }, env, options.cwd)
697
- : undefined;
698
- return {
699
- key: component.component.identity.artifactKey,
700
- state: component.state,
701
- ...(projectedError ? { error: projectedError } : {}),
702
- };
703
- })
704
- : [],
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
+ }),
705
1071
  ...(inspected.installedVersion
706
1072
  ? { installedVersion: inspected.installedVersion }
707
1073
  : {}),
@@ -709,18 +1075,96 @@ export async function statusCommandV5(options) {
709
1075
  }
710
1076
  catch (error) {
711
1077
  const message = error instanceof Error ? error.message : String(error);
712
- const code = message.split(':', 1)[0] || 'targetInspectionFailed';
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';
713
1086
  states[platform][scope] = {
714
1087
  state: 'error',
715
1088
  components: [],
716
- errors: [{ code, message }],
1089
+ errors: [finalizeTargetError({
1090
+ code,
1091
+ message: configErrorCode
1092
+ ? `${configErrorCode}: Codex activation state is unreadable.`
1093
+ : message,
1094
+ }, 'error')],
717
1095
  };
718
1096
  }
719
1097
  }
720
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
+ }
721
1164
  return {
722
1165
  name: entry.name,
723
1166
  version: entry.version,
1167
+ sharedNativePayloadDigest,
724
1168
  displayName: plugin.manifest.interface?.displayName ?? entry.name,
725
1169
  shortDescription: plugin.manifest.interface?.shortDescription
726
1170
  ?? plugin.manifest.description,
@@ -743,11 +1187,14 @@ export async function statusCommandV5(options) {
743
1187
  claude: { user: claude, project: claude },
744
1188
  codex: {
745
1189
  user: codex,
746
- project: codex && hasCodexProjectManagedArtifacts(plugin),
1190
+ project: codex
1191
+ && codexSurface.ok
1192
+ && codexSurface.classification !== 'empty',
747
1193
  },
748
1194
  },
749
1195
  states,
750
1196
  dependencies: plugin.manifest.dependencies ?? [],
1197
+ ...(codexStatus ? { codex: codexStatus } : {}),
751
1198
  };
752
1199
  }));
753
1200
  return {
@@ -755,7 +1202,7 @@ export async function statusCommandV5(options) {
755
1202
  resolvedCommit: item.resolution.resolvedCommit,
756
1203
  catalogVersion: item.resolution.manifest.catalogVersion,
757
1204
  channel: item.resolution.manifest.channel,
758
- freshness: item.resolution.source,
1205
+ freshness: 'active',
759
1206
  plugins,
760
1207
  };
761
1208
  }
@@ -773,6 +1220,12 @@ export async function statusCommandV5(options) {
773
1220
  const available = catalog.sources.flatMap((source) => 'plugins' in source
774
1221
  ? source.plugins.map((plugin) => ({ ...plugin, source }))
775
1222
  : []);
1223
+ const desiredTargetStates = calculateDesiredTargetStates({
1224
+ userIntent,
1225
+ projectIntent,
1226
+ available,
1227
+ codexProjectAllowed: !codexScopePathsAlias,
1228
+ });
776
1229
  const failedSourceIds = new Set(catalog.sources.filter((source) => 'error' in source).map((source) => source.id));
777
1230
  const selectedById = new Map();
778
1231
  if (requested.length === 0) {
@@ -852,10 +1305,10 @@ export async function statusCommandV5(options) {
852
1305
  return [{
853
1306
  ...target,
854
1307
  state: 'error',
855
- errors: [{
1308
+ errors: [finalizeTargetError({
856
1309
  code: 'codexScopePathAlias',
857
1310
  message: 'codexScopePathAlias: Codex project config resolves to the user config directory. Run this command from an actual project directory.',
858
- }],
1311
+ }, 'error')],
859
1312
  }];
860
1313
  }
861
1314
  if (entry.targets[platform][scope]) {
@@ -867,10 +1320,10 @@ export async function statusCommandV5(options) {
867
1320
  ...target,
868
1321
  state: live?.state ?? 'error',
869
1322
  components: live?.components ?? [],
870
- errors: live?.errors ?? [{
1323
+ errors: live?.errors ?? [finalizeTargetError({
871
1324
  code: 'targetInspectionFailed',
872
1325
  message: `No live inspection result exists for ${entry.source.id}/${entry.name}.`,
873
- }],
1326
+ }, 'error')],
874
1327
  ...(live?.dependencyReadiness
875
1328
  ? { dependencyReadiness: live.dependencyReadiness }
876
1329
  : {}),
@@ -894,12 +1347,12 @@ export async function statusCommandV5(options) {
894
1347
  return [{
895
1348
  ...target,
896
1349
  state: 'error',
897
- errors: [{
1350
+ errors: [finalizeTargetError({
898
1351
  code: sourceChanged ? 'sourceChanged' : 'noLongerSupported',
899
1352
  message: sourceChanged
900
1353
  ? `sourceChanged: live state for ${target.pluginId} has a different source identity.`
901
1354
  : `noLongerSupported: ${target.pluginId} has live state for ${platform}/${scope}, but the current bundle no longer supports that target.`,
902
- }],
1355
+ }, 'error')],
903
1356
  }];
904
1357
  }
905
1358
  if (!explicitTargetFilter)
@@ -907,10 +1360,14 @@ export async function statusCommandV5(options) {
907
1360
  return [{
908
1361
  ...target,
909
1362
  state: 'error',
910
- errors: [{
911
- code: 'unsupportedTarget',
912
- message: `${entry.source.id}/${entry.name} does not support ${platform}/${scope}.`,
913
- }],
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')],
914
1371
  }];
915
1372
  })));
916
1373
  const referenceSelectors = [...plannedSelectors, ...liveOnlySelectors];
@@ -949,10 +1406,10 @@ export async function statusCommandV5(options) {
949
1406
  cwd: path.resolve(options.cwd),
950
1407
  state: 'error',
951
1408
  components: [],
952
- errors: [{
1409
+ errors: [finalizeTargetError({
953
1410
  code: 'sourceMissing',
954
1411
  message: `sourceMissing: catalog source "${reference.sourceId}" is not configured for ${pluginId}.`,
955
- }],
1412
+ }, 'error')],
956
1413
  };
957
1414
  return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
958
1415
  })).values()];
@@ -978,10 +1435,10 @@ export async function statusCommandV5(options) {
978
1435
  cwd: path.resolve(options.cwd),
979
1436
  state: 'error',
980
1437
  components: [],
981
- errors: [{
1438
+ errors: [finalizeTargetError({
982
1439
  code: 'catalogSourceUnavailable',
983
1440
  message: `catalogSourceUnavailable: catalog source "${reference.sourceId}" is unavailable for ${pluginId}.`,
984
- }],
1441
+ }, 'error')],
985
1442
  };
986
1443
  return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
987
1444
  })).values()];
@@ -1017,14 +1474,142 @@ export async function statusCommandV5(options) {
1017
1474
  cwd: path.resolve(options.cwd),
1018
1475
  state: 'error',
1019
1476
  components: [],
1020
- errors: [{
1477
+ errors: [finalizeTargetError({
1021
1478
  code: 'bundleUnavailable',
1022
1479
  message: `bundleUnavailable: ${pluginId} has live state but is not present in the current source snapshot.`,
1023
- }],
1480
+ }, 'error')],
1024
1481
  };
1025
1482
  return [[`${pluginId}\0${reference.platform}\0${reference.scope}`, target]];
1026
1483
  })).values()];
1027
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
+ }
1028
1613
  const projectedInventoryErrors = [...new Map(selectedInventoryErrors.map((error) => [
1029
1614
  `${error.code}\0${error.message}`,
1030
1615
  { code: error.code, message: error.message },
@@ -1032,19 +1617,238 @@ export async function statusCommandV5(options) {
1032
1617
  const errors = [
1033
1618
  ...projectedInventoryErrors,
1034
1619
  ...selectorErrors,
1620
+ ...intentErrors,
1035
1621
  ...legacyOwners.map((reference) => projectTargetError({
1036
1622
  code: 'legacyStateUnsupported',
1037
1623
  message: `legacyStateUnsupported: legacy live ${reference.kind} at ${reference.location}`,
1038
- }, env, options.cwd)),
1624
+ }, env, options.cwd, 'error')),
1039
1625
  ];
1040
- const projectedTargets = targets.map((target) => ({
1626
+ const draftTargets = targets.map((target) => ({
1041
1627
  ...target,
1042
- errors: target.errors.map((error) => projectTargetError(error, env, options.cwd)),
1628
+ errors: target.errors.map((error) => projectTargetError(error, env, options.cwd, target.state)),
1043
1629
  }));
1044
1630
  const selectedByPluginId = new Map(selected.map((entry) => [
1045
1631
  formatPluginId({ sourceId: entry.source.id, pluginName: entry.name }),
1046
1632
  entry,
1047
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'));
1048
1852
  const targetRevisions = projectedTargets.map((target) => {
1049
1853
  const entry = selectedByPluginId.get(target.pluginId);
1050
1854
  return {
@@ -1055,7 +1859,7 @@ export async function statusCommandV5(options) {
1055
1859
  };
1056
1860
  });
1057
1861
  const payload = {
1058
- schemaVersion: 5,
1862
+ schemaVersion: 6,
1059
1863
  catalog: {
1060
1864
  primarySourceId: catalog.primarySourceId,
1061
1865
  configDigest: catalog.configDigest,
@@ -1081,11 +1885,10 @@ export async function statusCommandV5(options) {
1081
1885
  };
1082
1886
  const hasErrors = payload.catalog.sources.some((source) => source.error !== undefined)
1083
1887
  || payload.errors.length > 0
1084
- || payload.targets.some((target) => target.state === 'error'
1085
- && target.errors.some((error) => error.code !== 'awCapabilityUnsupported'));
1888
+ || payload.targets.some((target) => target.errors.some((error) => error.severity === 'blocking'));
1086
1889
  return {
1087
1890
  payload,
1088
- output: options.json ? JSON.stringify(payload) : renderStatusV5(payload, options.verbose === true),
1891
+ output: options.json ? JSON.stringify(payload) : renderStatusV6(payload, options.verbose === true),
1089
1892
  hasErrors,
1090
1893
  targetRevisions,
1091
1894
  pluginSummaries: available.map((entry) => {
@@ -1132,4 +1935,4 @@ export async function statusCommandV5(options) {
1132
1935
  }),
1133
1936
  };
1134
1937
  }
1135
- //# sourceMappingURL=status-v5.js.map
1938
+ //# sourceMappingURL=status-v6.js.map