@lesliechan721/aw 0.1.0-beta.10 → 0.1.0-beta.11

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 (218) hide show
  1. package/dist/authoring/assets/aw-config.d.mts +1 -50
  2. package/dist/authoring/assets/aw-config.mjs +58 -928
  3. package/dist/authoring/assets/aw-config.mjs.map +1 -1
  4. package/dist/authoring/scripts/init-plugin.mjs +28 -33
  5. package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
  6. package/dist/authoring/scripts/lib/plugin-version-check.d.mts +1 -0
  7. package/dist/authoring/scripts/lib/plugin-version-check.mjs +229 -8
  8. package/dist/authoring/scripts/lib/plugin-version-check.mjs.map +1 -1
  9. package/dist/authoring/scripts/validate-plugin.mjs +165 -45
  10. package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
  11. package/dist/scripts/bundle-plugins.js +18 -4
  12. package/dist/scripts/bundle-plugins.js.map +1 -1
  13. package/dist/scripts/test-plugin-scripts.d.ts +2 -0
  14. package/dist/scripts/test-plugin-scripts.js +21 -5
  15. package/dist/scripts/test-plugin-scripts.js.map +1 -1
  16. package/dist/src/commands/aw-capabilities.d.ts +1 -1
  17. package/dist/src/commands/aw-capabilities.js +1 -1
  18. package/dist/src/commands/aw-capabilities.js.map +1 -1
  19. package/dist/src/commands/catalog-dev-source.d.ts +6 -3
  20. package/dist/src/commands/catalog-dev-source.js +96 -35
  21. package/dist/src/commands/catalog-dev-source.js.map +1 -1
  22. package/dist/src/commands/catalog-publication-inspection.d.ts +1 -1
  23. package/dist/src/commands/catalog-publication-inspection.js +54 -8
  24. package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
  25. package/dist/src/commands/catalog-publication-journal.js +1 -1
  26. package/dist/src/commands/catalog-publication-journal.js.map +1 -1
  27. package/dist/src/commands/catalog-source.d.ts +19 -4
  28. package/dist/src/commands/catalog-source.js +121 -12
  29. package/dist/src/commands/catalog-source.js.map +1 -1
  30. package/dist/src/commands/catalog-store.d.ts +26 -7
  31. package/dist/src/commands/catalog-store.js +361 -42
  32. package/dist/src/commands/catalog-store.js.map +1 -1
  33. package/dist/src/commands/console.js +28 -17
  34. package/dist/src/commands/console.js.map +1 -1
  35. package/dist/src/commands/operation-plan.d.ts +2 -1
  36. package/dist/src/commands/operation-plan.js +24 -0
  37. package/dist/src/commands/operation-plan.js.map +1 -1
  38. package/dist/src/commands/operation-planner.d.ts +2 -2
  39. package/dist/src/commands/operation-planner.js +11 -19
  40. package/dist/src/commands/operation-planner.js.map +1 -1
  41. package/dist/src/commands/options.d.ts +2 -2
  42. package/dist/src/commands/options.js +18 -4
  43. package/dist/src/commands/options.js.map +1 -1
  44. package/dist/src/commands/plugin-capabilities.js +2 -2
  45. package/dist/src/commands/plugin-capabilities.js.map +1 -1
  46. package/dist/src/commands/rebuild-command.d.ts +7 -0
  47. package/dist/src/commands/rebuild-command.js +769 -279
  48. package/dist/src/commands/rebuild-command.js.map +1 -1
  49. package/dist/src/commands/rebuild-integration.d.ts +24 -47
  50. package/dist/src/commands/rebuild-integration.js +1074 -1011
  51. package/dist/src/commands/rebuild-integration.js.map +1 -1
  52. package/dist/src/commands/rebuild-operations.d.ts +50 -12
  53. package/dist/src/commands/rebuild-operations.js +207 -101
  54. package/dist/src/commands/rebuild-operations.js.map +1 -1
  55. package/dist/src/commands/status-v6.d.ts +21 -2
  56. package/dist/src/commands/status-v6.js +163 -31
  57. package/dist/src/commands/status-v6.js.map +1 -1
  58. package/dist/src/commands/sync-command.d.ts +17 -0
  59. package/dist/src/commands/sync-command.js +45 -37
  60. package/dist/src/commands/sync-command.js.map +1 -1
  61. package/dist/src/commands/write-commands.d.ts +5 -0
  62. package/dist/src/commands/write-commands.js +50 -3
  63. package/dist/src/commands/write-commands.js.map +1 -1
  64. package/dist/src/generators/local-plugin.js +14 -4
  65. package/dist/src/generators/local-plugin.js.map +1 -1
  66. package/dist/src/index.js +216 -85
  67. package/dist/src/index.js.map +1 -1
  68. package/dist/src/output/command-receipt.js +1 -3
  69. package/dist/src/output/command-receipt.js.map +1 -1
  70. package/dist/src/output/rebuild-progress.js +1 -3
  71. package/dist/src/output/rebuild-progress.js.map +1 -1
  72. package/dist/src/portable/materializer.js +6 -6
  73. package/dist/src/portable/materializer.js.map +1 -1
  74. package/dist/src/tui/catalog-generation.js +41 -1
  75. package/dist/src/tui/catalog-generation.js.map +1 -1
  76. package/dist/src/tui/catalog-sources/session.d.ts +1 -0
  77. package/dist/src/tui/catalog-sources/session.js +16 -3
  78. package/dist/src/tui/catalog-sources/session.js.map +1 -1
  79. package/dist/src/tui/catalog-sources/types.d.ts +3 -2
  80. package/dist/src/tui/components.d.ts +4 -0
  81. package/dist/src/tui/components.js +36 -24
  82. package/dist/src/tui/components.js.map +1 -1
  83. package/dist/src/tui/console-app-v4.d.ts +13 -4
  84. package/dist/src/tui/console-app-v4.js +2067 -839
  85. package/dist/src/tui/console-app-v4.js.map +1 -1
  86. package/dist/src/tui/controller-runtime.js +585 -33
  87. package/dist/src/tui/controller-runtime.js.map +1 -1
  88. package/dist/src/tui/controller.d.ts +152 -6
  89. package/dist/src/tui/controller.js +1168 -156
  90. package/dist/src/tui/controller.js.map +1 -1
  91. package/dist/src/tui/diagnostic-projection.d.ts +22 -0
  92. package/dist/src/tui/diagnostic-projection.js +437 -0
  93. package/dist/src/tui/diagnostic-projection.js.map +1 -0
  94. package/dist/src/tui/diagnostics.d.ts +1 -1
  95. package/dist/src/tui/diagnostics.js +6 -1
  96. package/dist/src/tui/diagnostics.js.map +1 -1
  97. package/dist/src/tui/glossary.d.ts +23 -0
  98. package/dist/src/tui/glossary.js +42 -0
  99. package/dist/src/tui/glossary.js.map +1 -0
  100. package/dist/src/tui/index.d.ts +4 -1
  101. package/dist/src/tui/index.js +4 -1
  102. package/dist/src/tui/index.js.map +1 -1
  103. package/dist/src/tui/keys.d.ts +44 -0
  104. package/dist/src/tui/keys.js +43 -15
  105. package/dist/src/tui/keys.js.map +1 -1
  106. package/dist/src/tui/lifecycle-action-view.d.ts +6 -0
  107. package/dist/src/tui/lifecycle-action-view.js +34 -0
  108. package/dist/src/tui/lifecycle-action-view.js.map +1 -0
  109. package/dist/src/tui/model.d.ts +12 -2
  110. package/dist/src/tui/model.js +128 -52
  111. package/dist/src/tui/model.js.map +1 -1
  112. package/dist/src/tui/operation-diagnostic-screens.d.ts +21 -0
  113. package/dist/src/tui/operation-diagnostic-screens.js +101 -0
  114. package/dist/src/tui/operation-diagnostic-screens.js.map +1 -0
  115. package/dist/src/tui/operation-history.d.ts +80 -0
  116. package/dist/src/tui/operation-history.js +130 -0
  117. package/dist/src/tui/operation-history.js.map +1 -0
  118. package/dist/src/tui/operation-review-planner.js +306 -86
  119. package/dist/src/tui/operation-review-planner.js.map +1 -1
  120. package/dist/src/tui/router.d.ts +82 -17
  121. package/dist/src/tui/router.js +186 -38
  122. package/dist/src/tui/router.js.map +1 -1
  123. package/dist/src/tui/screen-registry.d.ts +546 -0
  124. package/dist/src/tui/screen-registry.js +179 -0
  125. package/dist/src/tui/screen-registry.js.map +1 -0
  126. package/dist/src/tui/session-console-app.d.ts +6 -0
  127. package/dist/src/tui/session-console-app.js +13 -0
  128. package/dist/src/tui/session-console-app.js.map +1 -0
  129. package/dist/src/tui/session-host.d.ts +44 -0
  130. package/dist/src/tui/session-host.js +197 -0
  131. package/dist/src/tui/session-host.js.map +1 -0
  132. package/dist/src/types.d.ts +64 -3
  133. package/dist/src/types.js +1 -1
  134. package/dist/src/types.js.map +1 -1
  135. package/dist/src/utils/agent-version.js +1 -1
  136. package/dist/src/utils/agent-version.js.map +1 -1
  137. package/dist/src/utils/artifact-renderer.d.ts +2 -1
  138. package/dist/src/utils/artifact-renderer.js +52 -52
  139. package/dist/src/utils/artifact-renderer.js.map +1 -1
  140. package/dist/src/utils/bundle-layout.js +4 -4
  141. package/dist/src/utils/bundle-layout.js.map +1 -1
  142. package/dist/src/utils/catalog-capability-projection.d.ts +8 -0
  143. package/dist/src/utils/catalog-capability-projection.js +14 -0
  144. package/dist/src/utils/catalog-capability-projection.js.map +1 -0
  145. package/dist/src/utils/catalog-generation-resolver.d.ts +14 -2
  146. package/dist/src/utils/catalog-generation-resolver.js +49 -27
  147. package/dist/src/utils/catalog-generation-resolver.js.map +1 -1
  148. package/dist/src/utils/catalog-generation-service.d.ts +8 -1
  149. package/dist/src/utils/catalog-generation-service.js +81 -47
  150. package/dist/src/utils/catalog-generation-service.js.map +1 -1
  151. package/dist/src/utils/catalog-generation-store.d.ts +1 -0
  152. package/dist/src/utils/catalog-generation-store.js +60 -5
  153. package/dist/src/utils/catalog-generation-store.js.map +1 -1
  154. package/dist/src/utils/catalog-operation-context.js +1 -0
  155. package/dist/src/utils/catalog-operation-context.js.map +1 -1
  156. package/dist/src/utils/catalog-public-error.js +4 -0
  157. package/dist/src/utils/catalog-public-error.js.map +1 -1
  158. package/dist/src/utils/catalog-source-impact.d.ts +3 -2
  159. package/dist/src/utils/catalog-source-impact.js +142 -20
  160. package/dist/src/utils/catalog-source-impact.js.map +1 -1
  161. package/dist/src/utils/catalog-source-references.js +95 -9
  162. package/dist/src/utils/catalog-source-references.js.map +1 -1
  163. package/dist/src/utils/catalog-sources.d.ts +1 -1
  164. package/dist/src/utils/catalog-sources.js +19 -3
  165. package/dist/src/utils/catalog-sources.js.map +1 -1
  166. package/dist/src/utils/codex-manager.js +8 -0
  167. package/dist/src/utils/codex-manager.js.map +1 -1
  168. package/dist/src/utils/codex-native-observation.d.ts +34 -1
  169. package/dist/src/utils/codex-native-observation.js +132 -0
  170. package/dist/src/utils/codex-native-observation.js.map +1 -1
  171. package/dist/src/utils/codex-reconciler.d.ts +0 -2
  172. package/dist/src/utils/codex-reconciler.js.map +1 -1
  173. package/dist/src/utils/codex-shared-native.d.ts +2 -26
  174. package/dist/src/utils/codex-shared-native.js +8 -82
  175. package/dist/src/utils/codex-shared-native.js.map +1 -1
  176. package/dist/src/utils/git-catalog-provider.d.ts +3 -0
  177. package/dist/src/utils/git-catalog-provider.js +40 -1
  178. package/dist/src/utils/git-catalog-provider.js.map +1 -1
  179. package/dist/src/utils/local-marketplace.d.ts +1 -0
  180. package/dist/src/utils/local-marketplace.js +69 -73
  181. package/dist/src/utils/local-marketplace.js.map +1 -1
  182. package/dist/src/utils/multi-source-catalog.js +1 -0
  183. package/dist/src/utils/multi-source-catalog.js.map +1 -1
  184. package/dist/src/utils/native-cli.d.ts +9 -4
  185. package/dist/src/utils/native-cli.js +280 -34
  186. package/dist/src/utils/native-cli.js.map +1 -1
  187. package/dist/src/utils/path-catalog-provider.js +2 -0
  188. package/dist/src/utils/path-catalog-provider.js.map +1 -1
  189. package/dist/src/utils/plugin-config-write.d.ts +15 -13
  190. package/dist/src/utils/plugin-config-write.js +418 -198
  191. package/dist/src/utils/plugin-config-write.js.map +1 -1
  192. package/dist/src/utils/plugin-config.d.ts +48 -4
  193. package/dist/src/utils/plugin-config.js +289 -38
  194. package/dist/src/utils/plugin-config.js.map +1 -1
  195. package/dist/src/utils/plugin-scripts.d.ts +20 -12
  196. package/dist/src/utils/plugin-scripts.js +376 -109
  197. package/dist/src/utils/plugin-scripts.js.map +1 -1
  198. package/dist/src/utils/process-tree.d.ts +2 -2
  199. package/dist/src/utils/process-tree.js +1 -1
  200. package/dist/src/utils/process-tree.js.map +1 -1
  201. package/dist/src/utils/project-boundary.d.ts +11 -1
  202. package/dist/src/utils/project-boundary.js +17 -8
  203. package/dist/src/utils/project-boundary.js.map +1 -1
  204. package/dist/src/utils/safe-operation-diagnostic.d.ts +15 -0
  205. package/dist/src/utils/safe-operation-diagnostic.js +33 -0
  206. package/dist/src/utils/safe-operation-diagnostic.js.map +1 -0
  207. package/dist/src/utils/sensitive-content.d.ts +1 -0
  208. package/dist/src/utils/sensitive-content.js +15 -0
  209. package/dist/src/utils/sensitive-content.js.map +1 -0
  210. package/dist/src/utils/windows-claude-shim.d.ts +9 -0
  211. package/dist/src/utils/windows-claude-shim.js +141 -0
  212. package/dist/src/utils/windows-claude-shim.js.map +1 -0
  213. package/dist/vitest.config.js +91 -10
  214. package/dist/vitest.config.js.map +1 -1
  215. package/package.json +9 -9
  216. package/dist/authoring/templates/aw-config-runtime.d.mts +0 -2
  217. package/dist/authoring/templates/aw-config-runtime.mjs +0 -407
  218. package/dist/authoring/templates/aw-config-runtime.mjs.map +0 -1
