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

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 (237) hide show
  1. package/dist/authoring/scripts/init-plugin.mjs +4 -33
  2. package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
  3. package/dist/authoring/scripts/lib/plugin-version-check.mjs +1 -1
  4. package/dist/authoring/scripts/plugin-status.mjs +8 -11
  5. package/dist/authoring/scripts/plugin-status.mjs.map +1 -1
  6. package/dist/authoring/scripts/remove-plugin.mjs +1 -0
  7. package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
  8. package/dist/authoring/scripts/validate-plugin.mjs +104 -54
  9. package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
  10. package/dist/scripts/codex-eval-app-server.d.ts +2 -0
  11. package/dist/scripts/codex-eval-app-server.js +107 -1
  12. package/dist/scripts/codex-eval-app-server.js.map +1 -1
  13. package/dist/scripts/eval-plugin-skills.js +5 -2
  14. package/dist/scripts/eval-plugin-skills.js.map +1 -1
  15. package/dist/scripts/plugin-eval-contract.d.ts +5 -1
  16. package/dist/scripts/plugin-eval-contract.js +54 -4
  17. package/dist/scripts/plugin-eval-contract.js.map +1 -1
  18. package/dist/scripts/plugin-staging.d.ts +6 -7
  19. package/dist/scripts/plugin-staging.js +11 -23
  20. package/dist/scripts/plugin-staging.js.map +1 -1
  21. package/dist/scripts/test-plugin-scripts.js +2 -33
  22. package/dist/scripts/test-plugin-scripts.js.map +1 -1
  23. package/dist/src/adapters/helpers.js +2 -2
  24. package/dist/src/adapters/helpers.js.map +1 -1
  25. package/dist/src/authoring/workspace-commands.d.ts +17 -2
  26. package/dist/src/authoring/workspace-commands.js +21 -4
  27. package/dist/src/authoring/workspace-commands.js.map +1 -1
  28. package/dist/src/commands/aw-capabilities.d.ts +78 -0
  29. package/dist/src/commands/aw-capabilities.js +259 -0
  30. package/dist/src/commands/aw-capabilities.js.map +1 -0
  31. package/dist/src/commands/catalog-context.d.ts +52 -0
  32. package/dist/src/commands/catalog-context.js +156 -0
  33. package/dist/src/commands/catalog-context.js.map +1 -0
  34. package/dist/src/commands/catalog-dev-source.d.ts +112 -0
  35. package/dist/src/commands/catalog-dev-source.js +481 -0
  36. package/dist/src/commands/catalog-dev-source.js.map +1 -0
  37. package/dist/src/commands/catalog-generation.d.ts +26 -0
  38. package/dist/src/commands/catalog-generation.js +14 -0
  39. package/dist/src/commands/catalog-generation.js.map +1 -0
  40. package/dist/src/commands/catalog-publication-inspection.d.ts +1 -1
  41. package/dist/src/commands/catalog-publication-inspection.js +4 -5
  42. package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
  43. package/dist/src/commands/catalog-publication-target.d.ts +17 -0
  44. package/dist/src/commands/catalog-publication-target.js +60 -0
  45. package/dist/src/commands/catalog-publication-target.js.map +1 -0
  46. package/dist/src/commands/catalog-publish.d.ts +8 -1
  47. package/dist/src/commands/catalog-publish.js +25 -2
  48. package/dist/src/commands/catalog-publish.js.map +1 -1
  49. package/dist/src/commands/catalog-source.d.ts +23 -1
  50. package/dist/src/commands/catalog-source.js +126 -40
  51. package/dist/src/commands/catalog-source.js.map +1 -1
  52. package/dist/src/commands/catalog-status.d.ts +18 -2
  53. package/dist/src/commands/catalog-status.js +122 -18
  54. package/dist/src/commands/catalog-status.js.map +1 -1
  55. package/dist/src/commands/init.js +1 -1
  56. package/dist/src/commands/init.js.map +1 -1
  57. package/dist/src/commands/offline-cleanup-evidence.d.ts +23 -0
  58. package/dist/src/commands/offline-cleanup-evidence.js +38 -0
  59. package/dist/src/commands/offline-cleanup-evidence.js.map +1 -0
  60. package/dist/src/commands/options.d.ts +1 -0
  61. package/dist/src/commands/options.js +1 -0
  62. package/dist/src/commands/options.js.map +1 -1
  63. package/dist/src/commands/plugin-capabilities.js +1 -1
  64. package/dist/src/commands/plugin-capabilities.js.map +1 -1
  65. package/dist/src/commands/rebuild-command.d.ts +19 -7
  66. package/dist/src/commands/rebuild-command.js +415 -205
  67. package/dist/src/commands/rebuild-command.js.map +1 -1
  68. package/dist/src/commands/rebuild-integration.d.ts +10 -3
  69. package/dist/src/commands/rebuild-integration.js +71 -76
  70. package/dist/src/commands/rebuild-integration.js.map +1 -1
  71. package/dist/src/commands/rebuild-operations.d.ts +0 -8
  72. package/dist/src/commands/rebuild-operations.js +17 -115
  73. package/dist/src/commands/rebuild-operations.js.map +1 -1
  74. package/dist/src/commands/runtime.js +21 -34
  75. package/dist/src/commands/runtime.js.map +1 -1
  76. package/dist/src/commands/{status-v4.d.ts → status-v5.d.ts} +67 -21
  77. package/dist/src/commands/{status-v4.js → status-v5.js} +260 -30
  78. package/dist/src/commands/status-v5.js.map +1 -0
  79. package/dist/src/commands/wizard.d.ts +2 -2
  80. package/dist/src/commands/wizard.js +2 -2
  81. package/dist/src/commands/wizard.js.map +1 -1
  82. package/dist/src/commands/write-commands.js +73 -17
  83. package/dist/src/commands/write-commands.js.map +1 -1
  84. package/dist/src/constants.d.ts +6 -1
  85. package/dist/src/constants.js +6 -1
  86. package/dist/src/constants.js.map +1 -1
  87. package/dist/src/generators/local-plugin.js +57 -3
  88. package/dist/src/generators/local-plugin.js.map +1 -1
  89. package/dist/src/index.d.ts +4 -1
  90. package/dist/src/index.js +562 -85
  91. package/dist/src/index.js.map +1 -1
  92. package/dist/src/output/model.d.ts +1 -34
  93. package/dist/src/output/model.js +1 -144
  94. package/dist/src/output/model.js.map +1 -1
  95. package/dist/src/output/rebuild-progress.js +0 -3
  96. package/dist/src/output/rebuild-progress.js.map +1 -1
  97. package/dist/src/portable/commands.d.ts +4 -0
  98. package/dist/src/portable/commands.js +61 -4
  99. package/dist/src/portable/commands.js.map +1 -1
  100. package/dist/src/portable/materializer.d.ts +3 -0
  101. package/dist/src/portable/materializer.js +61 -10
  102. package/dist/src/portable/materializer.js.map +1 -1
  103. package/dist/src/tui/catalog-generation.d.ts +56 -0
  104. package/dist/src/tui/catalog-generation.js +244 -0
  105. package/dist/src/tui/catalog-generation.js.map +1 -0
  106. package/dist/src/tui/console-app-v4.d.ts +1 -1
  107. package/dist/src/tui/console-app-v4.js +446 -126
  108. package/dist/src/tui/console-app-v4.js.map +1 -1
  109. package/dist/src/tui/controller-runtime.d.ts +8 -2
  110. package/dist/src/tui/controller-runtime.js +606 -92
  111. package/dist/src/tui/controller-runtime.js.map +1 -1
  112. package/dist/src/tui/controller.d.ts +71 -6
  113. package/dist/src/tui/controller.js +377 -83
  114. package/dist/src/tui/controller.js.map +1 -1
  115. package/dist/src/tui/index.d.ts +1 -0
  116. package/dist/src/tui/index.js +1 -0
  117. package/dist/src/tui/index.js.map +1 -1
  118. package/dist/src/tui/input-display.d.ts +8 -0
  119. package/dist/src/tui/input-display.js +36 -0
  120. package/dist/src/tui/input-display.js.map +1 -0
  121. package/dist/src/tui/model.d.ts +27 -7
  122. package/dist/src/tui/model.js +273 -65
  123. package/dist/src/tui/model.js.map +1 -1
  124. package/dist/src/tui/router.d.ts +26 -0
  125. package/dist/src/tui/router.js.map +1 -1
  126. package/dist/src/tui/source-ref-presets.d.ts +3 -0
  127. package/dist/src/tui/source-ref-presets.js +11 -0
  128. package/dist/src/tui/source-ref-presets.js.map +1 -0
  129. package/dist/src/tui/views.js +31 -3
  130. package/dist/src/tui/views.js.map +1 -1
  131. package/dist/src/types.d.ts +90 -6
  132. package/dist/src/types.js.map +1 -1
  133. package/dist/src/utils/agent-version.d.ts +3 -0
  134. package/dist/src/utils/agent-version.js +13 -5
  135. package/dist/src/utils/agent-version.js.map +1 -1
  136. package/dist/src/utils/aw-home-mutation-lock.d.ts +1 -0
  137. package/dist/src/utils/aw-home-mutation-lock.js +32 -4
  138. package/dist/src/utils/aw-home-mutation-lock.js.map +1 -1
  139. package/dist/src/utils/bundle-integrity.d.ts +0 -1
  140. package/dist/src/utils/bundle-integrity.js +0 -25
  141. package/dist/src/utils/bundle-integrity.js.map +1 -1
  142. package/dist/src/utils/bundle-layout.js +8 -6
  143. package/dist/src/utils/bundle-layout.js.map +1 -1
  144. package/dist/src/utils/catalog-digests.js +13 -2
  145. package/dist/src/utils/catalog-digests.js.map +1 -1
  146. package/dist/src/utils/catalog-generation-error.d.ts +12 -0
  147. package/dist/src/utils/catalog-generation-error.js +16 -0
  148. package/dist/src/utils/catalog-generation-error.js.map +1 -0
  149. package/dist/src/utils/catalog-generation-resolver.d.ts +13 -0
  150. package/dist/src/utils/catalog-generation-resolver.js +129 -0
  151. package/dist/src/utils/catalog-generation-resolver.js.map +1 -0
  152. package/dist/src/utils/catalog-generation-service.d.ts +52 -0
  153. package/dist/src/utils/catalog-generation-service.js +620 -0
  154. package/dist/src/utils/catalog-generation-service.js.map +1 -0
  155. package/dist/src/utils/catalog-generation-state.d.ts +13 -0
  156. package/dist/src/utils/catalog-generation-state.js +201 -0
  157. package/dist/src/utils/catalog-generation-state.js.map +1 -0
  158. package/dist/src/utils/catalog-generation-store.d.ts +44 -0
  159. package/dist/src/utils/catalog-generation-store.js +387 -0
  160. package/dist/src/utils/catalog-generation-store.js.map +1 -0
  161. package/dist/src/utils/catalog-manifest-v5.d.ts +5 -0
  162. package/dist/src/utils/{catalog-manifest-v4.js → catalog-manifest-v5.js} +39 -35
  163. package/dist/src/utils/{catalog-manifest-v4.js.map → catalog-manifest-v5.js.map} +1 -1
  164. package/dist/src/utils/catalog-operation-context.d.ts +28 -0
  165. package/dist/src/utils/catalog-operation-context.js +242 -0
  166. package/dist/src/utils/catalog-operation-context.js.map +1 -0
  167. package/dist/src/utils/catalog-public-error.d.ts +7 -3
  168. package/dist/src/utils/catalog-public-error.js +20 -4
  169. package/dist/src/utils/catalog-public-error.js.map +1 -1
  170. package/dist/src/utils/catalog-snapshot.d.ts +5 -3
  171. package/dist/src/utils/catalog-snapshot.js +11 -3
  172. package/dist/src/utils/catalog-snapshot.js.map +1 -1
  173. package/dist/src/utils/catalog-source-cache.d.ts +1 -1
  174. package/dist/src/utils/catalog-source-cache.js +37 -12
  175. package/dist/src/utils/catalog-source-cache.js.map +1 -1
  176. package/dist/src/utils/catalog-source-identity.d.ts +1 -0
  177. package/dist/src/utils/catalog-source-identity.js +21 -2
  178. package/dist/src/utils/catalog-source-identity.js.map +1 -1
  179. package/dist/src/utils/catalog-sources.d.ts +1 -0
  180. package/dist/src/utils/catalog-sources.js +30 -11
  181. package/dist/src/utils/catalog-sources.js.map +1 -1
  182. package/dist/src/utils/codex-config.js +4 -4
  183. package/dist/src/utils/codex-config.js.map +1 -1
  184. package/dist/src/utils/codex-manager.d.ts +33 -0
  185. package/dist/src/utils/codex-manager.js +656 -0
  186. package/dist/src/utils/codex-manager.js.map +1 -0
  187. package/dist/src/utils/codex-skill-staging.d.ts +2 -0
  188. package/dist/src/utils/codex-skill-staging.js.map +1 -1
  189. package/dist/src/utils/dynamic-skill-tree.d.ts +4 -0
  190. package/dist/src/utils/dynamic-skill-tree.js +35 -5
  191. package/dist/src/utils/dynamic-skill-tree.js.map +1 -1
  192. package/dist/src/utils/git-catalog-provider.js +10 -25
  193. package/dist/src/utils/git-catalog-provider.js.map +1 -1
  194. package/dist/src/utils/lifecycle-active-store.d.ts +0 -28
  195. package/dist/src/utils/lifecycle-active-store.js +35 -247
  196. package/dist/src/utils/lifecycle-active-store.js.map +1 -1
  197. package/dist/src/utils/multi-source-catalog.d.ts +3 -0
  198. package/dist/src/utils/multi-source-catalog.js +120 -10
  199. package/dist/src/utils/multi-source-catalog.js.map +1 -1
  200. package/dist/src/utils/native-cli.d.ts +15 -6
  201. package/dist/src/utils/native-cli.js +31 -39
  202. package/dist/src/utils/native-cli.js.map +1 -1
  203. package/dist/src/utils/orphan-marketplace-cleanup.js +0 -3
  204. package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
  205. package/dist/src/utils/ownership.d.ts +10 -1
  206. package/dist/src/utils/ownership.js +52 -24
  207. package/dist/src/utils/ownership.js.map +1 -1
  208. package/dist/src/utils/path-catalog-provider.js +12 -8
  209. package/dist/src/utils/path-catalog-provider.js.map +1 -1
  210. package/dist/src/utils/plugin-config-write.js +18 -35
  211. package/dist/src/utils/plugin-config-write.js.map +1 -1
  212. package/dist/src/utils/plugin-config.d.ts +1 -12
  213. package/dist/src/utils/plugin-config.js +107 -226
  214. package/dist/src/utils/plugin-config.js.map +1 -1
  215. package/dist/src/utils/plugin-scripts.d.ts +1 -1
  216. package/dist/src/utils/plugin-scripts.js +1 -1
  217. package/dist/src/utils/plugin-scripts.js.map +1 -1
  218. package/dist/src/utils/state-paths.js +7 -2
  219. package/dist/src/utils/state-paths.js.map +1 -1
  220. package/dist/src/utils/target-eligibility.d.ts +7 -2
  221. package/dist/src/utils/target-eligibility.js +6 -3
  222. package/dist/src/utils/target-eligibility.js.map +1 -1
  223. package/package.json +4 -3
  224. package/dist/authoring/scripts/check-plugin-versions.d.mts +0 -2
  225. package/dist/authoring/scripts/check-plugin-versions.mjs +0 -5
  226. package/dist/authoring/scripts/check-plugin-versions.mjs.map +0 -1
  227. package/dist/src/commands/status-v4.js.map +0 -1
  228. package/dist/src/commands/status.d.ts +0 -93
  229. package/dist/src/commands/status.js +0 -442
  230. package/dist/src/commands/status.js.map +0 -1
  231. package/dist/src/utils/active-marketplace-runtime-lock.d.ts +0 -12
  232. package/dist/src/utils/active-marketplace-runtime-lock.js +0 -133
  233. package/dist/src/utils/active-marketplace-runtime-lock.js.map +0 -1
  234. package/dist/src/utils/catalog-manifest-v3.d.ts +0 -2
  235. package/dist/src/utils/catalog-manifest-v3.js +0 -3
  236. package/dist/src/utils/catalog-manifest-v3.js.map +0 -1
  237. package/dist/src/utils/catalog-manifest-v4.d.ts +0 -5
