@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,24 +1,22 @@
1
1
  import crypto from 'node:crypto';
2
2
  import path from 'node:path';
3
- import { DEFAULT_CATALOG_OUTPUT_PATH, readCatalogWorkspace, resolveCatalogWorkspaceRoot, validateCatalogSnapshotComplete, } from '@lesliechan721/aw-plugin-core';
3
+ import { DEFAULT_CATALOG_OUTPUT_PATH, readCatalogWorkspace, validateCatalogSnapshotComplete, } from '@lesliechan721/aw-plugin-core';
4
4
  import { runCatalogBuildCommand } from '../authoring/workspace-commands.js';
5
- import { withAwHomeMutationLock } from '../utils/aw-home-mutation-lock.js';
6
- import { calculateCatalogSourceIdentity } from '../utils/catalog-source-identity.js';
7
- import { catalogSourceCacheInternal } from '../utils/catalog-source-cache.js';
5
+ import { readCatalogGenerationStatus } from '../utils/catalog-generation-service.js';
8
6
  import { CLI_RESERVED_IMPORTS } from '../utils/manifest.js';
9
7
  import { CATALOG_SOURCE_ID_PATTERN, isDefaultOfficialCatalogSource, readCatalogSourcesConfigSnapshot, } from '../utils/catalog-sources.js';
10
- import { addCatalogSourceCommand, refreshCatalogSourceCommand, removeCatalogSourceCommand, setPrimaryCatalogSourceCommand, updateCatalogSourceCommand, } from './catalog-source.js';
8
+ import { addCatalogSourceCommand, removeCatalogSourceCommand, setPrimaryCatalogSourceCommand, updateCatalogSourceCommand, } from './catalog-source.js';
9
+ import { syncCatalogSourceCommand } from './catalog-generation.js';
11
10
  import { getCatalogStatus } from './catalog-status.js';
11
+ import { resolveCatalogWorkspaceRoot } from './catalog-workspace-resolution.js';
12
12
  function managedSources(sources, workspaceIdentity) {
13
13
  return sources.filter((source) => source.type === 'path'
14
14
  && source.managedBy?.kind === 'catalog-workspace'
15
15
  && source.managedBy.workspaceIdentity === workspaceIdentity);
16
16
  }