@@ -7,6 +7,7 @@ import { assertReadyPluginConfigStore, assertSafePluginConfigSegment, codexNativ
7
7
  import { collectSensitivePluginConfigValues, redactPluginScriptOutput, } from './plugin-scripts.js';
8
8
  import { resolveClaudeProjectKey, resolveCodexProjectKey } from './paths.js';
9
9
  import { withAwHomeMutationLock, } from './aw-home-mutation-lock.js';
10
+ import { assertProjectSharedConfigPathVisible, } from './project-boundary.js';
10
11
  export function buildConfigMutationReceipt(command, receipt) {
11
12
  return {
12
13
  ...receipt,
@@ -14,6 +15,60 @@ export function buildConfigMutationReceipt(command, receipt) {
14
15
  command,
15
16
  };
16
17
  }
18
+ function publicConfigApplyTargetResult(result) {
19
+ return {
20
+ target: {
21
+ pluginName: result.target.pluginName,
22
+ ...(result.target.pluginId ? { pluginId: result.target.pluginId } : {}),
23
+ platform: result.target.platform,
24
+ scope: result.target.scope,
25
+ },
26
+ action: result.action,
27
+ state: result.state,
28
+ ...(result.message ? { message: result.message } : {}),
29
+ ...(result.errorCode ? { errorCode: result.errorCode } : {}),
30
+ ...(result.relation ? { relation: result.relation } : {}),
31
+ ...(result.requiredBy ? { requiredBy: result.requiredBy } : {}),
32
+ };
33
+ }
34
+ function publicConfigApplyResult(apply) {
35
+ if (apply.state === 'skipped')
36
+ return apply;
37
+ return {
38
+ ...apply,
39
+ targetResults: apply.targetResults.map(publicConfigApplyTargetResult),
40
+ };
41
+ }
42
+ export function configWriteStateForError(error) {
43
+ return error?.configWrite === 'failed'
44
+ ? 'failed'
45
+ : 'notStarted';
46
+ }
47
+ function markConfigWriteFailed(error) {
48
+ const failure = error instanceof Error ? error : new Error(String(error));
49
+ return Object.assign(failure, { configWrite: 'failed' });
50
+ }
51
+ function skippedApply(reason) {
52
+ return { state: 'skipped', reason, targetResults: [] };
53
+ }
54
+ function unavailableApply(reason, stage, targetResults = []) {
55
+ const messages = {
56
+ invalidConfig: 'The effective config is invalid for every visible target.',
57
+ schemaUnavailable: 'The config schema is unavailable after the config commit.',
58
+ sourceUnavailable: 'The plugin source is unavailable after the config commit.',
59
+ effectiveConfigUnavailable: 'The effective config cannot be read after the config commit.',
60
+ targetDiscoveryFailed: 'Visible config apply targets cannot be discovered after the config commit.',
61
+ };
62
+ return {
63
+ state: 'unavailable',
64
+ reason,
65
+ targetResults,
66
+ error: { stage, code: reason, message: messages[reason] },
67
+ };
68
+ }
69
+ function overallStateForApply(apply) {
70
+ return apply.state === 'succeeded' || apply.state === 'skipped' ? 'succeeded' : 'partial';
71
+ }
17
72
  function uniqueInOrder(values) {
18
73
  return [...new Set(values)];
19
74
  }
@@ -91,6 +146,9 @@ async function reinstallVisibleTargets(options) {
91
146
  : { targets: dedupeTargets(options.applyTargets), failures: [] });
92
147
  const targetResults = [...discovered.failures];
93
148
  let runtimeFailed = discovered.failures.length > 0;
149
+ let invalidTargets = 0;
150
+ let unavailableTargets = 0;
151
+ const errors = [];
94
152
  const reinstall = options.reinstallCommandImpl ?? syncWriteCommand;
95
153
  if (options.plugin.sourceId && !options.plugin.pluginId) {
96
154
  throw new Error(`Plugin "${options.plugin.manifest.name}" is missing its namespaced plugin ID.`);
@@ -105,6 +163,7 @@ async function reinstallVisibleTargets(options) {
105
163
  ...(options.plugin.sourceId ? {
106
164
  sourceId: options.plugin.sourceId,
107
165
  sourceIdentity: options.plugin.sourceIdentity,
166
+ logicalIdentity: options.plugin.catalogLogicalIdentity,
108
167
  } : {}),
109
168
  pluginName: options.plugin.manifest.name,
110
169
  manifest: options.plugin.manifest,
@@ -118,6 +177,10 @@ async function reinstallVisibleTargets(options) {
118
177
  // Generic credential redaction and known config paths still apply.
119
178
  }
120
179
  let sanitized = redactPluginScriptOutput(message, sensitiveValues);
180
+ for (const privatePath of [target.projectKey, options.cwd]) {
181
+ if (privatePath)
182
+ sanitized = sanitized.split(privatePath).join('<project>');
183
+ }
121
184
  for (const scope of ['user', 'project']) {
122
185
  const configPath = resolvePluginConfigStorePath({
123
186
  sourceId: options.plugin.sourceId,
@@ -151,6 +214,48 @@ async function reinstallVisibleTargets(options) {
151
214
  ])));
152
215
  };
153
216
  for (const target of discovered.targets) {
217
+ try {
218
+ const effective = await resolveEffectivePluginConfig({
219
+ ...(options.plugin.sourceId ? {
220
+ sourceId: options.plugin.sourceId,
221
+ sourceIdentity: options.plugin.sourceIdentity,
222
+ logicalIdentity: options.plugin.catalogLogicalIdentity,
223
+ } : {}),
224
+ pluginName: options.plugin.manifest.name,
225
+ manifest: options.plugin.manifest,
226
+ targetScope: target.scope,
227
+ cwd: options.cwd,
228
+ env: options.env,
229
+ });
230
+ if (effective.issues.length > 0) {
231
+ invalidTargets += 1;
232
+ targetResults.push({
233
+ target,
234
+ action: 'reinstall',
235
+ state: 'skipped',
236
+ errorCode: 'invalidConfig',
237
+ message: 'The effective config is invalid for this target.',
238
+ });
239
+ continue;
240
+ }
241
+ }
242
+ catch {
243
+ runtimeFailed = true;
244
+ unavailableTargets += 1;
245
+ targetResults.push({
246
+ target,
247
+ action: 'reinstall',
248
+ state: 'failed',
249
+ errorCode: 'effectiveConfigUnavailable',
250
+ message: 'The effective config cannot be read for this target.',
251
+ });
252
+ errors.push({
253
+ stage: 'targetValidation',
254
+ code: 'effectiveConfigUnavailable',
255
+ message: 'The effective config cannot be read for a visible target.',
256
+ });
257
+ continue;
258
+ }
154
259
  try {
155
260
  const debugLogger = options.rebuildRuntime?.debugLogger;
156
261
  const reporter = options.rebuildRuntime?.reporter;
@@ -158,6 +263,10 @@ async function reinstallVisibleTargets(options) {
158
263
  cwd: options.cwd,
159
264
  platform: target.platform,
160
265
  scope: target.scope,
266
+ yes: true,
267
+ ...(options.rebuildRuntime?.scriptTimeoutMs === undefined
268
+ ? {}
269
+ : { scriptTimeoutMs: options.rebuildRuntime.scriptTimeoutMs }),
161
270
  }, {
162
271
  ...options.rebuildRuntime,
163
272
  env: options.env,
@@ -175,10 +284,12 @@ async function reinstallVisibleTargets(options) {
175
284
  },
176
285
  } : {}),
177
286
  });
178
- if (result.overallState === 'failed')
287
+ options.rebuildRuntime?.operationDiagnosticSink?.(result.rebuildResults);
288
+ if (result.overallState !== 'succeeded')
179
289
  runtimeFailed = true;
180
290
  targetResults.push(...await Promise.all(result.targetResults.map(async (entry) => ({
181
291
  ...entry,
292
+ state: entry.action === 'skipped' ? 'skipped' : entry.state,
182
293
  ...(entry.message ? { message: await sanitizeFailure(entry.message, entry.target) } : {}),
183
294
  }))));
184
295
  }
@@ -191,17 +302,33 @@ async function reinstallVisibleTargets(options) {
191
302
  state: 'failed',
192
303
  message,
193
304
  });