package/dist/src/index.js CHANGED
@@ -4,14 +4,15 @@ import path from 'node:path';
4
4
  import { spawn } from 'node:child_process';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { Command, CommanderError, Option } from 'commander';
7
+ import { resolveCatalogWorkspaceRoot } from '@lesliechan721/aw-plugin-core';
7
8
  import { initCommand } from './commands/init.js';
8
9
  import { addCatalogSourceCommand, explicitRefPolicy, listCatalogSources, removeCatalogSourceCommand, setPrimaryCatalogSourceCommand, updateCatalogSourceCommand, } from './commands/catalog-source.js';
10
+ import { activateCatalogSourceCandidateCommand, catalogGenerationStatusCommand, refreshCatalogSourceGenerationCommand, setCatalogSourceRefreshPolicyCommand, } from './commands/catalog-generation.js';
9
11
  import { cleanupWriteCommand as cleanupCommand, installWriteCommand as installCommand, reinstallWriteCommand as reinstallCommand, uninstallWriteCommand as uninstallCommand, upgradeWriteCommand as upgradeCommand, } from './commands/write-commands.js';
10
12
  import { formatInteractiveConsoleUnavailableMessage, runConsoleController, } from './commands/console.js';
11
13
  import { runCommandWizard, toWizardCandidates, WizardExecutionError, } from './commands/wizard.js';
12
14
  import { createCliExecutionContext, emitCommandEvent, } from './commands/runtime.js';
13
- import { loadConsoleItemsResult } from './commands/status.js';
14
- import { statusCommandV4 } from './commands/status-v4.js';
15
+ import { loadConsoleItemsResult, statusCommandV5 } from './commands/status-v5.js';
15
16
  import { normalizeUninstallCommandOptions, normalizeCleanupCommandOptions, resolveConfigReadResolution, resolveConfigProjectLayer, resolveConfigWriteScope, normalizeInstallCommandOptions, normalizeReinstallCommandOptions, normalizeUpgradeCommandOptions, } from './commands/options.js';
16
17
  import { isCommandWarningError, } from './types.js';
17
18
  import { formatWarnings } from './output/reporter.js';
@@ -26,6 +27,8 @@ import { writeCandidateEligibility } from './utils/target-eligibility.js';
26
27
  import { assertCatalogSourceReferencesSupported, inventoryLegacyConfigReferences, } from './utils/catalog-source-references.js';
27
28
  import { parsePluginId, withResolvedCatalogPlugin, withResolvedMultiSourceCatalog, } from './utils/multi-source-catalog.js';