17
17
  function normalizeSuggestedSourceId(workspaceRoot) {
18
- const stem = path.basename(workspaceRoot)
19
- .toLowerCase()
20
- .replace(/[^a-z0-9]+/gu, '-')
21
- .replace(/^-+|-+$/gu, '');
18
+ const stem = path.basename(workspaceRoot).toLowerCase()
19
+ .replace(/[^a-z0-9]+/gu, '-').replace(/^-+|-+$/gu, '');
22
20
  const prefixed = /^[a-z]/u.test(stem) ? stem : `catalog-${stem}`;
23
21
  const basename = (prefixed || 'catalog').slice(0, 28).replace(/-+$/u, '') || 'catalog';
24
22
  return `${basename}-dev`;
@@ -34,11 +32,6 @@ export function suggestedCatalogDevSourceId(workspaceRoot, workspaceIdentity, oc
34
32
  ? suffixedSourceId(base, workspaceIdentity)
35
33
  : base;
36
34
  }
37
- function assertExplicitSourceId(sourceId) {
38
- if (!CATALOG_SOURCE_ID_PATTERN.test(sourceId)) {
39
- throw new CatalogDevSourceError('invalidSourceId', `Invalid catalog development source ID: expected ${CATALOG_SOURCE_ID_PATTERN}.`);
40
- }
41
- }
42
35
  class CatalogDevSourceError extends Error {
43
36
  code;
44
37
  constructor(code, message) {
@@ -47,46 +40,37 @@ class CatalogDevSourceError extends Error {
47
40
  this.name = 'CatalogDevSourceError';
48
41
  }
49
42
  }
43
+ function assertExplicitSourceId(sourceId) {
44
+ if (!CATALOG_SOURCE_ID_PATTERN.test(sourceId)) {
45
+ throw new CatalogDevSourceError('invalidSourceId', 'Invalid Catalog development source ID.');
46
+ }
47
+ }
50
48
  export function createCatalogDevFailureReceipt(options) {
51
49
  const workspaceRoot = path.resolve(options.cwd, options.workspaceRoot ?? '.');
52
- const snapshotPath = path.join(workspaceRoot, DEFAULT_CATALOG_OUTPUT_PATH);
53
50
  if (options.command === 'activate') {
54
51
  return {
55
- receiptSchemaVersion: 1,
56
- command: 'catalog:dev:activate',
57
- ok: false,
58
- state: 'completed',
52
+ receiptSchemaVersion: 2, command: 'catalog:dev:activate', ok: false, state: 'failed',
59
53
  workspaceIdentity: null,
60
- snapshot: { path: snapshotPath, action: 'reused', digest: null },
61
- source: {
62
- id: options.sourceId ?? suggestedCatalogDevSourceId(workspaceRoot),
63
- action: 'reused',
64
- primary: false,
65
- },
54
+ snapshot: { action: 'reused', digest: null },
55
+ source: { id: options.sourceId ?? suggestedCatalogDevSourceId(workspaceRoot), action: 'reused', primary: false },
56
+ active: { ready: false, snapshotDigest: null },
66
57
  recovery: ['Fix the reported problem, then rerun catalog dev activate.'],
67
58
  errors: [{ code: options.code, message: options.message }],
68
59
  };
69
60
  }
70
61
  if (options.command === 'status') {
71
62
  return {
72
- receiptSchemaVersion: 1,
73
- command: 'catalog:dev:status',
74
- ok: false,
63
+ receiptSchemaVersion: 3, command: 'catalog:dev:status', ok: false, ready: false,
75
64
  workspaceIdentity: null,
76
- workspaceRoot,
77
- snapshot: { path: snapshotPath, state: 'absent', valid: false, digest: null },
65
+ snapshot: { state: 'absent', valid: false, digest: null },
78
66
  source: { exists: false, id: null, pathMatches: null, primary: null },
79
- cache: { state: 'not-applicable', validatedAt: null, snapshotDigest: null },
67
+ active: { exists: false, ready: false, digestMatchesSnapshot: false, snapshotDigest: null },
80
68
  issues: [{ code: options.code, message: options.message, blocking: true }],
81
69
  };
82
70
  }
83
71
  return {
84
- receiptSchemaVersion: 1,
85
- command: 'catalog:dev:deactivate',
86
- ok: false,
87
- state: 'completed',
72
+ receiptSchemaVersion: 2, command: 'catalog:dev:deactivate', ok: false, state: 'failed',
88
73
  workspaceIdentity: null,
89
- snapshotPath,
90
74
  source: { id: null, action: 'absent', previousPrimary: false },
91
75
  replacementPrimarySourceId: null,
92
76
  recovery: ['Fix the reported problem, then rerun catalog dev deactivate.'],
@@ -96,7 +80,7 @@ export function createCatalogDevFailureReceipt(options) {
96
80
  function codedFailure(error, fallbackCode) {
97
81
  return {
98
82
  code: error instanceof CatalogDevSourceError ? error.code : fallbackCode,
99
- message: error instanceof Error ? error.message : String(error),
83
+ message: error instanceof CatalogDevSourceError ? error.message : 'The Catalog development operation failed.',
100
84
  };
101
85
  }
102
86
  async function resolveWorkspace(cwd, workspaceRoot) {
@@ -109,8 +93,8 @@ async function resolveWorkspace(cwd, workspaceRoot) {
109
93
  const workspace = await readCatalogWorkspace(resolved.workspaceRoot, { reservedImports: CLI_RESERVED_IMPORTS });
110
94
  return { resolved, workspace };
111
95
  }
112
- catch (error) {
113
- throw new CatalogDevSourceError('workspaceInvalid', error instanceof Error ? error.message : String(error));
96
+ catch {
97
+ throw new CatalogDevSourceError('workspaceInvalid', 'Catalog Workspace is missing or invalid.');
114
98
  }
115
99
  }
116
100
  export function catalogDevSourceError(error, fallbackCode = 'catalogDevSourceFailed') {
@@ -120,14 +104,11 @@ export async function activateCatalogDevSource(options) {
120
104
  const { resolved, workspace } = await resolveWorkspace(options.cwd, options.workspaceRoot);
121
105
  const snapshotPath = path.join(workspace.workspaceRoot, DEFAULT_CATALOG_OUTPUT_PATH);
122
106
  const staticStatus = await getCatalogStatus({
123
- cwd: options.cwd,
124
- workspaceRoot: workspace.workspaceRoot,
125
- env: options.env,
107
+ cwd: options.cwd, workspaceRoot: workspace.workspaceRoot, env: options.env,
126
108
  });
127
109
  let snapshotAction = 'reused';
128
110
  let snapshotDigest = staticStatus.snapshot.snapshotDigest;
129
- const shouldBuild = options.forceBuild === true || staticStatus.snapshot.state !== 'current';
130
- if (shouldBuild) {
111
+ if (options.forceBuild === true || staticStatus.snapshot.state !== 'current') {
131
112
  try {
132
113
  await runCatalogBuildCommand({
133
114
  workspaceRoot: workspace.workspaceRoot,
@@ -140,152 +121,111 @@ export async function activateCatalogDevSource(options) {
140
121
  }
141
122
  catch (error) {
142
123
  return {
143
- receiptSchemaVersion: 1,
144
- command: 'catalog:dev:activate',
145
- ok: false,
146
- state: 'completed',
124
+ receiptSchemaVersion: 2, command: 'catalog:dev:activate', ok: false, state: 'failed',
147
125
  workspaceIdentity: workspace.workspaceIdentity,
148
- snapshot: { path: snapshotPath, action: 'built', digest: null },
126
+ snapshot: { action: 'built', digest: null },
149
127
  source: { id: options.sourceId ?? normalizeSuggestedSourceId(workspace.workspaceRoot), action: 'reused', primary: false },
150
- recovery: ['Fix the Catalog Workspace or snapshot output, then rerun catalog dev activate.'],
128
+ active: { ready: false, snapshotDigest: null },
129
+ recovery: ['Fix the Catalog Workspace, then rerun catalog dev activate.'],
151
130
  errors: [codedFailure(error, 'snapshotBuildFailed')],
152
131
  };
153
132
  }
154
133
  }
155
134
  let selectedId = options.sourceId ?? normalizeSuggestedSourceId(workspace.workspaceRoot);
156
135
  let sourceAction = 'reused';
136
+ let sourceCommitted = false;
157
137
  try {
158
- const result = await withAwHomeMutationLock({
159
- env: options.env,
160
- action: async (awHomeMutationToken) => {
161
- const configSnapshot = await readCatalogSourcesConfigSnapshot(options.env);
162
- const owned = managedSources(configSnapshot.config.sources, workspace.workspaceIdentity);
163
- if (owned.length > 1) {
164
- throw new CatalogDevSourceError('multipleManagedSources', `Catalog Workspace identity ${workspace.workspaceIdentity} owns multiple development sources: ${owned.map((source) => source.id).join(', ')}.`);
165
- }
166
- const existing = owned[0];
167
- selectedId = options.sourceId ?? normalizeSuggestedSourceId(workspace.workspaceRoot);
168
- if (options.sourceId !== undefined) {
169
- assertExplicitSourceId(options.sourceId);
170
- if (existing && existing.id !== options.sourceId) {
171
- throw new CatalogDevSourceError('sourceIdConflict', `Catalog Workspace already owns development source "${existing.id}"; it cannot also own "${options.sourceId}".`);
172
- }
173
- const collision = configSnapshot.config.sources.find((source) => source.id === options.sourceId);
174
- if (collision && collision !== existing) {
175
- throw new CatalogDevSourceError('sourceIdConflict', `Catalog source "${options.sourceId}" is owned by another Workspace or is foreign.`);
176
- }
177
- }
178
- else if (!existing && configSnapshot.config.sources.some((source) => source.id === selectedId)) {
179
- selectedId = suffixedSourceId(selectedId, workspace.workspaceIdentity);
180
- if (configSnapshot.config.sources.some((source) => source.id === selectedId)) {
181
- throw new CatalogDevSourceError('sourceIdConflict', `Deterministic Catalog development source ID "${selectedId}" is already in use.`);
182
- }
183
- }
184
- if (existing)
185
- selectedId = existing.id;
186
- const runtime = { ...options.runtime?.sourceRuntime, awHomeMutationToken };
187
- if (!existing) {
188
- sourceAction = 'added';
189
- return addCatalogSourceCommand({
190
- source: {
191
- id: selectedId,
192
- type: 'path',
193
- path: snapshotPath,
194
- primary: options.primary === true,
195
- managedBy: { kind: 'catalog-workspace', workspaceIdentity: workspace.workspaceIdentity },
196
- },
197
- cliVersion: options.cliVersion,
198
- cwd: workspace.workspaceRoot,
199
- env: options.env,
200
- runtime,
201
- managedByWorkspaceIdentity: workspace.workspaceIdentity,
202
- });
203
- }
204
- if (existing.path !== snapshotPath || (options.primary === true && !existing.primary)) {
205
- sourceAction = 'updated';
206
- const updated = existing.path === snapshotPath
207
- ? { errors: [] }
208
- : await updateCatalogSourceCommand({
209
- sourceId: existing.id,
210
- update: { type: 'path', path: snapshotPath },
211
- cliVersion: options.cliVersion,
212
- cwd: workspace.workspaceRoot,
213
- env: options.env,
214
- runtime,
215
- managedByWorkspaceIdentity: workspace.workspaceIdentity,
216
- });
217
- if (options.primary === true && !existing.primary) {
218
- await setPrimaryCatalogSourceCommand({
219
- sourceId: existing.id,
220
- cwd: workspace.workspaceRoot,
221
- env: options.env,
222
- runtime,
223
- });
224
- }
225
- if (existing.path !== snapshotPath)
226
- return updated;
227
- const refreshed = await refreshCatalogSourceCommand({
228
- sourceId: existing.id,
229
- cliVersion: options.cliVersion,
230
- env: options.env,
231
- runtime,
232
- });
233
- return { errors: refreshed.errors };
234
- }
235
- const refreshed = await refreshCatalogSourceCommand({
236
- sourceId: existing.id,
237
- cliVersion: options.cliVersion,
238
- env: options.env,
239
- runtime,
240
- });
241
- return { errors: refreshed.errors };
242
- },
138
+ const configSnapshot = await readCatalogSourcesConfigSnapshot(options.env);
139
+ const owned = managedSources(configSnapshot.config.sources, workspace.workspaceIdentity);
140
+ if (owned.length > 1) {
141
+ throw new CatalogDevSourceError('multipleManagedSources', 'Workspace owns multiple development sources.');
142
+ }
143
+ const existing = owned[0];
144
+ if (options.sourceId !== undefined) {
145
+ assertExplicitSourceId(options.sourceId);
146
+ if (existing && existing.id !== options.sourceId) {
147
+ throw new CatalogDevSourceError('sourceIdConflict', 'Workspace already owns another development source.');
148
+ }
149
+ const collision = configSnapshot.config.sources.find((source) => source.id === options.sourceId);
150
+ if (collision && collision !== existing) {
151
+ throw new CatalogDevSourceError('sourceIdConflict', 'The selected source ID is already in use.');
152
+ }
153
+ }
154
+ else if (!existing && configSnapshot.config.sources.some((source) => source.id === selectedId)) {
155
+ selectedId = suffixedSourceId(selectedId, workspace.workspaceIdentity);
156
+ if (configSnapshot.config.sources.some((source) => source.id === selectedId)) {
157
+ throw new CatalogDevSourceError('sourceIdConflict', 'The generated development source ID is already in use.');
158
+ }
159
+ }
160
+ if (existing)
161
+ selectedId = existing.id;
162
+ if (!existing) {
163
+ sourceAction = 'added';
164
+ await addCatalogSourceCommand({
165
+ source: {
166
+ id: selectedId, type: 'path', path: snapshotPath, primary: false,
167
+ managedBy: { kind: 'catalog-workspace', workspaceIdentity: workspace.workspaceIdentity },
168
+ },
169
+ cliVersion: options.cliVersion, cwd: workspace.workspaceRoot, env: options.env,
170
+ runtime: options.runtime?.sourceRuntime,
171
+ managedByWorkspaceIdentity: workspace.workspaceIdentity,
172
+ });
173
+ sourceCommitted = true;
174
+ }
175
+ else if (existing.path !== snapshotPath) {
176
+ sourceAction = 'updated';
177
+ await updateCatalogSourceCommand({
178
+ sourceId: existing.id, update: { type: 'path', path: snapshotPath },
179
+ cliVersion: options.cliVersion, cwd: workspace.workspaceRoot, env: options.env,
180
+ runtime: options.runtime?.sourceRuntime,
181
+ managedByWorkspaceIdentity: workspace.workspaceIdentity,
182
+ });
183
+ sourceCommitted = true;
184
+ }
185
+ const current = (await readCatalogSourcesConfigSnapshot(options.env)).config.sources
186
+ .find((source) => source.id === selectedId);
187
+ if (options.primary === true && !current.primary) {
188
+ await setPrimaryCatalogSourceCommand({
189
+ sourceId: selectedId, cwd: workspace.workspaceRoot, env: options.env,
190
+ runtime: options.runtime?.sourceRuntime,
191
+ });
192
+ sourceCommitted = true;
193
+ }
194
+ await options.runtime?.beforeSync?.();
195
+ const synced = await syncCatalogSourceCommand({
196
+ sourceId: selectedId, cliVersion: options.cliVersion, env: options.env,
243
197
  });
244
198
  const configured = (await readCatalogSourcesConfigSnapshot(options.env)).config.sources
245
199
  .find((source) => source.id === selectedId);
246
- const refreshErrors = result.errors.length === 0 ? [] : [{
247
- code: 'sourceRefreshFailed',
248
- message: result.errors.map((error) => error.message).join('; '),
249
- }];
250
200
  return {
251
- receiptSchemaVersion: 1,
252
- command: 'catalog:dev:activate',
253
- ok: refreshErrors.length === 0,
254
- state: refreshErrors.length === 0 ? 'completed' : 'partial',
201
+ receiptSchemaVersion: 2, command: 'catalog:dev:activate', ok: true, state: 'completed',
255
202
  workspaceIdentity: workspace.workspaceIdentity,
256
- snapshot: { path: snapshotPath, action: snapshotAction, digest: snapshotDigest },
203
+ snapshot: { action: snapshotAction, digest: snapshotDigest },
257
204
  source: { id: selectedId, action: sourceAction, primary: configured.primary },
258
- recovery: refreshErrors.length === 0 ? [] : [
259
- 'Fix the Catalog snapshot, then rerun catalog dev activate or refresh the source.',
260
- ],
261
- errors: refreshErrors,
205
+ active: { ready: true, snapshotDigest: synced.active?.snapshotDigest ?? synced.resolution.snapshotDigest },
206
+ recovery: [], errors: [],
262
207
  };
263
208
  }
264
209
  catch (error) {
265
210
  return {
266
- receiptSchemaVersion: 1,
267
- command: 'catalog:dev:activate',
268
- ok: false,
269
- state: 'completed',
211
+ receiptSchemaVersion: 2, command: 'catalog:dev:activate', ok: false,
212
+ state: snapshotAction === 'built' || sourceCommitted ? 'partial' : 'failed',
270
213
  workspaceIdentity: workspace.workspaceIdentity,
271
- snapshot: { path: snapshotPath, action: snapshotAction, digest: snapshotDigest },
214
+ snapshot: { action: snapshotAction, digest: snapshotDigest },
272
215
  source: { id: selectedId, action: sourceAction, primary: false },
273
- recovery: ['The snapshot was kept. Fix the source configuration, then rerun catalog dev activate.'],
274
- errors: [codedFailure(error, 'sourceConfigFailed')],
216
+ active: { ready: false, snapshotDigest: null },
217
+ recovery: ['The source configuration and snapshot were kept. Fix the problem, then rerun catalog dev activate.'],
218
+ errors: [codedFailure(error, sourceCommitted ? 'sourceSyncFailed' : 'sourceConfigFailed')],
275
219
  };
276
220
  }
277
221
  }
278
222
  export async function getCatalogDevSourceStatus(options) {
279
- const requestedRoot = path.resolve(options.cwd, options.workspaceRoot ?? '.');
280
223
  const empty = {
281
- receiptSchemaVersion: 1,
282
- command: 'catalog:dev:status',
283
- ok: false,
224
+ receiptSchemaVersion: 3, command: 'catalog:dev:status', ok: false, ready: false,
284
225
  workspaceIdentity: null,
285
- workspaceRoot: requestedRoot,
286
- snapshot: { path: path.join(requestedRoot, DEFAULT_CATALOG_OUTPUT_PATH), state: 'absent', valid: false, digest: null },
226
+ snapshot: { state: 'absent', valid: false, digest: null },
287
227
  source: { exists: false, id: null, pathMatches: null, primary: null },
288
- cache: { state: 'not-applicable', validatedAt: null, snapshotDigest: null },
228
+ active: { exists: false, ready: false, digestMatchesSnapshot: false, snapshotDigest: null },
289
229
  issues: [],
290
230
  };
291
231
  let workspace;
@@ -293,187 +233,183 @@ export async function getCatalogDevSourceStatus(options) {
293
233
  workspace = await resolveWorkspace(options.cwd, options.workspaceRoot);
294
234
  }
295
235
  catch (error) {
296
- empty.issues.push({ code: 'workspaceInvalid', message: codedFailure(error, 'workspaceInvalid').message, blocking: true });
236
+ empty.issues.push({ ...codedFailure(error, 'workspaceInvalid'), blocking: true });
297
237
  return empty;
298
238
  }
239
+ empty.workspaceIdentity = workspace.workspace.workspaceIdentity;
299
240
  const staticStatus = await getCatalogStatus({
300
- cwd: options.cwd,
301
- workspaceRoot: workspace.workspace.workspaceRoot,
302
- env: options.env,
303
- });
304
- const receipt = {
305
- ...empty,
306
- workspaceIdentity: workspace.workspace.workspaceIdentity,
307
- workspaceRoot: workspace.workspace.workspaceRoot,
308
- snapshot: {
309
- path: staticStatus.snapshot.path,
310
- state: staticStatus.snapshot.state,
311
- valid: staticStatus.snapshot.valid,
312
- digest: staticStatus.snapshot.snapshotDigest,
313
- },
241
+ cwd: options.cwd, workspaceRoot: workspace.workspace.workspaceRoot, env: options.env,
242
+ }).catch(() => null);
243
+ if (!staticStatus) {
244
+ empty.issues.push({ code: 'catalogStatusInvalid', message: 'Catalog snapshot status is invalid.', blocking: true });
245
+ return empty;
246
+ }
247
+ empty.snapshot = {
248
+ state: staticStatus.snapshot.state,
249
+ valid: staticStatus.snapshot.valid,
250
+ digest: staticStatus.snapshot.snapshotDigest,
314
251
  };
252
+ const workspaceIssues = staticStatus.issues.filter((issue) => issue.blocking);
253
+ empty.issues.push(...workspaceIssues.map((issue) => ({
254
+ code: issue.code,
255
+ message: 'Catalog Workspace status has a blocking issue.',
256
+ blocking: true,
257
+ })));
315
258
  if (staticStatus.snapshot.state !== 'current') {
316
- receipt.issues.push({
259
+ empty.issues.push({
317
260
  code: `snapshot${staticStatus.snapshot.state[0].toUpperCase()}${staticStatus.snapshot.state.slice(1)}`,
318
- message: `Catalog development snapshot is ${staticStatus.snapshot.state}.`,
261
+ message: `Catalog development snapshot is ${staticStatus.snapshot.state}.`, blocking: true,
262
+ });
263
+ }
264
+ const config = await readCatalogSourcesConfigSnapshot(options.env).catch(() => null);
265
+ if (!config) {
266
+ empty.issues.push({ code: 'sourceConfigInvalid', message: 'Catalog source configuration is invalid.', blocking: true });
267
+ return empty;
268
+ }
269
+ const owned = managedSources(config.config.sources, workspace.workspace.workspaceIdentity);
270
+ if (owned.length !== 1) {
271
+ empty.issues.push({
272
+ code: owned.length === 0 ? 'sourceInactive' : 'multipleManagedSources',
273
+ message: owned.length === 0
274
+ ? 'Workspace has no configured development source.'
275
+ : 'Workspace owns multiple development sources.',
319
276
  blocking: true,
320
277
  });
321
278
  }
322
- try {
323
- const config = await readCatalogSourcesConfigSnapshot(options.env);
324
- const owned = managedSources(config.config.sources, workspace.workspace.workspaceIdentity);
325
- if (owned.length > 1) {
326
- receipt.issues.push({
327
- code: 'multipleManagedSources',
328
- message: `Workspace owns multiple development sources: ${owned.map((source) => source.id).join(', ')}.`,
329
- blocking: true,
330
- });
279
+ const source = owned.length === 1 ? owned[0] : null;
280
+ if (source) {
281
+ const snapshotPath = path.join(workspace.workspace.workspaceRoot, DEFAULT_CATALOG_OUTPUT_PATH);
282
+ const pathMatches = source.path === snapshotPath;
283
+ empty.source = { exists: true, id: source.id, pathMatches, primary: source.primary };
284
+ if (!pathMatches) {
285
+ empty.issues.push({ code: 'sourcePathMismatch', message: 'Managed source path does not match this Workspace.', blocking: true });
331
286
  }
332
- const source = owned.length === 1 ? owned[0] : null;
333
- if (!source) {
334
- receipt.issues.push({ code: 'sourceInactive', message: 'Workspace has no active development source.', blocking: false });
335
- const suggested = normalizeSuggestedSourceId(workspace.workspace.workspaceRoot);
336
- const collision = config.config.sources.find((entry) => entry.id === suggested);
337
- if (collision) {
338
- receipt.issues.push({
339
- code: 'suggestedSourceIdCollision',
340
- message: `Suggested source ID "${suggested}" is owned by another Workspace or is foreign.`,
341
- blocking: false,
342
- });
343
- }
287
+ const status = await readCatalogGenerationStatus({ sourceId: source.id, env: options.env }).catch(() => null);
288
+ const entry = status?.sources[0];
289
+ const snapshotDigest = entry?.active?.snapshotDigest ?? null;
290
+ const digestMatchesSnapshot = snapshotDigest !== null && snapshotDigest === empty.snapshot.digest;
291
+ empty.active = {
292
+ exists: entry?.active !== undefined,
293
+ ready: entry?.activeReady === true,
294
+ digestMatchesSnapshot,
295
+ snapshotDigest,
296
+ };
297
+ if (!entry?.active) {
298
+ empty.issues.push({ code: 'activeAbsent', message: 'Development source has no Active snapshot.', blocking: true });
344
299
  }
345
- else {
346
- const pathMatches = source.path === receipt.snapshot.path;
347
- receipt.source = { exists: true, id: source.id, pathMatches, primary: source.primary };
348
- if (!pathMatches) {
349
- receipt.issues.push({
350
- code: 'sourcePathMismatch',
351
- message: 'Managed development source path does not match the current Workspace snapshot.',
352
- blocking: true,
353
- });
354
- }
355
- const sourceIdentity = await calculateCatalogSourceIdentity(source);
356
- const location = catalogSourceCacheInternal.resolveCatalogSourceCacheLocation({
357
- sourceId: source.id,
358
- sourceIdentity,
359
- env: options.env,
360
- });
361
- const entry = await catalogSourceCacheInternal.readCatalogSourceCache({
362
- location,
363
- sourceId: source.id,
364
- sourceIdentity,
365
- requestedRef: 'path',
366
- cliVersion: options.cliVersion,
367
- });
368
- receipt.cache = entry ? {
369
- state: entry.entryDir === location.currentDir ? 'current' : 'last-good',
370
- validatedAt: entry.metadata.validatedAt,
371
- snapshotDigest: entry.metadata.snapshotDigest,
372
- } : { state: 'absent', validatedAt: null, snapshotDigest: null };
300
+ else if (!entry.activeReady) {
301
+ empty.issues.push({ code: entry.errorCode ?? 'activeNotReady', message: 'Development source Active snapshot is not ready.', blocking: true });
302
+ }
303
+ if (entry?.active && !digestMatchesSnapshot) {
304
+ empty.issues.push({ code: 'activeSnapshotDigestMismatch', message: 'Active digest does not match the Workspace snapshot.', blocking: true });
373
305
  }
374
306
  }
375
- catch (error) {
376
- receipt.issues.push({ code: 'sourceConfigInvalid', message: codedFailure(error, 'sourceConfigInvalid').message, blocking: true });
377
- }
378
- receipt.ok = !receipt.issues.some((issue) => issue.blocking);
379
- return receipt;
307
+ empty.ok = true;
308
+ empty.ready = empty.snapshot.state === 'current'
309
+ && staticStatus.ok
310
+ && workspaceIssues.length === 0
311
+ && source !== null
312
+ && empty.source.pathMatches === true
313
+ && empty.active.ready
314
+ && empty.active.digestMatchesSnapshot;
315
+ return empty;
380
316
  }
381
317
  export async function deactivateCatalogDevSource(options) {
382
- const { workspace } = await resolveWorkspace(options.cwd, options.workspaceRoot);
383
- const snapshotPath = path.join(workspace.workspaceRoot, DEFAULT_CATALOG_OUTPUT_PATH);
384
- const config = await readCatalogSourcesConfigSnapshot(options.env).catch((error) => {
385
- throw new CatalogDevSourceError('sourceConfigInvalid', error instanceof Error ? error.message : String(error));
318
+ if (options.workspaceRoot !== undefined && options.sourceId !== undefined) {
319
+ throw new CatalogDevSourceError('invalidArguments', '--workspace-root and --source-id are mutually exclusive.');
320
+ }
321
+ const config = await readCatalogSourcesConfigSnapshot(options.env).catch(() => {
322
+ throw new CatalogDevSourceError('sourceConfigInvalid', 'Catalog source configuration is invalid.');
386
323
  });
387
- const owned = managedSources(config.config.sources, workspace.workspaceIdentity);
388
- const base = {
389
- receiptSchemaVersion: 1,
390
- command: 'catalog:dev:deactivate',
391
- workspaceIdentity: workspace.workspaceIdentity,
392
- snapshotPath,
393
- };
394
- if (owned.length > 1) {
395
- return {
396
- ...base, ok: false, state: 'completed',
397
- source: { id: null, action: 'retained', previousPrimary: false },
398
- replacementPrimarySourceId: null,
399
- recovery: ['Resolve the duplicate managed source configuration, then rerun catalog dev deactivate.'],
400
- errors: [{ code: 'multipleManagedSources', message: `Workspace owns multiple development sources: ${owned.map((source) => source.id).join(', ')}.` }],
401
- };
324
+ let source;
325
+ let workspaceIdentity;
326
+ let workspaceRoot;
327
+ if (options.sourceId !== undefined) {
328
+ assertExplicitSourceId(options.sourceId);
329
+ const configuredSource = config.config.sources.find((entry) => entry.id === options.sourceId);
330
+ if (configuredSource?.type !== 'path' || configuredSource.managedBy?.kind !== 'catalog-workspace') {
331
+ throw new CatalogDevSourceError('managedSourceNotFound', 'The source is not a Workspace-managed path source.');
332
+ }
333
+ if (options.yes !== true) {
334
+ return {
335
+ receiptSchemaVersion: 2, command: 'catalog:dev:deactivate', ok: false, state: 'failed',
336
+ workspaceIdentity: configuredSource.managedBy.workspaceIdentity,
337
+ source: { id: configuredSource.id, action: 'retained', previousPrimary: configuredSource.primary },
338
+ replacementPrimarySourceId: null,
339
+ recovery: ['Rerun with --source-id and --yes.'],
340
+ errors: [{ code: 'confirmationRequired', message: 'Recovery by source ID requires --yes.' }],
341
+ };
342
+ }
343
+ source = configuredSource;
344
+ workspaceIdentity = configuredSource.managedBy.workspaceIdentity;
345
+ workspaceRoot = options.cwd;
346
+ }
347
+ else {
348
+ const resolved = await resolveWorkspace(options.cwd, options.workspaceRoot);
349
+ workspaceIdentity = resolved.workspace.workspaceIdentity;
350
+ workspaceRoot = resolved.workspace.workspaceRoot;
351
+ const owned = managedSources(config.config.sources, workspaceIdentity);
352
+ if (owned.length > 1) {
353
+ throw new CatalogDevSourceError('multipleManagedSources', 'Workspace owns multiple development sources.');
354
+ }
355
+ source = owned[0];
402
356
  }
403
- const source = owned[0];
404
357
  if (!source) {
405
358
  return {
406
- ...base, ok: true, state: 'completed',
407
- source: { id: null, action: 'absent', previousPrimary: false },
408
- replacementPrimarySourceId: null,
409
- recovery: [], errors: [],
359
+ receiptSchemaVersion: 2, command: 'catalog:dev:deactivate', ok: true, state: 'completed',
360
+ workspaceIdentity, source: { id: null, action: 'absent', previousPrimary: false },
361
+ replacementPrimarySourceId: null, recovery: [], errors: [],
410
362
  };
411
363
  }
412
364
  let replacementPrimarySourceId = null;
413
365
  if (source.primary) {
414
- const otherSources = config.config.sources.filter((entry) => entry.id !== source.id);
415
- const official = otherSources.find(isDefaultOfficialCatalogSource);
416
- if (official)
417
- replacementPrimarySourceId = official.id;
418
- else if (otherSources.length === 1)
419
- replacementPrimarySourceId = otherSources[0].id;
420
- else {
366
+ const others = config.config.sources.filter((entry) => entry.id !== source.id);
367
+ const requested = options.replacementPrimary === undefined
368
+ ? others.find(isDefaultOfficialCatalogSource)
369
+ ?? (others.length === 1 ? others[0] : undefined)
370
+ : others.find((entry) => entry.id === options.replacementPrimary);
371
+ if (!requested) {
421
372
  return {
422
- ...base, ok: false, state: 'completed',
423
- source: { id: source.id, action: 'retained', previousPrimary: true },
373
+ receiptSchemaVersion: 2, command: 'catalog:dev:deactivate', ok: false, state: 'failed',
374
+ workspaceIdentity, source: { id: source.id, action: 'retained', previousPrimary: true },
424
375
  replacementPrimarySourceId: null,
425
- recovery: ['Select a replacement primary source, then rerun catalog dev deactivate.'],
426
- errors: [{
427
- code: otherSources.length === 0 ? 'replacementPrimaryUnavailable' : 'replacementPrimaryAmbiguous',
428
- message: otherSources.length === 0
429
- ? 'No replacement primary Catalog source is available.'
430
- : `Replacement primary Catalog source is ambiguous: ${otherSources.map((entry) => entry.id).join(', ')}.`,
431
- }],
376
+ recovery: ['Select an existing replacement primary source.'],
377
+ errors: [{ code: 'replacementPrimaryUnavailable', message: 'A replacement primary source is required.' }],
432
378
  };
433
379
  }
380
+ replacementPrimarySourceId = requested.id;
381
+ }
382
+ else if (options.replacementPrimary !== undefined) {
383
+ throw new CatalogDevSourceError('replacementPrimaryInvalid', '--replacement-primary requires a primary target source.');
434
384
  }
435
385
  try {
436
- await withAwHomeMutationLock({
437
- env: options.env,
438
- action: async (awHomeMutationToken) => {
439
- const lockedConfig = await readCatalogSourcesConfigSnapshot(options.env);
440
- if (lockedConfig.digest !== config.digest) {
441
- throw new CatalogDevSourceError('sourceConfigChanged', 'Catalog sources config changed before development source deactivation. Rerun the command.');
442
- }
443
- const runtime = { ...options.runtime?.sourceRuntime, awHomeMutationToken };
444
- if (replacementPrimarySourceId) {
445
- await setPrimaryCatalogSourceCommand({
446
- sourceId: replacementPrimarySourceId,
447
- cwd: workspace.workspaceRoot,
448
- env: options.env,
449
- runtime,
450
- });
451
- }
452
- await removeCatalogSourceCommand({
453
- sourceId: source.id,
454
- cwd: workspace.workspaceRoot,
455
- env: options.env,
456
- runtime,
457
- managedByWorkspaceIdentity: workspace.workspaceIdentity,
458
- });
459
- },
386
+ if (replacementPrimarySourceId) {
387
+ await setPrimaryCatalogSourceCommand({
388
+ sourceId: replacementPrimarySourceId, cwd: workspaceRoot, env: options.env,
389
+ runtime: options.runtime?.sourceRuntime,
390
+ });
391
+ }
392
+ await removeCatalogSourceCommand({
393
+ sourceId: source.id, cwd: workspaceRoot, env: options.env,
394
+ runtime: options.runtime?.sourceRuntime,
395
+ managedByWorkspaceIdentity: workspaceIdentity,
460
396
  });
461
397
  return {
462
- ...base, ok: true, state: 'completed',
463
- source: { id: source.id, action: 'removed', previousPrimary: source.primary },
464
- replacementPrimarySourceId,
465
- recovery: [], errors: [],
398
+ receiptSchemaVersion: 2, command: 'catalog:dev:deactivate', ok: true, state: 'completed',
399
+ workspaceIdentity, source: { id: source.id, action: 'removed', previousPrimary: source.primary },
400
+ replacementPrimarySourceId, recovery: [], errors: [],
466
401
  };
467
402
  }
468
403
  catch (error) {
469
404
  const after = await readCatalogSourcesConfigSnapshot(options.env).catch(() => null);
470
- const sourceStillExists = after?.config.sources.some((entry) => entry.id === source.id) ?? true;
405
+ const stillExists = after?.config.sources.some((entry) => entry.id === source.id) ?? true;
471
406
  const configChanged = after !== null && after.digest !== config.digest;
472
407
  return {
473
- ...base, ok: false, state: configChanged ? 'partial' : 'completed',
474
- source: { id: source.id, action: sourceStillExists ? 'retained' : 'removed', previousPrimary: source.primary },
408
+ receiptSchemaVersion: 2, command: 'catalog:dev:deactivate', ok: false,
409
+ state: configChanged || !stillExists ? 'partial' : 'failed', workspaceIdentity,
410
+ source: { id: source.id, action: stillExists ? 'retained' : 'removed', previousPrimary: source.primary },
475
411
  replacementPrimarySourceId,
476
- recovery: ['The snapshot was kept. Fix the source configuration or cache, then rerun catalog dev deactivate.'],
412
+ recovery: ['Fix the source configuration, then rerun catalog dev deactivate.'],
477
413
  errors: [codedFailure(error, 'sourceConfigFailed')],
478
414
  };
479
415
  }