305
+ errors.push({
306
+ stage: 'apply',
307
+ code: 'targetApplyFailed',
308
+ message: 'A visible config apply target failed.',
309
+ });
194
310
  }
195
311
  }
196
- const overallState = runtimeFailed || targetResults.some((entry) => entry.state === 'failed')
197
- ? 'partial' : 'succeeded';
198
- return {
199
- overallState,
200
- targetResults,
201
- ...(discovered.targets.length === 0 && discovered.failures.length === 0
202
- ? { applySkippedReason: 'noVisibleTarget' }
203
- : {}),
204
- };
312
+ if (discovered.targets.length === 0 && discovered.failures.length === 0) {
313
+ return skippedApply('noVisibleTarget');
314
+ }
315
+ if (discovered.targets.length > 0 && invalidTargets === discovered.targets.length) {
316
+ return unavailableApply('invalidConfig', 'targetValidation', targetResults);
317
+ }
318
+ if (discovered.targets.length > 0 && unavailableTargets === discovered.targets.length) {
319
+ return unavailableApply('effectiveConfigUnavailable', 'targetValidation', targetResults);
320
+ }
321
+ if (runtimeFailed
322
+ || invalidTargets > 0
323
+ || unavailableTargets > 0
324
+ || targetResults.some((entry) => entry.state === 'failed' || entry.state === 'skipped')) {
325
+ return {
326
+ state: 'partial',
327
+ targetResults,
328
+ ...(errors.length > 0 ? { errors } : {}),
329
+ };
330
+ }
331
+ return { state: 'succeeded', targetResults };
205
332
  }