28
29
  import { sanitizeCatalogSourceError } from './utils/catalog-public-error.js';
30
+ import { catalogGenerationErrorCode } from './utils/catalog-generation-error.js';
31
+ import { bootstrapCatalogOperationSources, resolveCatalogOperationContext, } from './utils/catalog-operation-context.js';
29
32
  import { formatConfigCommandValue, parseConfigValue, } from './utils/config-value.js';
30
33
  import { withAwHomeMutationLock, } from './utils/aw-home-mutation-lock.js';
31
34
  import { installPortableSkills, materializePortableSkillsToDirectory, PortableCommandError, renderPortableReview, } from './portable/commands.js';
@@ -35,7 +38,10 @@ import { resolveRepoRoot } from './utils/state-paths.js';
35
38
  import { runCatalogBuildCommand, runCatalogInitCommand, runCatalogValidateCommand, runCatalogVersionCommand, runPluginBuildCommand, runPluginTestCommand, } from './authoring/workspace-commands.js';
36
39
  import { runCatalogPublishCommand } from './commands/catalog-publish.js';
37
40
  import { getCatalogStatus, renderCatalogStatus } from './commands/catalog-status.js';
41
+ import { getCatalogContext } from './commands/catalog-context.js';
42
+ import { activateCatalogDevSource, catalogDevSourceError, createCatalogDevFailureReceipt, deactivateCatalogDevSource, getCatalogDevSourceStatus, } from './commands/catalog-dev-source.js';
38
43
  import { getPluginCapabilitiesResult, parsePluginCapabilitySurface, renderPluginCapabilities, } from './commands/plugin-capabilities.js';
44
+ import { AwCapabilityUnsupportedError, checkCurrentAw, describeCurrentAw, inspectPluginRequirements, IMPLEMENTED_AW_CAPABILITIES, } from './commands/aw-capabilities.js';
39
45
  function createDefaultIo() {
40
46
  return {
41
47
  stdout: (text) => process.stdout.write(text),
@@ -141,6 +147,9 @@ export function buildEquivalentWriteCommandTokens(command, selection, rawOptions
141
147
  selection.platform ?? 'both',
142
148
  '--scope',
143
149
  selection.scope ?? 'user',
150
+ ...(rawOptions.allowManagedCodexInstall === true
151
+ ? ['--allow-managed-codex-install']
152
+ : []),
144
153
  ...(command === 'cleanup' ? [] : optionTokens('--script-timeout', rawOptions.scriptTimeout)),
145
154
  ...(!all && selection.plugins.length > 0 ? ['--', ...selection.plugins] : []),
146
155
  ];
@@ -209,7 +218,6 @@ async function loadWizardCandidates(context, rawOptions) {
209
218
  cwd: context.cwd,
210
219
  scope: rawOptions.scope,
211
220
  platform: rawOptions.platform,
212
- includeCatalogOnly: true,
213
221
  }, context);
214
222
  return toWizardCandidates(loaded.items);
215
223
  }
@@ -389,6 +397,20 @@ async function resolveMultiSourceConfigRead(options) {
389
397
  return { ...stored, result };
390
398
  });
391
399
  }
400
+ export function createManagedCodexAuthorizer(rawOptions, context) {
401
+ if (rawOptions.allowManagedCodexInstall === true)
402
+ return async () => true;
403
+ if (!(context.interactive && context.isTty && !context.isCi && rawOptions.json !== true)
404
+ || !context.prompt.confirm)
405
+ return undefined;
406
+ return async () => {
407
+ const response = await context.prompt.confirm({
408
+ message: '系统中没有可用的 Codex CLI。是否获取本次操作所需的 AW-managed Codex runtime?',
409
+ defaultValue: false,
410
+ });
411
+ return !response.cancelled && response.value === true;
412
+ };
413
+ }
392
414
  async function executeWriteCommand(command, pluginNames, rawOptions, context) {
393
415
  const raw = { cwd: context.cwd, ...rawOptions };
394
416
  const commandOptions = command === 'install'
@@ -404,12 +426,17 @@ async function executeWriteCommand(command, pluginNames, rawOptions, context) {
404
426
  type: 'options:normalized',
405
427
  data: { plugins: pluginNames, options: commandOptions },
406
428
  });
429
+ const managedCodexAuthorizer = createManagedCodexAuthorizer(rawOptions, context);
430
+ const runtime = {
431
+ ...context,
432
+ ...(managedCodexAuthorizer ? { managedCodexAuthorizer } : {}),
433
+ };
407
434
  switch (command) {
408
- case 'install': return installCommand(pluginNames, commandOptions, context);
409
- case 'upgrade': return upgradeCommand(pluginNames, commandOptions, context);
410
- case 'uninstall': return uninstallCommand(pluginNames, commandOptions, context);
411
- case 'cleanup': return cleanupCommand(pluginNames, commandOptions, context);
412
- case 'reinstall': return reinstallCommand(pluginNames, commandOptions, context);
435
+ case 'install': return installCommand(pluginNames, commandOptions, runtime);
436
+ case 'upgrade': return upgradeCommand(pluginNames, commandOptions, runtime);
437
+ case 'uninstall': return uninstallCommand(pluginNames, commandOptions, runtime);
438
+ case 'cleanup': return cleanupCommand(pluginNames, commandOptions, runtime);
439
+ case 'reinstall': return reinstallCommand(pluginNames, commandOptions, runtime);
413
440
  }
414
441
  }
415
442
  async function runWriteCommandAction(command, pluginNames, rawOptions, context) {
@@ -443,7 +470,6 @@ async function runWriteCommandAction(command, pluginNames, rawOptions, context)
443
470
  cwd: context.cwd,
444
471
  scope: rawOptions.scope,
445
472
  platform: rawOptions.platform,
446
- includeCatalogOnly: true,
447
473
  }, context);