206
333
  async function resolveConfigApplyTargets(options) {
207
334
  if (options.applyTargets !== undefined) {
@@ -217,15 +344,16 @@ async function resolveConfigApplyTargets(options) {
217
344
  rebuildRuntime: options.rebuildRuntime,
218
345
  });
219
346
  }
220
- async function configApplyHasIssues(options) {
221
- const scopes = [...new Set(options.targets.map((target) => target.scope))];
222
- for (const scope of scopes) {
223
- if (options.knownValidScopes?.includes(scope))
224
- continue;
347
+ async function configApplyHasValidCodexTarget(options) {
348
+ const codexScopes = new Set(options.targets
349
+ .filter((target) => target.platform === 'codex')
350
+ .map((target) => target.scope));
351
+ for (const scope of codexScopes) {
225
352
  const effective = await resolveEffectivePluginConfig({
226
353
  ...(options.plugin.sourceId ? {
227
354
  sourceId: options.plugin.sourceId,
228
355
  sourceIdentity: options.plugin.sourceIdentity,
356
+ logicalIdentity: options.plugin.catalogLogicalIdentity,
229
357
  } : {}),
230
358
  pluginName: options.plugin.manifest.name,
231
359
  manifest: options.plugin.manifest,
@@ -233,14 +361,29 @@ async function configApplyHasIssues(options) {
233
361
  cwd: options.cwd,
234
362
  env: options.env,
235
363
  });
236
- if (effective.issues.length > 0)
364
+ if (effective.issues.length === 0)
237
365
  return true;
238
366
  }
239
367
  return false;
240
368
  }
369
+ async function applyConfigToVisibleTargets(options) {
370
+ let discovered;
371
+ try {
372
+ discovered = await resolveConfigApplyTargets(options);
373
+ }
374
+ catch {
375
+ return unavailableApply('targetDiscoveryFailed', 'targetDiscovery');
376
+ }
377
+ if (discovered.targets.length === 0
378
+ && discovered.failures.length === 0
379
+ && options.noVisibleTargetHasInvalidConfig) {
380
+ return unavailableApply('invalidConfig', 'targetValidation');
381
+ }
382
+ return reinstallVisibleTargets({ ...options, discovered });
383
+ }
241
384
  function otherProjectsWarning(scope) {
242
385
  return scope === 'user'
243
- ? ['其它项目不会由本次命令扫描或更新。请在每个项目目录中运行对应的 aw reinstall 命令。']
386
+ ? ['其它项目不会由本次命令扫描或更新,可能需要在对应项目目录中运行 aw sync。']
244
387
  : [];
245
388
  }
246
389
  function buildReceiptFieldEntry(options) {
@@ -261,25 +404,38 @@ export async function replayConfigRuntimeWrites(options) {
261
404
  action: async (awHomeMutationToken) => {
262
405
  const env = options.env ?? process.env;
263
406
  const rebuildRuntime = { ...options.rebuildRuntime, awHomeMutationToken };
264
- const discovered = await resolveConfigApplyTargets({
265
- plugin: options.plugin,
266
- scope: options.scope,
267
- cwd: options.cwd,
268
- env,
269
- applyTargets: options.applyTargets,
270
- nativeCliRunner: options.nativeCliRunner,
271
- rebuildRuntime,
272
- });
273
- const applied = await configApplyHasIssues({
274
- plugin: options.plugin,
275
- targets: discovered.targets,
276
- cwd: options.cwd,
277
- env,
278
- }) ? {
279
- overallState: 'partial',
280
- targetResults: [],
281
- applySkippedReason: 'invalidConfig',
282
- } : await reinstallVisibleTargets({
407
+ let discovered;
408
+ try {
409
+ discovered = await resolveConfigApplyTargets({
410
+ plugin: options.plugin,
411
+ scope: options.scope,
412
+ cwd: options.cwd,
413
+ env,
414
+ applyTargets: options.applyTargets,
415
+ nativeCliRunner: options.nativeCliRunner,
416
+ rebuildRuntime,
417
+ });
418
+ }
419
+ catch {
420
+ return {
421
+ configWrite: 'succeeded',
422
+ overallState: 'partial',
423
+ apply: publicConfigApplyResult(unavailableApply('targetDiscoveryFailed', 'targetDiscovery')),
424
+ otherProjectsMayRequireSync: false,
425
+ };
426
+ }
427
+ if (options.scope === 'user'
428
+ && options.sharedNativeApplyConfirmed !== true
429
+ && pluginHasSharedNativeRefreshKeys(options.plugin)
430
+ && await configApplyHasValidCodexTarget({
431
+ plugin: options.plugin,
432
+ targets: discovered.targets,
433
+ cwd: options.cwd,
434
+ env,
435
+ })) {
436
+ throwSharedNativeApplyConfirmationRequired();
437
+ }
438
+ const apply = await reinstallVisibleTargets({
283
439
  plugin: options.plugin,
284
440
  scope: options.scope,
285
441
  cwd: options.cwd,
@@ -292,10 +448,9 @@ export async function replayConfigRuntimeWrites(options) {
292
448
  });
293
449
  return {
294
450
  configWrite: 'succeeded',
295
- overallState: applied.overallState,
296
- targetResults: applied.targetResults,
297
- ...(applied.applySkippedReason ? { applySkippedReason: applied.applySkippedReason } : {}),
298
- otherProjectsRequireReinstall: options.scope === 'user',
451
+ overallState: overallStateForApply(apply),
452
+ apply: publicConfigApplyResult(apply),
453
+ otherProjectsMayRequireSync: false,
299
454
  };
300
455
  },
301
456
  });
@@ -307,6 +462,17 @@ function changedKeysAffectSharedNativeTarget(options) {
307
462
  && target.delivery?.mode === 'codex-native'
308
463
  && target.refreshKeys.some((key) => changedKeys.has(key)));
309
464
  }
465
+ function pluginHasSharedNativeRefreshKeys(plugin) {
466
+ return (plugin.manifest.artifacts?.targets ?? []).some((target) => target.platform === 'codex'
467
+ && target.target === 'codex.skill'
468
+ && target.delivery?.mode === 'codex-native'
469
+ && target.refreshKeys.length > 0);
470
+ }
471
+ function throwSharedNativeApplyConfirmationRequired() {
472
+ const error = new Error('sharedNativeConfigApplyConfirmationRequired: Applying this user config changes a shared Codex native artifact. Re-run with --yes.');
473
+ error.code = 'sharedNativeConfigApplyConfirmationRequired';
474
+ throw error;
475
+ }
310
476
  async function applyPluginConfigWriteUnlocked(options) {
311
477
  const requestedPluginName = options.pluginName ?? options.plugin?.manifest.name;
312
478
  if (!requestedPluginName)
@@ -315,6 +481,7 @@ async function applyPluginConfigWriteUnlocked(options) {
315
481
  const configIdentity = options.plugin?.sourceId ? {
316
482
  sourceId: options.plugin.sourceId,
317
483
  sourceIdentity: options.plugin.sourceIdentity,
484
+ logicalIdentity: options.plugin.catalogLogicalIdentity,
318
485
  } : {};
319
486
  const requestedUpdates = options.request.updates ?? {};
320
487
  const requestedRemoveKeys = uniqueInOrder(options.request.removeKeys ?? []);
@@ -346,11 +513,14 @@ async function applyPluginConfigWriteUnlocked(options) {
346
513
  });
347
514
  assertReadyPluginConfigStore(userStore);
348
515
  }
349
- for (const key of requestedRemoveKeys) {
350
- if (!schema[key])
351
- throw new Error(`Unknown config key "${key}".`);
352
- }
353
516
  if (options.scope === 'project') {
517
+ const rejectedSensitiveKeys = Object.keys(requestedUpdates)
518
+ .filter((key) => schema[key]?.sensitive === true);
519
+ if (rejectedSensitiveKeys.length > 0) {
520
+ const error = new Error('sensitiveProjectConfigUnsupported: Sensitive config can only be set in user scope.');
521
+ error.code = 'sensitiveProjectConfigUnsupported';
522
+ throw error;
523
+ }
354
524
  const userOnlyKeys = codexNativeRefreshKeys(schemaPlugin.manifest);
355
525
  const rejectedKeys = Object.keys(requestedUpdates).filter((key) => userOnlyKeys.has(key));
356
526
  if (rejectedKeys.length > 0) {
@@ -369,8 +539,14 @@ async function applyPluginConfigWriteUnlocked(options) {
369
539
  schema,
370
540
  });
371
541
  assertReadyPluginConfigStore(store);
542
+ for (const key of requestedRemoveKeys) {
543
+ if (!schema[key] && !Object.hasOwn(store.values, key)) {
544
+ throw new Error(`Unknown config key "${key}".`);
545
+ }
546
+ }
372
547
  const warnings = [];
373
548
  const removedKeys = requestedRemoveKeys.filter((key) => Object.hasOwn(store.values, key));
549
+ const staleRemovedKeys = removedKeys.filter((key) => !schema[key]);
374
550
  const updatedKeys = Object.entries(updates)
375
551
  .filter(([key, value]) => !Object.hasOwn(store.values, key)
376
552
  || stablePluginConfigStringify(store.values[key]) !== stablePluginConfigStringify(value))
@@ -383,7 +559,7 @@ async function applyPluginConfigWriteUnlocked(options) {
383
559
  });
384
560
  if (options.apply !== false
385
561
  && options.scope === 'user'
386
- && options.sharedNativeApplyConfirmed === false
562
+ && options.sharedNativeApplyConfirmed !== true
387
563
  && sharedNativeAffected) {
388
564
  applyTargets ??= (await discoverVisibleTargets({
389
565
  plugin: schemaPlugin,
@@ -395,90 +571,91 @@ async function applyPluginConfigWriteUnlocked(options) {
395
571
  rebuildRuntime: options.rebuildRuntime,
396
572
  })).targets;
397
573
  if (applyTargets.some((target) => target.platform === 'codex')) {
398
- const error = new Error('sharedNativeConfigApplyConfirmationRequired: Applying this user config changes a shared Codex native artifact. Re-run with --yes.');
399
- error.code = 'sharedNativeConfigApplyConfirmationRequired';
400
- throw error;
574
+ throwSharedNativeApplyConfirmationRequired();
401
575
  }
402
576
  }
577
+ if (options.apply !== false
578
+ && options.sharedNativeApplyConfirmed !== true
579
+ && changedKeys.length > 0
580
+ && schemaPlugin.manifest.scripts?.preApply) {
581
+ const error = new Error('preApplyAuthorizationRequired: Applying this config runs plugin preApply. Re-run with --yes.');
582
+ error.code = 'preApplyAuthorizationRequired';
583
+ throw error;
584
+ }
403
585
  if (changedKeys.length > 0) {
404
- await patchPluginConfigStore({
586
+ try {
587
+ const write = await patchPluginConfigStore({
588
+ ...configIdentity,
589
+ pluginName,
590
+ scope: options.scope,
591
+ cwd: options.cwd,
592
+ env: options.env,
593
+ updates: Object.fromEntries(updatedKeys.map((key) => [key, updates[key]])),
594
+ removeKeys: requestedRemoveKeys,
595
+ schema,
596
+ });
597
+ warnings.push(...write.warnings);
598
+ }
599
+ catch (error) {
600
+ throw markConfigWriteFailed(error);
601
+ }
602
+ }
603
+ let effective;
604
+ try {
605
+ effective = summarizeEffectivePluginConfig(await resolveEffectivePluginConfig({
405
606
  ...configIdentity,
406
607
  pluginName,
407
- scope: options.scope,
608
+ manifest: schemaPlugin.manifest,
609
+ targetScope: options.scope,
408
610
  cwd: options.cwd,
409
611
  env: options.env,
410
- updates: Object.fromEntries(updatedKeys.map((key) => [key, updates[key]])),
411
- removeKeys: requestedRemoveKeys,
412
- schema,
413
- });
414
- }
415
- const effective = summarizeEffectivePluginConfig(await resolveEffectivePluginConfig({
416
- ...configIdentity,
417
- pluginName,
418
- manifest: schemaPlugin.manifest,
419
- targetScope: options.scope,
420
- cwd: options.cwd,
421
- env: options.env,
422
- }));
423
- let applied;
424
- if (changedKeys.length === 0) {
425
- applied = {
426
- overallState: 'succeeded',
427
- targetResults: [],
428
- applySkippedReason: 'noConfigChange',
429
- };
612
+ }));
430
613
  }
431
- else if (effective.issues.length > 0) {
432
- applied = {
614
+ catch {
615
+ const apply = unavailableApply('effectiveConfigUnavailable', 'effectiveConfig');
616
+ const otherProjectsMayRequireSync = options.scope === 'user' && changedKeys.length > 0;
617
+ if (otherProjectsMayRequireSync)
618
+ warnings.push(...otherProjectsWarning(options.scope));
619
+ return {
620
+ plugin: pluginName,
621
+ scope: options.scope,
622
+ ...(schemaAccess.schema ? { schema: schemaAccess.schema } : {}),
623
+ updatedKeys,
624
+ removedKeys,
625
+ staleRemovedKeys,
626
+ configWrite: 'succeeded',
433
627
  overallState: 'partial',
434
- targetResults: [],
435
- applySkippedReason: 'invalidConfig',
628
+ apply: publicConfigApplyResult(apply),
629
+ otherProjectsMayRequireSync,
630
+ warnings,
436
631
  };
437
632
  }
438
- else if (options.apply === false) {
439
- applied = {
440
- overallState: 'succeeded',
441
- targetResults: [],
442
- applySkippedReason: 'notRequested',
443
- };
633
+ let apply;
634
+ try {
635
+ apply = changedKeys.length === 0
636
+ ? skippedApply('noConfigChange')
637
+ : staleRemovedKeys.length === changedKeys.length
638
+ ? skippedApply('noEffectiveConfigChange')
639
+ : options.apply === false
640
+ ? skippedApply('notRequested')
641
+ : await applyConfigToVisibleTargets({
642
+ plugin: schemaPlugin,
643
+ scope: options.scope,
644
+ cwd: options.cwd,
645
+ env: options.env ?? process.env,
646
+ applyTargets,
647
+ nativeCliRunner: options.nativeCliRunner,
648
+ reinstallCommandImpl: options.reinstallCommandImpl,
649
+ rebuildRuntime: options.rebuildRuntime,
650
+ noVisibleTargetHasInvalidConfig: effective.issues.length > 0,
651
+ });
444
652
  }
445
- else {
446
- const discovered = await resolveConfigApplyTargets({
447
- plugin: schemaPlugin,
448
- scope: options.scope,
449
- cwd: options.cwd,
450
- env: options.env ?? process.env,
451
- applyTargets: options.applyTargets,
452
- nativeCliRunner: options.nativeCliRunner,
453
- rebuildRuntime: options.rebuildRuntime,
454
- });
455
- applied = await configApplyHasIssues({
456
- plugin: schemaPlugin,
457
- targets: discovered.targets,
458
- cwd: options.cwd,
459
- env: options.env,
460
- knownValidScopes: [options.scope],
461
- }) ? {
462
- overallState: 'partial',
463
- targetResults: [],
464
- applySkippedReason: 'invalidConfig',
465
- } : await reinstallVisibleTargets({
466
- plugin: schemaPlugin,
467
- scope: options.scope,
468
- cwd: options.cwd,
469
- env: options.env ?? process.env,
470
- applyTargets,
471
- nativeCliRunner: options.nativeCliRunner,
472
- reinstallCommandImpl: options.reinstallCommandImpl,
473
- rebuildRuntime: options.rebuildRuntime,
474
- discovered,
475
- });
653
+ catch (error) {
654
+ const failure = error instanceof Error ? error : new Error(String(error));
655
+ throw Object.assign(failure, { configWrite: 'succeeded' });
476
656
  }
477
- const otherProjectsRequireReinstall = options.scope === 'user'
478
- && changedKeys.length > 0
479
- && effective.issues.length === 0
480
- && applied.applySkippedReason !== 'invalidConfig';
481
- if (otherProjectsRequireReinstall)
657
+ const otherProjectsMayRequireSync = options.scope === 'user' && changedKeys.length > 0;
658
+ if (otherProjectsMayRequireSync)
482
659
  warnings.push(...otherProjectsWarning(options.scope));
483
660
  return {
484
661
  plugin: pluginName,
@@ -486,12 +663,12 @@ async function applyPluginConfigWriteUnlocked(options) {
486
663
  ...(schemaAccess.schema ? { schema: schemaAccess.schema } : {}),
487
664
  updatedKeys,
488
665
  removedKeys,
666
+ staleRemovedKeys,
489
667
  effective,
490
668
  configWrite: 'succeeded',
491
- overallState: applied.overallState,
492
- targetResults: applied.targetResults,
493
- ...(applied.applySkippedReason ? { applySkippedReason: applied.applySkippedReason } : {}),
494
- otherProjectsRequireReinstall,
669
+ overallState: overallStateForApply(apply),
670
+ apply: publicConfigApplyResult(apply),
671
+ otherProjectsMayRequireSync,
495
672
  warnings,
496
673
  };
497
674
  }
@@ -500,6 +677,20 @@ export async function applyPluginConfigWrite(options) {
500
677
  if (!requestedPluginName)
501
678
  throw new Error('Plugin name is required for config write.');
502
679
  assertSafePluginConfigSegment(requestedPluginName);
680
+ if (options.scope === 'project') {
681
+ const targetPath = resolvePluginConfigStorePath({
682
+ sourceId: options.plugin?.sourceId,
683
+ pluginName: requestedPluginName,
684
+ scope: 'project',
685
+ cwd: options.cwd,
686
+ env: options.env,
687
+ });
688
+ await assertProjectSharedConfigPathVisible({
689
+ cwd: options.cwd,
690
+ targetPath,
691
+ env: options.env,
692
+ });
693
+ }
503
694
  return withAwHomeMutationLock({
504
695
  env: options.env,
505
696
  token: options.awHomeMutationToken,
@@ -522,6 +713,7 @@ export async function applyPluginConfigWrite(options) {
522
713
  ...(options.plugin.sourceId ? {
523
714
  sourceId: options.plugin.sourceId,
524
715
  sourceIdentity: options.plugin.sourceIdentity,
716
+ logicalIdentity: options.plugin.catalogLogicalIdentity,
525
717
  } : {}),
526
718
  pluginName: options.plugin.manifest.name,
527
719
  manifest: options.plugin.manifest,
@@ -539,6 +731,7 @@ export async function applyPluginConfigWrite(options) {
539
731
  }
540
732
  }
541
733
  let message = redactPluginScriptOutput(error instanceof Error ? error.message : String(error), sensitiveValues);
734
+ message = message.split(options.cwd).join('<project>');
542
735
  for (const scope of ['user', 'project']) {
543
736
  const configPath = resolvePluginConfigStorePath({
544
737
  sourceId: options.plugin?.sourceId,
@@ -556,6 +749,13 @@ export async function applyPluginConfigWrite(options) {
556
749
  const safeError = new Error(message);
557
750
  const code = error.code;
558
751
  safeError.code = typeof code === 'string' ? code : 'configApplyFailed';
752
+ const configWrite = error.configWrite;
753
+ if (configWrite === 'succeeded' || configWriteStateForError(error) === 'failed') {
754
+ safeError.configWrite = configWrite === 'succeeded' ? 'succeeded' : 'failed';
755
+ }
756
+ if (error && typeof error === 'object' && 'operationDiagnostic' in error) {
757
+ safeError.operationDiagnostic = error.operationDiagnostic;
758
+ }
559
759
  throw safeError;
560
760
  }
561
761
  },
@@ -563,19 +763,14 @@ export async function applyPluginConfigWrite(options) {
563
763
  }
564
764
  async function resetPluginConfigWithHelperUnlocked(options) {
565
765
  const pluginName = assertSafePluginConfigSegment(options.pluginName);
566
- const schemaAccess = options.plugin ? await resolvePluginConfigSchemaAccess({
567
- pluginName,
568
- currentPlugin: options.plugin,
569
- scope: options.scope,
570
- cwd: options.cwd,
571
- env: options.env,
572
- }) : undefined;
573
766
  let configIdentity = options.plugin?.sourceId ? {
574
767
  sourceId: options.plugin.sourceId,
575
768
  sourceIdentity: options.plugin.sourceIdentity,
769
+ logicalIdentity: options.plugin.catalogLogicalIdentity,
576
770
  } : options.sourceId ? {
577
771
  sourceId: options.sourceId,
578
772
  sourceIdentity: options.sourceIdentity,
773
+ logicalIdentity: options.logicalIdentity,
579
774
  } : {};
580
775
  if (options.sourceId && !options.sourceIdentity) {
581
776
  try {
@@ -586,10 +781,15 @@ async function resetPluginConfigWithHelperUnlocked(options) {
586
781
  cwd: options.cwd,
587
782
  env: options.env,
588
783
  });
589
- if (identity)
784
+ if (identity?.binding.kind === 'source')
785
+ configIdentity = {
786
+ sourceId: options.sourceId,
787
+ sourceIdentity: identity.binding.sourceIdentity,
788
+ };
789
+ if (identity?.binding.kind === 'catalog')
590
790
  configIdentity = {
591
791
  sourceId: options.sourceId,
592
- sourceIdentity: identity.sourceIdentity,
792
+ logicalIdentity: identity.binding.logicalIdentity,
593
793
  };
594
794
  }
595
795
  catch {
@@ -597,6 +797,7 @@ async function resetPluginConfigWithHelperUnlocked(options) {
597
797
  }
598
798
  }
599
799
  let removedKeys = [];
800
+ let removedKeysKnown = false;
600
801
  try {
601
802
  const store = await readPluginConfigStore({
602
803
  ...configIdentity,
@@ -606,92 +807,110 @@ async function resetPluginConfigWithHelperUnlocked(options) {
606
807
  env: options.env,
607
808
  });
608
809
  removedKeys = collectRemovedConfigKeys(store.values);
810
+ removedKeysKnown = store.state !== 'invalid';
609
811
  }
610
812
  catch {
611
813
  // Reset is the final recovery boundary and does not require a readable store.
612
814
  }
613
815
  const warnings = [];
614
- const reset = await resetPluginConfigStore({
615
- ...configIdentity,
616
- pluginName,
617
- scope: options.scope,
618
- cwd: options.cwd,
619
- env: options.env,
620
- });
621
- let applied = {
622
- overallState: 'succeeded',
623
- targetResults: [],
624
- applySkippedReason: reset.deleted ? 'notRequested' : 'noConfigChange',
625
- };
816
+ const sharedNativeAffected = options.plugin
817
+ && (removedKeysKnown
818
+ ? changedKeysAffectSharedNativeTarget({
819
+ plugin: options.plugin,
820
+ changedKeys: removedKeys,
821
+ })
822
+ : pluginHasSharedNativeRefreshKeys(options.plugin));
823
+ if (options.plugin
824
+ && options.apply !== false
825
+ && options.scope === 'user'
826
+ && options.sharedNativeApplyConfirmed !== true
827
+ && sharedNativeAffected) {
828
+ const discovered = await resolveConfigApplyTargets({
829
+ plugin: options.plugin,
830
+ scope: options.scope,
831
+ cwd: options.cwd,
832
+ env: options.env ?? process.env,
833
+ applyTargets: options.applyTargets,
834
+ nativeCliRunner: options.nativeCliRunner,
835
+ rebuildRuntime: options.rebuildRuntime,
836
+ });
837
+ if (discovered.targets.some((target) => target.platform === 'codex')) {
838
+ throwSharedNativeApplyConfirmationRequired();
839
+ }
840
+ }
841
+ let reset;
842
+ try {
843
+ reset = await resetPluginConfigStore({
844
+ ...configIdentity,
845
+ pluginName,
846
+ scope: options.scope,
847
+ cwd: options.cwd,
848
+ env: options.env,
849
+ });
850
+ }
851
+ catch (error) {
852
+ throw markConfigWriteFailed(error);
853
+ }
854
+ let schemaAccess;
855
+ let apply = reset.deleted ? skippedApply('notRequested') : skippedApply('noConfigChange');
626
856
  let effective;
627
- if (schemaAccess?.plugin) {
628
- if (schemaAccess.plugin.manifest.config?.fields) {
857
+ if (options.plugin) {
858
+ try {
859
+ schemaAccess = await resolvePluginConfigSchemaAccess({
860
+ pluginName,
861
+ currentPlugin: options.plugin,
862
+ scope: options.scope,
863
+ cwd: options.cwd,
864
+ env: options.env,
865
+ });
866
+ }
867
+ catch {
868
+ if (reset.deleted && options.apply !== false) {
869
+ apply = unavailableApply('sourceUnavailable', 'source');
870
+ }
871
+ }
872
+ const schemaPlugin = schemaAccess?.plugin;
873
+ if (schemaPlugin?.manifest.config?.fields) {
629
874
  try {
630
875
  effective = summarizeEffectivePluginConfig(await resolveEffectivePluginConfig({
631
876
  ...configIdentity,
632
877
  pluginName,
633
- manifest: schemaAccess.plugin.manifest,
878
+ manifest: schemaPlugin.manifest,
634
879
  targetScope: options.scope,
635
880
  cwd: options.cwd,
636
881
  env: options.env,
637
882
  }));
638
883
  }
639
884
  catch {
640
- if (options.apply !== false) {
641
- applied = {
642
- overallState: 'partial',
643
- targetResults: [],
644
- applySkippedReason: 'invalidConfig',
645
- };
885
+ if (reset.deleted && options.apply !== false) {
886
+ apply = unavailableApply('effectiveConfigUnavailable', 'effectiveConfig');
646
887
  }
647
888
  }
889
+ if (reset.deleted && options.apply !== false && apply.state === 'skipped') {
890
+ apply = await applyConfigToVisibleTargets({
891
+ plugin: schemaPlugin,
892
+ scope: options.scope,
893
+ cwd: options.cwd,
894
+ env: options.env ?? process.env,
895
+ applyTargets: options.applyTargets,
896
+ nativeCliRunner: options.nativeCliRunner,
897
+ reinstallCommandImpl: options.reinstallCommandImpl,
898
+ rebuildRuntime: options.rebuildRuntime,
899
+ noVisibleTargetHasInvalidConfig: (effective?.issues.length ?? 0) > 0,
900
+ });
901
+ }
648
902
  }
649
- if (reset.deleted && effective && effective.issues.length > 0) {
650
- applied = {
651
- overallState: 'partial',
652
- targetResults: [],
653
- applySkippedReason: 'invalidConfig',
654
- };
655
- }
656
- else if (reset.deleted && options.apply !== false && applied.applySkippedReason !== 'invalidConfig') {
657
- const discovered = await resolveConfigApplyTargets({
658
- plugin: schemaAccess.plugin,
659
- scope: options.scope,
660
- cwd: options.cwd,
661
- env: options.env ?? process.env,
662
- applyTargets: options.applyTargets,
663
- nativeCliRunner: options.nativeCliRunner,
664
- rebuildRuntime: options.rebuildRuntime,
665
- });
666
- applied = await configApplyHasIssues({
667
- plugin: schemaAccess.plugin,
668
- targets: discovered.targets,
669
- cwd: options.cwd,
670
- env: options.env,
671
- knownValidScopes: effective ? [options.scope] : undefined,
672
- }) ? {
673
- overallState: 'partial',
674
- targetResults: [],
675
- applySkippedReason: 'invalidConfig',
676
- } : await reinstallVisibleTargets({
677
- plugin: schemaAccess.plugin,
678
- scope: options.scope,
679
- cwd: options.cwd,
680
- env: options.env ?? process.env,
681
- applyTargets: options.applyTargets,
682
- nativeCliRunner: options.nativeCliRunner,
683
- reinstallCommandImpl: options.reinstallCommandImpl,
684
- rebuildRuntime: options.rebuildRuntime,
685
- discovered,
686
- });
903
+ else if (reset.deleted && options.apply !== false && apply.state === 'skipped') {
904
+ apply = unavailableApply('schemaUnavailable', 'schema');
687
905
  }
688
906
  }
689
- const otherProjectsRequireReinstall = Boolean(schemaAccess?.plugin)
690
- && options.scope === 'user'
691
- && reset.deleted
692
- && (effective?.issues.length ?? 0) === 0
693
- && applied.applySkippedReason !== 'invalidConfig';
694
- if (otherProjectsRequireReinstall)
907
+ else if (reset.deleted && options.apply !== false) {
908
+ apply = options.pluginError
909
+ ? unavailableApply('sourceUnavailable', 'source')
910
+ : unavailableApply('schemaUnavailable', 'schema');
911
+ }
912
+ const otherProjectsMayRequireSync = options.scope === 'user' && reset.deleted;
913
+ if (otherProjectsMayRequireSync)
695
914
  warnings.push(...otherProjectsWarning(options.scope));
696
915
  return {
697
916
  plugin: pluginName,
@@ -704,10 +923,9 @@ async function resetPluginConfigWithHelperUnlocked(options) {
704
923
  removedKeys,
705
924
  ...(effective ? { effective } : {}),
706
925
  configWrite: 'succeeded',
707
- overallState: applied.overallState,
708
- targetResults: applied.targetResults,
709
- ...(applied.applySkippedReason ? { applySkippedReason: applied.applySkippedReason } : {}),
710
- otherProjectsRequireReinstall,
926
+ overallState: overallStateForApply(apply),
927
+ apply: publicConfigApplyResult(apply),
928
+ otherProjectsMayRequireSync,
711
929
  warnings,
712
930
  };
713
931
  }
@@ -751,9 +969,11 @@ export async function describeResetAffectedFields(options) {
751
969
  ...(options.plugin?.sourceId ? {
752
970
  sourceId: options.plugin.sourceId,
753
971
  sourceIdentity: options.plugin.sourceIdentity,
972
+ logicalIdentity: options.plugin.catalogLogicalIdentity,
754
973
  } : options.sourceId ? {
755
974
  sourceId: options.sourceId,
756
975
  sourceIdentity: options.sourceIdentity,
976
+ logicalIdentity: options.logicalIdentity,
757
977
  } : {}),
758
978
  pluginName: options.pluginName,
759
979
  scope: options.scope,