448
474
  if (loaded.catalogUnavailable) {
449
475
  throw new Error('插件目录不可用。请运行 `aw init` 或 `aw init --force`,或使用完整参数重试。');
@@ -676,9 +702,32 @@ export function buildProgram(options = {}) {
676
702
  const plugin = program
677
703
  .command('plugin')
678
704
  .description('Create and validate AW plugin source');
705
+ const self = program
706
+ .command('self')
707
+ .description('Describe and check this AW executable');
708
+ self
709
+ .command('describe')
710
+ .description('Describe implemented AW capabilities')
711
+ .requiredOption('--json', 'emit one machine-readable JSON object')
712
+ .action(() => {
713
+ writeJsonReceipt(io.stdout, describeCurrentAw(resolveCliVersion()));
714
+ });
715
+ self
716
+ .command('check')
717
+ .description('Check nearby plugin requirements against this AW executable')
718
+ .option('--from <path>', 'start discovery from this file or directory')
719
+ .requiredOption('--json', 'emit one machine-readable JSON object')
720
+ .action(async (rawOptions) => {
721
+ const result = await checkCurrentAw({
722
+ awVersion: resolveCliVersion(),
723
+ from: path.resolve(cwd, rawOptions.from ?? '.'),
724
+ });
725
+ writeJsonReceipt(io.stdout, result);
726
+ commandExitState.exitCode = result.ok ? 0 : 1;
727
+ });
679
728
  plugin
680
729
  .command('capabilities')
681
- .description('Show the current plugin authoring capability contract')
730
+ .description('Show the current plugin manifest authoring surface')
682
731
  .option('--surface <surface>', 'manifest | build-config | extensions | slash-commands | mcp-apps | config | lifecycle | artifacts')
683
732
  .option('--json', 'emit one machine-readable JSON object', false)
684
733
  .action((rawOptions) => {
@@ -701,6 +750,38 @@ export function buildProgram(options = {}) {
701
750
  commandExitState.exitCode = 1;
702
751
  }
703
752
  });
753
+ plugin
754
+ .command('requirements')
755
+ .description('Inspect or update effective AW capabilities required by a plugin')
756
+ .argument('<plugin-directory>', 'plugin source directory')
757
+ .option('--workspace-root <root>', 'Catalog Workspace root (default: nearest ancestor from plugin directory)')
758
+ .option('--add <capability>', 'add one declared AW capability')
759
+ .option('--remove <capability>', 'remove one declared AW capability')
760
+ .requiredOption('--json', 'emit one machine-readable JSON object')
761
+ .action(async (pluginDirectory, rawOptions) => {
762
+ try {
763
+ const result = await inspectPluginRequirements({
764
+ pluginDirectory,
765
+ ...(rawOptions.workspaceRoot ? { workspaceRoot: rawOptions.workspaceRoot } : {}),
766
+ ...(rawOptions.add ? { add: rawOptions.add } : {}),
767
+ ...(rawOptions.remove ? { remove: rawOptions.remove } : {}),
768
+ cwd,
769
+ });
770
+ writeJsonReceipt(io.stdout, result);
771
+ if (result.observations.some((observation) => observation.blocking)) {
772
+ commandExitState.exitCode = 1;
773
+ }
774
+ }
775
+ catch (error) {
776
+ writeJsonReceipt(io.stdout, {
777
+ schemaVersion: 1,
778
+ command: 'plugin:requirements',
779
+ ok: false,
780
+ error: error instanceof Error ? error.message : String(error),
781
+ });
782
+ commandExitState.exitCode = 1;
783
+ }
784
+ });
704
785
  const skill = program
705
786
  .command('skill')
706
787
  .description('Install, materialize, or validate Agent Skills');
@@ -868,9 +949,11 @@ export function buildProgram(options = {}) {
868
949
  .action(async (selector, rawOptions) => {
869
950
  const context = createActionContext('skill:install', {});
870
951
  const writeFailure = (error) => {
871
- const code = error instanceof PortableCommandError || error instanceof SkillsCliError
872
- ? error.code
873
- : 'portableInstallFailed';
952
+ const capabilityError = error instanceof AwCapabilityUnsupportedError ? error : undefined;
953
+ const code = capabilityError?.code
954
+ ?? (error instanceof PortableCommandError || error instanceof SkillsCliError
955
+ ? error.code
956
+ : 'portableInstallFailed');
874
957
  writeJsonReceipt(io.stdout, {
875
958
  receiptSchemaVersion: 4,
876
959
  command: 'skill:install',
@@ -888,7 +971,15 @@ export function buildProgram(options = {}) {
888
971
  materializationDigest: null,
889
972
  verification: { records: [], missing: [] },
890
973
  warnings: [],
891
- failures: [{ code, message: `${code}: portable Skill 安装未执行。` }],
974
+ failures: [{
975
+ code,
976
+ message: capabilityError?.message ?? `${code}: portable Skill 安装未执行。`,
977
+ ...(capabilityError ? {
978
+ plugin: capabilityError.plugin,
979
+ missingCapabilities: capabilityError.missingCapabilities,
980
+ availableCapabilities: capabilityError.availableCapabilities,
981
+ } : {}),
982
+ }],
892
983
  });
893
984
  };
894
985
  if (rawOptions.json && !rawOptions.yes) {
@@ -979,9 +1070,11 @@ export function buildProgram(options = {}) {
979
1070
  catch (error) {
980
1071
  if (!rawOptions.json)
981
1072
  throw error;
982
- const code = error instanceof PortableCommandError || error instanceof SkillsCliError
983
- ? error.code
984
- : 'portableMaterializeFailed';
1073
+ const capabilityError = error instanceof AwCapabilityUnsupportedError ? error : undefined;
1074
+ const code = capabilityError?.code
1075
+ ?? (error instanceof PortableCommandError || error instanceof SkillsCliError
1076
+ ? error.code
1077
+ : 'portableMaterializeFailed');
985
1078
  writeJsonReceipt(io.stdout, {
986
1079
  receiptSchemaVersion: 4,
987
1080
  command: 'skill:materialize',
@@ -995,7 +1088,15 @@ export function buildProgram(options = {}) {
995
1088
  configDigest: null,
996
1089
  materializationDigest: null,
997
1090
  outputDigest: null,
998
- errors: [{ code, message: `${code}: portable Skill 导出未执行。` }],
1091
+ errors: [{
1092
+ code,
1093
+ message: capabilityError?.message ?? `${code}: portable Skill 导出未执行。`,
1094
+ ...(capabilityError ? {
1095
+ plugin: capabilityError.plugin,
1096
+ missingCapabilities: capabilityError.missingCapabilities,
1097
+ availableCapabilities: capabilityError.availableCapabilities,
1098
+ } : {}),
1099
+ }],
999
1100
  });
1000
1101
  commandExitState.exitCode = 1;
1001
1102
  }
@@ -1019,9 +1120,7 @@ export function buildProgram(options = {}) {
1019
1120
  .option('--skill-short-description <text>', 'initial Skill UI summary (25-64 characters)')
1020
1121
  .option('--skill-invocation <mode>', 'model | manual | claude-model-only (default: model)')
1021
1122
  .option('--version <semver>', 'initial stable plugin version (default: 0.1.0)')
1022
- .option('--min-version <semver>', 'compatibility.aw.minVersion')
1023
- .option('--catalog-min-version <semver>', 'target catalog compatibility minimum')
1024
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1123
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)')
1025
1124
  .option('--no-skills', 'create the plugin without a skills directory')
1026
1125
  .option('--with-mcp', 'add a minimal .mcp.json', false)
1027
1126
  .option('--with-apps', 'add a minimal .app.json', false)
@@ -1042,35 +1141,39 @@ export function buildProgram(options = {}) {
1042
1141
  .option('--skill-description <text>', 'Skill goal and discovery description (required)')
1043
1142
  .option('--skill-short-description <text>', 'Skill UI summary (25-64 characters)')
1044
1143
  .option('--skill-invocation <mode>', 'model | manual | claude-model-only (default: model)')
1045
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)');
1144
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)');
1046
1145
  plugin
1047
1146
  .command('remove')
1048
1147
  .description('Remove one committed and unchanged canonical plugin source tree')
1049
1148
  .argument('<plugin-name>', 'existing lowercase hyphen-case plugin name')
1050
- .requiredOption('--workspace-root <path>', 'Catalog Workspace root')
1149
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)')
1051
1150
  .option('--yes', 'confirm plugin source deletion', false)
1052
1151
  .option('--json', 'emit one schema 1 JSON object', false);
1053
1152
  plugin
1054
1153
  .command('validate')
1055
1154
  .description('Validate one source plugin directory')
1056
1155
  .argument('<plugin-directory>', 'source plugin directory')
1057
- .option('--catalog-min-version <semver>', 'validate compatibility against a target catalog')
1058
1156
  .option('--strict-agent-skills', 'allow only Agent Skills portable core frontmatter', false)
1059
1157
  .option('--claude-skill-profile <profile>', 'minimum | current (default: minimum)')
1060
1158
  .option('--version-base <git-ref>', 'production bundle comparison base (default: HEAD)')
1061
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1159
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from plugin directory)')
1062
1160
  .option('--json', 'emit one machine-readable JSON result', false);
1063
1161
  plugin
1064
1162
  .command('test')
1065
1163
  .description('Run deterministic Node tests declared by one source plugin')
1066
1164
  .argument('<plugin-directory>', 'source plugin directory')
1067
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1165
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from plugin directory)')
1068
1166
  .option('--json', 'emit one machine-readable JSON result', false)
1069
1167
  .action(async (pluginDirectory, rawOptions) => {
1070
1168
  try {
1169
+ const workspace = await resolveCatalogWorkspaceRoot({
1170
+ cwd: path.resolve(cwd, pluginDirectory),
1171
+ ...(rawOptions.workspaceRoot === undefined ? {} : { explicitRoot: path.resolve(cwd, rawOptions.workspaceRoot) }),
1172
+ mode: 'existing',
1173
+ });
1071
1174
  commandExitState.exitCode = await runPluginTestCommand({
1072
- workspaceRoot: path.resolve(cwd, rawOptions.workspaceRoot ?? '.'),
1073
- pluginDirectory,
1175
+ ...workspace,
1176
+ pluginDirectory: path.resolve(cwd, pluginDirectory),
1074
1177
  json: rawOptions.json,
1075
1178
  io,
1076
1179
  });
@@ -1087,15 +1190,20 @@ export function buildProgram(options = {}) {
1087
1190
  .command('build')
1088
1191
  .description('Build and inspect one source plugin bundle')
1089
1192
  .argument('<plugin-directory>', 'source plugin directory')
1090
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1193
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from plugin directory)')
1091
1194
  .option('--out <path>', 'output path inside the Catalog Workspace')
1092
1195
  .option('--force', 'replace an existing generated output', false)
1093
1196
  .option('--json', 'emit one machine-readable JSON result', false)
1094
1197
  .action(async (pluginDirectory, rawOptions) => {
1095
1198
  try {
1199
+ const workspace = await resolveCatalogWorkspaceRoot({
1200
+ cwd: path.resolve(cwd, pluginDirectory),
1201
+ ...(rawOptions.workspaceRoot === undefined ? {} : { explicitRoot: path.resolve(cwd, rawOptions.workspaceRoot) }),
1202
+ mode: 'existing',
1203
+ });
1096
1204
  await runPluginBuildCommand({
1097
- workspaceRoot: path.resolve(cwd, rawOptions.workspaceRoot ?? '.'),
1098
- pluginDirectory,
1205
+ ...workspace,
1206
+ pluginDirectory: path.resolve(cwd, pluginDirectory),
1099
1207
  out: rawOptions.out,
1100
1208
  force: rawOptions.force,
1101
1209
  json: rawOptions.json,
@@ -1117,15 +1225,7 @@ export function buildProgram(options = {}) {
1117
1225
  .option('--all', 'check every current Catalog Workspace plugin', false)
1118
1226
  .option('--base <git-ref>', 'explicit Git comparison base')
1119
1227
  .option('--json', 'emit one schema v3 JSON document', false)
1120
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)');
1121
- plugin
1122
- .command('check-versions')
1123
- .description('Deprecated alias for plugin status')
1124
- .argument('[plugin-name]', 'one explicit plugin name')
1125
- .option('--all', 'check every plugin changed relative to the Git base', false)
1126
- .option('--base <git-ref>', 'explicit Git comparison base')
1127
- .option('--json', 'emit one schema v3 JSON document', false)
1128
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)');
1228
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)');
1129
1229
  skill
1130
1230
  .command('validate')
1131
1231
  .description('Validate one Agent Skill directory')
@@ -1139,7 +1239,7 @@ export function buildProgram(options = {}) {
1139
1239
  catalog
1140
1240
  .command('init')
1141
1241
  .description('Initialize a local AW Catalog Workspace')
1142
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1242
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor, then Git worktree root, then current directory)')
1143
1243
  .option('--owner-name <name>', 'catalog owner name')
1144
1244
  .option('--owner-url <url>', 'catalog owner URL')
1145
1245
  .option('--display-name <name>', 'catalog display name')
@@ -1148,9 +1248,14 @@ export function buildProgram(options = {}) {
1148
1248
  .option('--json', 'emit one machine-readable JSON result', false)
1149
1249
  .action(async (rawOptions) => {
1150
1250
  try {
1251
+ const workspace = await resolveCatalogWorkspaceRoot({
1252
+ cwd,
1253
+ ...(rawOptions.workspaceRoot === undefined ? {} : { explicitRoot: rawOptions.workspaceRoot }),
1254
+ mode: 'initialize',
1255
+ });
1151
1256
  await runCatalogInitCommand({
1152
1257
  ...rawOptions,
1153
- workspaceRoot: path.resolve(cwd, rawOptions.workspaceRoot ?? '.'),
1258
+ ...workspace,
1154
1259
  io,
1155
1260
  });
1156
1261
  }
@@ -1162,17 +1267,43 @@ export function buildProgram(options = {}) {
1162
1267
  commandExitState.exitCode = 1;
1163
1268
  }
1164
1269
  });
1270
+ catalog
1271
+ .command('context')
1272
+ .description('Inspect resolved Catalog Workspace and publication context without network access')
1273
+ .option('--workspace-root <path>', 'explicit Catalog Workspace root')
1274
+ .option('--remote <name>', 'Git remote (default: origin, otherwise sole remote; explicit if ambiguous)')
1275
+ .option('--branch <name>', 'explicit Catalog publication branch')
1276
+ .requiredOption('--json', 'emit one schema 1 JSON object')
1277
+ .action(async (rawOptions) => {
1278
+ const receipt = await getCatalogContext({
1279
+ cwd,
1280
+ workspaceRoot: rawOptions.workspaceRoot,
1281
+ remote: rawOptions.remote,
1282
+ branch: rawOptions.branch,
1283
+ env,
1284
+ awVersion: resolveCliVersion(),
1285
+ capabilities: IMPLEMENTED_AW_CAPABILITIES,
1286
+ });
1287
+ writeJsonReceipt(io.stdout, receipt);
1288
+ if (receipt.issues.some((issue) => issue.blocking))
1289
+ commandExitState.exitCode = 1;
1290
+ });
1165
1291
  catalog
1166
1292
  .command('version')
1167
1293
  .description('Read or set the Catalog version')
1168
1294
  .argument('[version]', 'stable or x.y.z-beta.N catalog version')
1169
1295
  .option('--bump <level>', 'bump the stable SemVer base: patch, minor, or major')
1170
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1296
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)')
1171
1297
  .option('--json', 'emit one machine-readable JSON result', false)
1172
1298
  .action(async (version, rawOptions) => {
1173
1299
  try {
1300
+ const workspace = await resolveCatalogWorkspaceRoot({
1301
+ cwd,
1302
+ ...(rawOptions.workspaceRoot === undefined ? {} : { explicitRoot: rawOptions.workspaceRoot }),
1303
+ mode: 'existing',
1304
+ });
1174
1305
  await runCatalogVersionCommand({
1175
- workspaceRoot: path.resolve(cwd, rawOptions.workspaceRoot ?? '.'),
1306
+ ...workspace,
1176
1307
  version,
1177
1308
  bump: rawOptions.bump,
1178
1309
  json: rawOptions.json,
@@ -1190,14 +1321,19 @@ export function buildProgram(options = {}) {
1190
1321
  catalog
1191
1322
  .command('build')
1192
1323
  .description('Build a deterministic development Catalog snapshot')
1193
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1324
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)')
1194
1325
  .option('--out <path>', 'output path inside the Catalog Workspace')
1195
1326
  .option('--force', 'replace an existing generated output', false)
1196
1327
  .option('--json', 'emit one machine-readable JSON result', false)
1197
1328
  .action(async (rawOptions) => {
1198
1329
  try {
1330
+ const workspace = await resolveCatalogWorkspaceRoot({
1331
+ cwd,
1332
+ ...(rawOptions.workspaceRoot === undefined ? {} : { explicitRoot: rawOptions.workspaceRoot }),
1333
+ mode: 'existing',
1334
+ });
1199
1335
  await runCatalogBuildCommand({
1200
- workspaceRoot: path.resolve(cwd, rawOptions.workspaceRoot ?? '.'),
1336
+ ...workspace,
1201
1337
  out: rawOptions.out,
1202
1338
  force: rawOptions.force,
1203
1339
  json: rawOptions.json,
@@ -1214,7 +1350,7 @@ export function buildProgram(options = {}) {
1214
1350
  });
1215
1351
  catalog
1216
1352
  .command('validate')
1217
- .description('Validate a schema 4 Catalog snapshot')
1353
+ .description('Validate a schema 5 Catalog snapshot')
1218
1354
  .argument('<snapshot-directory>', 'Catalog snapshot directory')
1219
1355
  .option('--json', 'emit one machine-readable JSON result', false)
1220
1356
  .action(async (snapshotDirectory, rawOptions) => {
@@ -1236,14 +1372,15 @@ export function buildProgram(options = {}) {
1236
1372
  catalog
1237
1373
  .command('status')
1238
1374
  .description('Inspect a Catalog Workspace; --preflight executes plugin validation and build code')
1239
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1240
- .option('--remote <name>', 'configured Git remote name for preflight (default: origin)')
1375
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)')
1376
+ .option('--remote <name>', 'Git remote for preflight (default: origin, otherwise sole remote; explicit if ambiguous)')
1241
1377
  .option('--branch <name>', 'dedicated Catalog branch for preflight (default: catalog)')
1242
1378
  .option('--preflight', 'run publication validation and temporary plugin builds (executes plugin code)', false)
1243
1379
  .option('--json', 'emit one machine-readable JSON status object', false)
1244
1380
  .action(async (rawOptions) => {
1245
1381
  const receipt = await getCatalogStatus({
1246
- workspaceRoot: path.resolve(cwd, rawOptions.workspaceRoot ?? '.'),
1382
+ cwd,
1383
+ workspaceRoot: rawOptions.workspaceRoot,
1247
1384
  remote: rawOptions.remote,
1248
1385
  branch: rawOptions.branch,
1249
1386
  preflight: rawOptions.preflight,
@@ -1258,8 +1395,8 @@ export function buildProgram(options = {}) {
1258
1395
  catalog
1259
1396
  .command('publish')
1260
1397
  .description('Publish a versioned Catalog snapshot to a configured Git remote')
1261
- .option('--workspace-root <path>', 'Catalog Workspace root (default: current directory)')
1262
- .option('--remote <name>', 'configured Git remote name (default: origin)')
1398
+ .option('--workspace-root <path>', 'Catalog Workspace root (default: nearest ancestor from current directory)')
1399
+ .option('--remote <name>', 'Git remote (default: origin, otherwise sole remote; explicit if ambiguous)')
1263
1400
  .option('--branch <name>', 'dedicated Catalog branch (default: catalog)')
1264
1401
  .option('--expected-descriptor-digest <digest>', 'required exact descriptor returned by publication preflight')
1265
1402
  .option('-y, --yes', 'confirm publication without a prompt', false)
@@ -1268,7 +1405,8 @@ export function buildProgram(options = {}) {
1268
1405
  try {
1269
1406
  const context = createActionContext('catalog:publish', {});
1270
1407
  const result = await runCatalogPublishCommand({
1271
- workspaceRoot: path.resolve(cwd, rawOptions.workspaceRoot ?? '.'),
1408
+ cwd,
1409
+ workspaceRoot: rawOptions.workspaceRoot,
1272
1410
  remote: rawOptions.remote,
1273
1411
  branch: rawOptions.branch,
1274
1412
  expectedDescriptorDigest: rawOptions.expectedDescriptorDigest,
@@ -1308,6 +1446,75 @@ export function buildProgram(options = {}) {
1308
1446
  commandExitState.exitCode = 1;
1309
1447
  }
1310
1448
  });
1449
+ const catalogDev = catalog
1450
+ .command('dev')
1451
+ .description('Manage the current Catalog Workspace development source');
1452
+ catalogDev
1453
+ .command('activate')
1454
+ .option('--workspace-root <path>', 'explicit Catalog Workspace root')
1455
+ .option('--source-id <id>', 'explicit managed source ID')
1456
+ .option('--primary', 'make the development source primary', false)
1457
+ .option('--force-build', 'rebuild a current snapshot', false)
1458
+ .requiredOption('--json', 'emit one schema 1 JSON receipt')
1459
+ .action(async (rawOptions) => {
1460
+ try {
1461
+ const receipt = await activateCatalogDevSource({
1462
+ cwd,
1463
+ workspaceRoot: rawOptions.workspaceRoot,
1464
+ sourceId: rawOptions.sourceId,
1465
+ primary: rawOptions.primary,
1466
+ forceBuild: rawOptions.forceBuild,
1467
+ cliVersion: resolveCliVersion(),
1468
+ env,
1469
+ });
1470
+ writeJsonReceipt(io.stdout, receipt);
1471
+ commandExitState.exitCode = receipt.ok ? 0 : 1;
1472
+ }
1473
+ catch (error) {
1474
+ const failure = catalogDevSourceError(error);
1475
+ writeJsonReceipt(io.stdout, createCatalogDevFailureReceipt({
1476
+ command: 'activate', cwd, workspaceRoot: rawOptions.workspaceRoot,
1477
+ sourceId: rawOptions.sourceId, ...failure,
1478
+ }));
1479
+ commandExitState.exitCode = 1;
1480
+ }
1481
+ });
1482
+ catalogDev
1483
+ .command('status')
1484
+ .option('--workspace-root <path>', 'explicit Catalog Workspace root')
1485
+ .requiredOption('--json', 'emit one schema 1 JSON receipt')
1486
+ .action(async (rawOptions) => {
1487
+ const receipt = await getCatalogDevSourceStatus({
1488
+ cwd,
1489
+ workspaceRoot: rawOptions.workspaceRoot,
1490
+ cliVersion: resolveCliVersion(),
1491
+ env,
1492
+ });
1493
+ writeJsonReceipt(io.stdout, receipt);
1494
+ commandExitState.exitCode = receipt.ok ? 0 : 1;
1495
+ });
1496
+ catalogDev
1497
+ .command('deactivate')
1498
+ .option('--workspace-root <path>', 'explicit Catalog Workspace root')
1499
+ .requiredOption('--json', 'emit one schema 1 JSON receipt')
1500
+ .action(async (rawOptions) => {
1501
+ try {
1502
+ const receipt = await deactivateCatalogDevSource({
1503
+ cwd,
1504
+ workspaceRoot: rawOptions.workspaceRoot,
1505
+ env,
1506
+ });
1507
+ writeJsonReceipt(io.stdout, receipt);
1508
+ commandExitState.exitCode = receipt.ok ? 0 : 1;
1509
+ }
1510
+ catch (error) {
1511
+ const failure = catalogDevSourceError(error);
1512
+ writeJsonReceipt(io.stdout, createCatalogDevFailureReceipt({
1513
+ command: 'deactivate', cwd, workspaceRoot: rawOptions.workspaceRoot, ...failure,
1514
+ }));
1515
+ commandExitState.exitCode = 1;
1516
+ }
1517
+ });
1311
1518
  const catalogSource = catalog
1312
1519
  .command('source')
1313
1520
  .description('Manage catalog sources');
@@ -1328,17 +1535,38 @@ export function buildProgram(options = {}) {
1328
1535
  writeLine(io.stderr, message);
1329
1536
  commandExitState.exitCode = 1;
1330
1537
  };
1538
+ const writeCatalogGenerationFailure = (command, sourceId, json, error) => {
1539
+ const failure = sanitizeCatalogSourceError(error, env);
1540
+ const message = redactString(failure.message);
1541
+ if (json) {
1542
+ writeJsonReceipt(io.stdout, {
1543
+ catalogGenerationSchemaVersion: 1,
1544
+ command,
1545
+ ok: false,
1546
+ ...(sourceId ? { sourceId } : {}),
1547
+ errors: [{ code: catalogGenerationErrorCode(error), message }],
1548
+ });
1549
+ }
1550
+ writeLine(io.stderr, message);
1551
+ commandExitState.exitCode = 1;
1552
+ };
1331
1553
  const writeConfigMutationFailure = (command, plugin, json, error) => {
1332
1554
  const message = error instanceof Error ? error.message : String(error);
1333
- const code = message.includes('legacyStateUnsupported')
1334
- ? 'legacyStateUnsupported'
1335
- : message.includes('sourceChanged')
1336
- ? 'sourceChanged'
1337
- : message.includes('sourceMissing')
1338
- ? 'sourceMissing'
1339
- : message.startsWith('Cannot resolve required catalog sources:')
1340
- ? 'catalogSourceUnavailable'
1341
- : message.split(':', 1)[0] || 'configMutationFailed';
1555
+ const generationCode = catalogGenerationErrorCode(error);
1556
+ const code = generationCode === 'catalogGenerationUnavailable'
1557
+ || generationCode === 'catalogGenerationSourceMissing'
1558
+ ? 'catalogSourceUnavailable'
1559
+ : generationCode !== 'catalogGenerationFailed'
1560
+ ? generationCode
1561
+ : message.includes('legacyStateUnsupported')
1562
+ ? 'legacyStateUnsupported'
1563
+ : message.includes('sourceChanged')
1564
+ ? 'sourceChanged'
1565
+ : message.includes('sourceMissing')
1566
+ ? 'sourceMissing'
1567
+ : message.startsWith('Cannot resolve required catalog sources:')
1568
+ ? 'catalogSourceUnavailable'
1569
+ : message.split(':', 1)[0] || 'configMutationFailed';
1342
1570
  if (json && !message.includes('Usage:')) {
1343
1571
  writeJsonReceipt(io.stdout, {
1344
1572
  receiptSchemaVersion: 4,
@@ -1352,16 +1580,33 @@ export function buildProgram(options = {}) {
1352
1580
  writeLine(io.stderr, message);
1353
1581
  commandExitState.exitCode = 1;
1354
1582
  };
1355
- const withResolvedConfigMutationPlugin = (context, selector, consume) => withAwHomeMutationLock({
1356
- env: context.env,
1357
- action: (awHomeMutationToken) => withResolvedCatalogPlugin({
1358
- selector,
1583
+ const withResolvedConfigMutationPlugin = (context, selector, consume) => (async () => {
1584
+ const parsed = parsePluginId(selector);
1585
+ await bootstrapCatalogOperationSources({
1359
1586
  cliVersion: resolveCliVersion(),
1360
- freshnessPolicy: 'requireRemote',
1587
+ ...(parsed.sourceId ? { sourceIds: [parsed.sourceId] } : {}),
1361
1588
  env: context.env,
1362
- consume: (resolution) => consume(resolution, awHomeMutationToken),
1363
- }),
1364
- });
1589
+ });
1590
+ return withAwHomeMutationLock({
1591
+ env: context.env,
1592
+ action: async (awHomeMutationToken) => {
1593
+ const catalogOperationContext = await resolveCatalogOperationContext({
1594
+ cliVersion: resolveCliVersion(),
1595
+ ...(parsed.sourceId ? { sourceIds: [parsed.sourceId] } : {}),
1596
+ env: context.env,
1597
+ bootstrapMissingActive: false,
1598
+ });
1599
+ return withResolvedCatalogPlugin({
1600
+ selector,
1601
+ cliVersion: resolveCliVersion(),
1602
+ freshnessPolicy: 'cacheFirst',
1603
+ operationContext: catalogOperationContext,
1604
+ env: context.env,
1605
+ consume: (resolution) => consume(resolution, awHomeMutationToken, catalogOperationContext),
1606
+ });
1607
+ },
1608
+ });
1609
+ })();
1365
1610
  catalogSource
1366
1611
  .command('list')
1367
1612
  .option('-j, --json', 'print catalog sources as JSON', false)
@@ -1376,6 +1621,109 @@ export function buildProgram(options = {}) {
1376
1621
  writeLine(io.stdout, `${source.primary ? '*' : '-'} ${source.id} ${source.type} ${source.sourceIdentity}`);
1377
1622
  }
1378
1623
  });
1624
+ catalogSource
1625
+ .command('refresh')
1626
+ .argument('<id>')
1627
+ .option('-j, --json', 'print the generation refresh result as JSON', false)
1628
+ .action(async (id, rawOptions) => {
1629
+ try {
1630
+ const result = await refreshCatalogSourceGenerationCommand({
1631
+ sourceId: id,
1632
+ cliVersion: resolveCliVersion(),
1633
+ env,
1634
+ });
1635
+ if (rawOptions.json) {
1636
+ writeJsonReceipt(io.stdout, {
1637
+ ...result,
1638
+ command: 'catalog:source:refresh',
1639
+ ok: true,
1640
+ });
1641
+ }
1642
+ else {
1643
+ writeLine(io.stdout, `Catalog source ${id}: ${result.outcome}.`);
1644
+ }
1645
+ }
1646
+ catch (error) {
1647
+ writeCatalogGenerationFailure('catalog:source:refresh', id, rawOptions.json === true, error);
1648
+ }
1649
+ });
1650
+ catalogSource
1651
+ .command('activate-candidate')
1652
+ .argument('<id>')
1653
+ .option('-j, --json', 'print the generation activation result as JSON', false)
1654
+ .action(async (id, rawOptions) => {
1655
+ try {
1656
+ const result = await activateCatalogSourceCandidateCommand({ sourceId: id, env });
1657
+ if (rawOptions.json) {
1658
+ writeJsonReceipt(io.stdout, {
1659
+ ...result,
1660
+ command: 'catalog:source:activate-candidate',
1661
+ ok: true,
1662
+ });
1663
+ }
1664
+ else {
1665
+ writeLine(io.stdout, `Catalog source ${id} Candidate activated.`);
1666
+ }
1667
+ }
1668
+ catch (error) {
1669
+ writeCatalogGenerationFailure('catalog:source:activate-candidate', id, rawOptions.json === true, error);
1670
+ }
1671
+ });
1672
+ catalogSource
1673
+ .command('generation-status')
1674
+ .argument('[id]')
1675
+ .option('-j, --json', 'print Catalog generation status as JSON', false)
1676
+ .action(async (id, rawOptions) => {
1677
+ try {
1678
+ const result = await catalogGenerationStatusCommand({ sourceId: id, env });
1679
+ if (rawOptions.json) {
1680
+ writeJsonReceipt(io.stdout, result);
1681
+ }
1682
+ else {
1683
+ for (const source of result.sources) {
1684
+ const active = source.active ? `Active ${source.active.catalogVersion}` : 'no Active';
1685
+ const candidate = source.candidate
1686
+ ? `, Candidate ${source.candidate.catalogVersion}`
1687
+ : '';
1688
+ writeLine(io.stdout, `${source.sourceId}: ${active}${candidate} (${source.refreshPolicy})`);
1689
+ }
1690
+ }
1691
+ }
1692
+ catch (error) {
1693
+ writeCatalogGenerationFailure('catalog:source:generation-status', id, rawOptions.json === true, error);
1694
+ }
1695
+ });
1696
+ catalogSource
1697
+ .command('refresh-policy')
1698
+ .argument('<id>')
1699
+ .argument('<policy>', 'startup or manual')
1700
+ .option('-j, --json', 'print Catalog refresh policy result as JSON', false)
1701
+ .action(async (id, policy, rawOptions) => {
1702
+ try {
1703
+ if (policy !== 'startup' && policy !== 'manual') {
1704
+ throw new Error('Catalog refresh policy must be startup or manual.');
1705
+ }
1706
+ const result = await setCatalogSourceRefreshPolicyCommand({
1707
+ sourceId: id,
1708
+ refreshPolicy: policy,
1709
+ env,
1710
+ });
1711
+ if (rawOptions.json) {
1712
+ writeJsonReceipt(io.stdout, {
1713
+ catalogGenerationSchemaVersion: 1,
1714
+ command: 'catalog:source:refresh-policy',
1715
+ ok: true,
1716
+ ...result,
1717
+ });
1718
+ }
1719
+ else {
1720
+ writeLine(io.stdout, `Catalog source ${id} refresh policy: ${result.refreshPolicy}.`);
1721
+ }
1722
+ }
1723
+ catch (error) {
1724
+ writeCatalogGenerationFailure('catalog:source:refresh-policy', id, rawOptions.json === true, error);
1725
+ }
1726
+ });
1379
1727
  catalogSource
1380
1728
  .command('add')
1381
1729
  .argument('<id>')
@@ -1553,6 +1901,7 @@ export function buildProgram(options = {}) {
1553
1901
  .option('-s, --scope <scope>', 'project or user')
1554
1902
  .option('-p, --platform <platform>', 'codex | claude | both')
1555
1903
  .option('--script-timeout <ms>', 'override plugin lifecycle script timeout in milliseconds')
1904
+ .option('--allow-managed-codex-install', 'allow this command to acquire or rebuild the pinned AW-managed Codex runtime', false)
1556
1905
  .option('-j, --json', 'print receipt as JSON', false)
1557
1906
  .option('-v, --verbose', 'show command diagnostics', false)
1558
1907
  .option('-D, --debug', 'write debug diagnostics to a log file', false)
@@ -1580,6 +1929,7 @@ export function buildProgram(options = {}) {
1580
1929
  .option('-s, --scope <scope>', 'project or user')
1581
1930
  .option('-p, --platform <platform>', 'codex | claude | both')
1582
1931
  .option('--script-timeout <ms>', 'override plugin lifecycle script timeout in milliseconds')
1932
+ .option('--allow-managed-codex-install', 'allow this command to acquire or rebuild the pinned AW-managed Codex runtime', false)
1583
1933
  .option('-j, --json', 'print receipt as JSON', false)
1584
1934
  .option('-v, --verbose', 'show command diagnostics', false)
1585
1935
  .option('-D, --debug', 'write debug diagnostics to a log file', false)
@@ -1608,6 +1958,7 @@ export function buildProgram(options = {}) {
1608
1958
  .option('-s, --scope <scope>', 'project or user')
1609
1959
  .option('-p, --platform <platform>', 'codex | claude | both')
1610
1960
  .option('--script-timeout <ms>', 'override plugin lifecycle script timeout in milliseconds')
1961
+ .option('--allow-managed-codex-install', 'allow this command to acquire or rebuild the pinned AW-managed Codex runtime', false)
1611
1962
  .option('-j, --json', 'print receipt as JSON', false)
1612
1963
  .option('-v, --verbose', 'show command diagnostics', false)
1613
1964
  .option('-D, --debug', 'write debug diagnostics to a log file', false)
@@ -1636,6 +1987,7 @@ export function buildProgram(options = {}) {
1636
1987
  .option('-p, --platform <platform>', 'codex | claude | both')
1637
1988
  .option('-j, --json', 'print cleanup result as JSON', false)
1638
1989
  .option('--force', 'remove exclusively owned plugin output without dependency protection', false)
1990
+ .option('--allow-managed-codex-install', 'allow this command to acquire or rebuild the pinned AW-managed Codex runtime', false)
1639
1991
  .option('-v, --verbose', 'show command diagnostics', false)
1640
1992
  .option('-D, --debug', 'write debug diagnostics to a log file', false)
1641
1993
  .option('--log-file <path>', 'write debug diagnostics to the specified file')
@@ -1662,6 +2014,7 @@ export function buildProgram(options = {}) {
1662
2014
  .option('-s, --scope <scope>', 'project or user')
1663
2015
  .option('-p, --platform <platform>', 'codex | claude | both')
1664
2016
  .option('--script-timeout <ms>', 'override plugin lifecycle script timeout in milliseconds')
2017
+ .option('--allow-managed-codex-install', 'allow this command to acquire or rebuild the pinned AW-managed Codex runtime', false)
1665
2018
  .option('-j, --json', 'print receipt as JSON', false)
1666
2019
  .option('-v, --verbose', 'show command diagnostics', false)
1667
2020
  .option('-D, --debug', 'write debug diagnostics to a log file', false)
@@ -1852,7 +2205,7 @@ export function buildProgram(options = {}) {
1852
2205
  outcome = await runActionWithContext(context, async () => {
1853
2206
  const scope = resolveConfigWriteScope(rawOptions.scope);
1854
2207
  const projectLayer = resolveConfigProjectLayer(rawOptions);
1855
- const execute = async (selectedPlugin, selectedKey, inputValue) => withResolvedConfigMutationPlugin(context, selectedPlugin, async ({ pluginId, source, plugin }, awHomeMutationToken) => {
2208
+ const execute = async (selectedPlugin, selectedKey, inputValue) => withResolvedConfigMutationPlugin(context, selectedPlugin, async ({ pluginId, source, plugin }, awHomeMutationToken, catalogOperationContext) => {
1856
2209
  if (!plugin.manifest.config?.schema) {
1857
2210
  throw new Error(`configSchemaUnavailable: Plugin "${selectedPlugin}" does not declare an AW config schema.`);
1858
2211
  }
@@ -1867,7 +2220,12 @@ export function buildProgram(options = {}) {
1867
2220
  cwd: context.cwd,
1868
2221
  env: context.env,
1869
2222
  nativeCliRunner: context.nativeCliRunner,
1870
- rebuildRuntime: { ...context, awHomeMutationToken },
2223
+ rebuildRuntime: {
2224
+ ...context,
2225
+ awHomeMutationToken,
2226
+ catalogOperationContext,
2227
+ expectedGenerationSetDigest: catalogOperationContext.generationSetDigest,
2228
+ },
1871
2229
  awHomeMutationToken,
1872
2230
  request: {
1873
2231
  updates: { [selectedKey]: inputValue },
@@ -1993,7 +2351,7 @@ export function buildProgram(options = {}) {
1993
2351
  outcome = await runActionWithContext(context, async () => {
1994
2352
  const scope = resolveConfigWriteScope(rawOptions.scope);
1995
2353
  const projectLayer = resolveConfigProjectLayer(rawOptions);
1996
- const execute = async (selectedPlugin, selectedKey) => withResolvedConfigMutationPlugin(context, selectedPlugin, async ({ pluginId, source, plugin }, awHomeMutationToken) => {
2354
+ const execute = async (selectedPlugin, selectedKey) => withResolvedConfigMutationPlugin(context, selectedPlugin, async ({ pluginId, source, plugin }, awHomeMutationToken, catalogOperationContext) => {
1997
2355
  if (plugin.manifest.config?.schema && !plugin.manifest.config.schema[selectedKey]) {
1998
2356
  throw new Error(`Unknown config key "${selectedKey}".`);
1999
2357
  }
@@ -2017,7 +2375,12 @@ export function buildProgram(options = {}) {
2017
2375
  cwd: context.cwd,
2018
2376
  env: context.env,
2019
2377
  nativeCliRunner: context.nativeCliRunner,
2020
- rebuildRuntime: { ...context, awHomeMutationToken },
2378
+ rebuildRuntime: {
2379
+ ...context,
2380
+ awHomeMutationToken,
2381
+ catalogOperationContext,
2382
+ expectedGenerationSetDigest: catalogOperationContext.generationSetDigest,
2383
+ },
2021
2384
  awHomeMutationToken,
2022
2385
  request: {
2023
2386
  removeKeys: [selectedKey],
@@ -2122,7 +2485,7 @@ export function buildProgram(options = {}) {
2122
2485
  if (!confirmed) {
2123
2486
  throw new Error(`Reset requires confirmation. Re-run \`aw config reset ${selectedPlugin} -s ${selectedScope}${projectLayer === 'local' ? ' --local' : ''} --yes\` to delete this store.`);
2124
2487
  }
2125
- return withResolvedConfigMutationPlugin(context, selectedPlugin, async ({ pluginId, source, plugin }, awHomeMutationToken) => {
2488
+ return withResolvedConfigMutationPlugin(context, selectedPlugin, async ({ pluginId, source, plugin }, awHomeMutationToken, catalogOperationContext) => {
2126
2489
  const affectedFields = await describeResetAffectedFields({
2127
2490
  pluginName: plugin.manifest.name,
2128
2491
  plugin,
@@ -2138,7 +2501,12 @@ export function buildProgram(options = {}) {
2138
2501
  cwd: context.cwd,
2139
2502
  env: context.env,
2140
2503
  nativeCliRunner: context.nativeCliRunner,
2141
- rebuildRuntime: { ...context, awHomeMutationToken },
2504
+ rebuildRuntime: {
2505
+ ...context,
2506
+ awHomeMutationToken,
2507
+ catalogOperationContext,
2508
+ expectedGenerationSetDigest: catalogOperationContext.generationSetDigest,
2509
+ },
2142
2510
  awHomeMutationToken,
2143
2511
  plugin,
2144
2512
  });
@@ -2252,7 +2620,7 @@ export function buildProgram(options = {}) {
2252
2620
  .option('-j, --json', 'print status as JSON', false)
2253
2621
  .action(async (plugins, rawOptions) => {
2254
2622
  const context = createActionContext('status', rawOptions);
2255
- const result = await runActionWithContext(context, () => statusCommandV4({
2623
+ const result = await runActionWithContext(context, () => statusCommandV5({
2256
2624
  plugins: plugins ?? [],
2257
2625
  cwd,
2258
2626
  env: context.env,
@@ -2295,10 +2663,16 @@ export async function runCli(argv, options = {}) {
2295
2663
  ...options.io,
2296
2664
  };
2297
2665
  const jsonAuthoringCommand = argv.includes('--json')
2298
- && ((argv[0] === 'catalog' && ['init', 'version', 'build', 'validate', 'status', 'publish'].includes(argv[1] ?? ''))
2299
- || (argv[0] === 'plugin' && ['build', 'test'].includes(argv[1] ?? '')))
2666
+ && ((argv[0] === 'catalog' && ['init', 'context', 'version', 'build', 'validate', 'status', 'publish'].includes(argv[1] ?? ''))
2667
+ || (argv[0] === 'plugin' && ['build', 'test', 'validate', 'status', 'remove'].includes(argv[1] ?? '')))
2300
2668
  ? `${argv[0]}:${argv[1]}`
2301
2669
  : null;
2670
+ const jsonCatalogDevCommand = argv.includes('--json')
2671
+ && argv[0] === 'catalog'
2672
+ && argv[1] === 'dev'
2673
+ && ['activate', 'status', 'deactivate'].includes(argv[2] ?? '')
2674
+ ? argv[2]
2675
+ : null;
2302
2676
  try {
2303
2677
  const authoringScriptByCommand = {
2304
2678
  init: 'init-plugin.mjs',
@@ -2306,7 +2680,6 @@ export async function runCli(argv, options = {}) {
2306
2680
  remove: 'remove-plugin.mjs',
2307
2681
  validate: 'validate-plugin.mjs',
2308
2682
  status: 'plugin-status.mjs',
2309
- 'check-versions': 'check-plugin-versions.mjs',
2310
2683
  };
2311
2684
  const authoringScript = argv[0] === 'plugin'
2312
2685
  ? authoringScriptByCommand[argv[1] ?? '']
@@ -2315,16 +2688,52 @@ export async function runCli(argv, options = {}) {
2315
2688
  : undefined;
2316
2689
  if (authoringScript && !argv.includes('--help') && !argv.includes('-h')) {
2317
2690
  const authoringArgs = argv.slice(2);
2691
+ let authoringEnv = options.env ?? process.env;
2318
2692
  if (argv[0] === 'plugin'
2319
- && argv[1] === 'validate'
2320
- && !authoringArgs.some((token) => token === '--workspace-root' || token.startsWith('--workspace-root='))) {
2321
- authoringArgs.push('--workspace-root', options.cwd ?? process.cwd());
2693
+ && !authoringArgs.some((token) => token === '--plugin-root' || token.startsWith('--plugin-root='))) {
2694
+ let explicitRoot;
2695
+ for (let index = 0; index < authoringArgs.length; index += 1) {
2696
+ const token = authoringArgs[index];
2697
+ if (token.startsWith('--workspace-root='))
2698
+ explicitRoot = token.slice('--workspace-root='.length);
2699
+ if (token === '--workspace-root')
2700
+ explicitRoot = authoringArgs[index + 1];
2701
+ }
2702
+ const originalCwd = options.cwd ?? process.cwd();
2703
+ let discoveryCwd = originalCwd;
2704
+ if (argv[1] === 'validate') {
2705
+ const valueOptions = new Set(['--workspace-root', '--claude-skill-profile', '--version-base']);
2706
+ for (let index = 0; index < authoringArgs.length; index += 1) {
2707
+ const token = authoringArgs[index];
2708
+ if (valueOptions.has(token)) {
2709
+ index += 1;
2710
+ continue;
2711
+ }
2712
+ if (!token.startsWith('-')) {
2713
+ discoveryCwd = path.resolve(originalCwd, token);
2714
+ authoringArgs[index] = discoveryCwd;
2715
+ break;
2716
+ }
2717
+ }
2718
+ }
2719
+ const workspace = await resolveCatalogWorkspaceRoot({
2720
+ cwd: discoveryCwd,
2721
+ ...(explicitRoot === undefined ? {} : { explicitRoot: path.resolve(options.cwd ?? process.cwd(), explicitRoot) }),
2722
+ mode: 'existing',
2723
+ });
2724
+ authoringEnv = {
2725
+ ...authoringEnv,
2726
+ AW_AUTHORING_WORKSPACE_ROOT: workspace.workspaceRoot,
2727
+ AW_AUTHORING_WORKSPACE_ROOT_RESOLVED_FROM: workspace.workspaceRootResolvedFrom,
2728
+ };
2729
+ if (explicitRoot === undefined)
2730
+ authoringArgs.push('--workspace-root', workspace.workspaceRoot);
2322
2731
  }
2323
2732
  return runAuthoringScript({
2324
2733
  scriptName: authoringScript,
2325
2734
  args: authoringArgs,
2326
2735
  cwd: options.cwd ?? process.cwd(),
2327
- env: options.env ?? process.env,
2736
+ env: authoringEnv,
2328
2737
  io,
2329
2738
  });
2330
2739
  }
@@ -2367,7 +2776,7 @@ export async function runCli(argv, options = {}) {
2367
2776
  }
2368
2777
  const program = buildProgram({
2369
2778
  ...options,
2370
- io,
2779
+ io: jsonCatalogDevCommand ? { ...io, stderr: () => undefined } : io,
2371
2780
  diagnostics: {
2372
2781
  ...options.diagnostics,
2373
2782
  metadata: {
@@ -2380,6 +2789,74 @@ export async function runCli(argv, options = {}) {
2380
2789
  return program.__awCommandExitState?.exitCode ?? 0;
2381
2790
  }
2382
2791
  catch (error) {
2792
+ if (jsonCatalogDevCommand) {
2793
+ const workspaceRootIndex = argv.findIndex((token) => token === '--workspace-root');
2794
+ const workspaceRootOption = argv.find((token) => token.startsWith('--workspace-root='));
2795
+ const workspaceRoot = workspaceRootOption?.slice('--workspace-root='.length)
2796
+ ?? (workspaceRootIndex >= 0 ? argv[workspaceRootIndex + 1] : undefined);
2797
+ const sourceIdIndex = argv.findIndex((token) => token === '--source-id');
2798
+ const sourceIdOption = argv.find((token) => token.startsWith('--source-id='));
2799
+ const sourceId = sourceIdOption?.slice('--source-id='.length)
2800
+ ?? (sourceIdIndex >= 0 ? argv[sourceIdIndex + 1] : undefined);
2801
+ const failure = error instanceof CommanderError
2802
+ ? { code: 'invalidArguments', message: error.message }
2803
+ : catalogDevSourceError(error);
2804
+ writeJsonReceipt(io.stdout, createCatalogDevFailureReceipt({
2805
+ command: jsonCatalogDevCommand,
2806
+ cwd: options.cwd ?? process.cwd(),
2807
+ workspaceRoot,
2808
+ sourceId,
2809
+ ...failure,
2810
+ }));
2811
+ return 1;
2812
+ }
2813
+ if (jsonAuthoringCommand && !(error instanceof CommanderError)) {
2814
+ const message = error instanceof Error ? error.message : String(error);
2815
+ if (jsonAuthoringCommand === 'plugin:validate') {
2816
+ writeJsonReceipt(io.stdout, {
2817
+ ok: false,
2818
+ profile: 'unknown',
2819
+ warnings: [],
2820
+ errors: [message],
2821
+ });
2822
+ }
2823
+ else if (jsonAuthoringCommand === 'plugin:status') {
2824
+ writeJsonReceipt(io.stdout, {
2825
+ schemaVersion: 3,
2826
+ policy: 'development',
2827
+ ok: false,
2828
+ base: null,
2829
+ requestedBase: null,
2830
+ baseCommit: null,
2831
+ checkedPlugins: 0,
2832
+ checks: [],
2833
+ workspaceRoot: null,
2834
+ workspaceRootResolvedFrom: null,
2835
+ errors: [{ code: 'workspaceResolutionFailed', message }],
2836
+ });
2837
+ }
2838
+ else if (jsonAuthoringCommand === 'plugin:remove') {
2839
+ writeJsonReceipt(io.stdout, {
2840
+ schemaVersion: 1,
2841
+ command: 'plugin:remove',
2842
+ ok: false,
2843
+ workspaceRoot: null,
2844
+ workspaceRootResolvedFrom: null,
2845
+ baseCommit: null,
2846
+ plugin: null,
2847
+ removed: false,
2848
+ errors: [{ code: 'workspaceResolutionFailed', message }],
2849
+ });
2850
+ }
2851
+ else {
2852
+ writeJsonReceipt(io.stdout, {
2853
+ command: jsonAuthoringCommand,
2854
+ ok: false,
2855
+ errors: [{ code: 'workspaceResolutionFailed', message }],
2856
+ });
2857
+ }
2858
+ return 1;
2859
+ }
2383
2860
  if (jsonAuthoringCommand && error instanceof CommanderError) {
2384
2861
  writeJsonReceipt(io.stdout, {
2385
2862
  command: jsonAuthoringCommand,