@lesliechan721/aw 0.1.0-beta.60 → 0.1.0-beta.62

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 (74) hide show
  1. package/dist/authoring/scripts/validate-plugin.mjs +56 -9
  2. package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
  3. package/dist/scripts/aw-skill-eval-materializer.js +3 -0
  4. package/dist/scripts/aw-skill-eval-materializer.js.map +1 -1
  5. package/dist/scripts/test-plugin-scripts.js +20 -1
  6. package/dist/scripts/test-plugin-scripts.js.map +1 -1
  7. package/dist/src/commands/aw-capabilities.d.ts +1 -1
  8. package/dist/src/commands/aw-capabilities.js +1 -0
  9. package/dist/src/commands/aw-capabilities.js.map +1 -1
  10. package/dist/src/commands/rebuild-command.js +25 -26
  11. package/dist/src/commands/rebuild-command.js.map +1 -1
  12. package/dist/src/commands/rebuild-integration.d.ts +2 -0
  13. package/dist/src/commands/rebuild-integration.js +23 -7
  14. package/dist/src/commands/rebuild-integration.js.map +1 -1
  15. package/dist/src/commands/review-inspection.js +38 -5
  16. package/dist/src/commands/review-inspection.js.map +1 -1
  17. package/dist/src/commands/review-preparation.js +1 -0
  18. package/dist/src/commands/review-preparation.js.map +1 -1
  19. package/dist/src/generators/local-plugin.js +7 -5
  20. package/dist/src/generators/local-plugin.js.map +1 -1
  21. package/dist/src/portable/materializer.js +3 -0
  22. package/dist/src/portable/materializer.js.map +1 -1
  23. package/dist/src/review/review-profile.d.ts +1 -0
  24. package/dist/src/review/review-profile.js +44 -8
  25. package/dist/src/review/review-profile.js.map +1 -1
  26. package/dist/src/review/review-selection.js +19 -6
  27. package/dist/src/review/review-selection.js.map +1 -1
  28. package/dist/src/review/skill-materialization.d.ts +1 -0
  29. package/dist/src/review/skill-materialization.js +2 -0
  30. package/dist/src/review/skill-materialization.js.map +1 -1
  31. package/dist/src/review/source-binding.d.ts +5 -0
  32. package/dist/src/review/source-binding.js +83 -22
  33. package/dist/src/review/source-binding.js.map +1 -1
  34. package/dist/src/tui/config-leaf-editor.d.ts +24 -0
  35. package/dist/src/tui/config-leaf-editor.js +19 -7
  36. package/dist/src/tui/config-leaf-editor.js.map +1 -1
  37. package/dist/src/tui/config-references.d.ts +1 -0
  38. package/dist/src/tui/config-references.js +8 -1
  39. package/dist/src/tui/config-references.js.map +1 -1
  40. package/dist/src/tui/console-app-v4.js +77 -17
  41. package/dist/src/tui/console-app-v4.js.map +1 -1
  42. package/dist/src/tui/controller-runtime.d.ts +1 -1
  43. package/dist/src/tui/controller-runtime.js +119 -91
  44. package/dist/src/tui/controller-runtime.js.map +1 -1
  45. package/dist/src/tui/controller.d.ts +3 -0
  46. package/dist/src/tui/controller.js +19 -0
  47. package/dist/src/tui/controller.js.map +1 -1
  48. package/dist/src/tui/model.js +1 -1
  49. package/dist/src/tui/model.js.map +1 -1
  50. package/dist/src/tui/operation-review-planner.js +13 -8
  51. package/dist/src/tui/operation-review-planner.js.map +1 -1
  52. package/dist/src/utils/artifact-renderer.d.ts +8 -1
  53. package/dist/src/utils/artifact-renderer.js +25 -7
  54. package/dist/src/utils/artifact-renderer.js.map +1 -1
  55. package/dist/src/utils/managed-command-materialization.d.ts +2 -0
  56. package/dist/src/utils/managed-command-materialization.js +2 -1
  57. package/dist/src/utils/managed-command-materialization.js.map +1 -1
  58. package/dist/src/utils/plugin-config-impact.d.ts +15 -0
  59. package/dist/src/utils/plugin-config-impact.js +132 -24
  60. package/dist/src/utils/plugin-config-impact.js.map +1 -1
  61. package/dist/src/utils/plugin-config-references.d.ts +80 -0
  62. package/dist/src/utils/plugin-config-references.js +340 -0
  63. package/dist/src/utils/plugin-config-references.js.map +1 -0
  64. package/dist/src/utils/plugin-config-write.js +148 -31
  65. package/dist/src/utils/plugin-config-write.js.map +1 -1
  66. package/dist/src/utils/plugin-config.d.ts +10 -2
  67. package/dist/src/utils/plugin-config.js +53 -4
  68. package/dist/src/utils/plugin-config.js.map +1 -1
  69. package/dist/src/utils/plugin-scripts.d.ts +1 -0
  70. package/dist/src/utils/plugin-scripts.js +1 -1
  71. package/dist/src/utils/plugin-scripts.js.map +1 -1
  72. package/dist/src/utils/runtime-config.js +1 -0
  73. package/dist/src/utils/runtime-config.js.map +1 -1
  74. package/package.json +3 -3
@@ -14,7 +14,7 @@ export interface TuiControllerRuntimeTestHooks {
14
14
  }
15
15
  export declare function setTuiControllerRuntimeTestHooksForTests(hooks: TuiControllerRuntimeTestHooks | undefined): void;
16
16
  export declare function statusTargetFingerprint(targets: StatusScopedTarget[], revisions?: StatusTargetRevision[]): string;
17
- export declare function configAffectedStatusTargets(targets: StatusV8Target[], pluginId: string, configScope: 'user' | 'project'): StatusScopedTarget[];
17
+ export declare function configAffectedStatusTargets(targets: StatusV8Target[], pluginId: string, configScope: 'user' | 'project', consumerPluginIds?: readonly string[]): StatusScopedTarget[];
18
18
  export declare function createTuiControllerDependencies(context: CliExecutionContext, progressFeed?: RebuildProgressFeed, options?: {
19
19
  now?: () => number;
20
20
  inventoryCatalogSourceReferences?: typeof inventoryCatalogSourceReferences;
@@ -12,12 +12,12 @@ import { createCodexNativeObservationSession, } from '../utils/codex-native-obse
12
12
  import { prepareNativeCliExecution } from '../utils/native-cli.js';
13
13
  import { readCatalogSourcesConfigSnapshot, recoverInvalidCatalogSourcesConfig, } from '../utils/catalog-sources.js';
14
14
  import { withResolvedCatalogPlugin, withResolvedMultiSourceCatalog, formatPluginId, parsePluginId, } from '../utils/multi-source-catalog.js';
15
- import { coercePluginConfigUpdates, inspectPluginConfigResetTarget, listNamespacedPluginConfigStoreIdentities, readPluginConfigStore, resolveConfigRead, resolveEffectivePluginConfig, resolveEffectivePluginConfigFromStores, resolveAwProjectRoot, resolvePluginConfigStorePath, } from '../utils/plugin-config.js';
15
+ import { coercePluginConfigUpdates, inspectPluginConfigResetTarget, listNamespacedPluginConfigStoreIdentities, readPluginConfigStore, resolveConfigRead, resolveEffectivePluginConfig, resolveEffectivePluginConfigFromStores, resolvePluginConfigReferenceContext, resolveAwProjectRoot, resolvePluginConfigStorePath, } from '../utils/plugin-config.js';
16
16
  import { assertProjectSharedConfigPathVisible } from '../utils/project-boundary.js';
17
17
  import { calculatePluginIntentDigest, readPluginIntentState, } from '../utils/plugin-intent-state.js';
18
18
  import { applyPluginConfigWrite, replayConfigRuntimeWrites, resolveConfigPreApplyAuthorization, resetPluginConfigWithHelper, } from '../utils/plugin-config-write.js';
19
- import { analyzePluginConfigMutationImpact, pluginSharedNativeConfigTargets } from '../utils/plugin-config-impact.js';
20
- import { discoverInstalledPluginManagedCommandPackages } from '../utils/managed-command-materialization.js';
19
+ import { analyzePluginConfigMutationImpact, discoverPluginConfigManagedCommandPackages, pluginConfigTargetRenderScopes, pluginSharedNativeConfigTargets } from '../utils/plugin-config-impact.js';
20
+ import { collectPluginConfigReferenceEvidence, resolvePluginConfigReferenceConsumers, resolvePluginConfigReferencePlugins } from '../utils/plugin-config-references.js';
21
21
  import { createBatchIntentCompatiblePlanFingerprint } from '../commands/operation-plan.js';
22
22
  import { inventoryCatalogSourceReferences } from '../utils/catalog-source-references.js';
23
23
  import { operationEvidenceMatches, operationEvidenceFingerprint, TuiConfigInvalidStoreError, TuiController, TuiOperationBlockedError, } from './controller.js';
@@ -115,28 +115,46 @@ export function statusTargetFingerprint(targets, revisions = []) {
115
115
  .localeCompare([right.pluginId, right.platform, right.scope].join('\0'), 'en')),
116
116
  });
117
117
  }
118
- export function configAffectedStatusTargets(targets, pluginId, configScope) {
118
+ export function configAffectedStatusTargets(targets, pluginId, configScope, consumerPluginIds = []) {
119
119
  const affected = new Map();
120
+ const selected = new Set([pluginId, ...consumerPluginIds]);
120
121
  for (const target of flattenStatusTargets(targets)) {
121
122
  const intent = statusTargetIntent(target);
122
- if (target.pluginId !== pluginId || !intent.enabled)
123
+ if (!selected.has(target.pluginId) || !intent.enabled)
123
124
  continue;
124
125
  for (const scope of intent.scopes) {
125
126
  if (configScope === 'project' && scope !== 'project')
126
127
  continue;
127
- affected.set(`${target.platform}\0${scope}`, { ...target, scope });
128
+ affected.set(`${target.pluginId}\0${target.platform}\0${scope}`, { ...target, scope });
128
129
  }
129
130
  }
130
131
  return [...affected.values()]
131
- .sort((left, right) => `${left.platform}\0${left.scope}`
132
- .localeCompare(`${right.platform}\0${right.scope}`, 'en'));
132
+ .sort((left, right) => `${left.pluginId}\0${left.platform}\0${left.scope}`
133
+ .localeCompare(`${right.pluginId}\0${right.platform}\0${right.scope}`, 'en'));
133
134
  }
134
- function configRetrySharedNativeRenderTargets(plugin) {
135
- return pluginSharedNativeConfigTargets(plugin);
135
+ async function configRetrySharedNativeRenderTargets(plugin, targets, env) {
136
+ const plugins = await resolvePluginConfigReferenceConsumers({ plugin, env });
137
+ return plugins.flatMap((consumer) => pluginSharedNativeConfigTargets(consumer).filter((shared) => targets.some((target) => (target.pluginName ?? plugin.manifest.name) === consumer.manifest.name
138
+ && target.platform === (shared.platform ?? 'codex'))));
139
+ }
140
+ async function configRetryStoreDigest(options) {
141
+ const plugins = await resolvePluginConfigReferencePlugins({ sourceId: options.plugin.sourceId,
142
+ sourceIdentity: options.plugin.sourceIdentity, logicalIdentity: options.plugin.catalogLogicalIdentity, env: options.env });
143
+ const byName = new Map([...plugins, options.plugin].map((plugin) => [plugin.manifest.name, plugin]));
144
+ const profiles = [{ pluginName: options.plugin.manifest.name, scope: options.scope },
145
+ ...options.targets.flatMap((target) => {
146
+ const plugin = byName.get(target.pluginName);
147
+ if (!plugin)
148
+ throw operationReviewStale('重试目标的插件定义已变化。');
149
+ return pluginConfigTargetRenderScopes(plugin, target).map((scope) => ({ pluginName: target.pluginName, scope }));
150
+ }),
151
+ ...options.commandPackages.map(({ producer }) => ({ pluginName: producer.pluginName, scope: producer.scope })),
152
+ ...options.preApplyAuthorization.map(({ pluginName, scope }) => ({ pluginName, scope }))];
153
+ return digest(await collectPluginConfigReferenceEvidence({ ...options, profiles, plugins }));
136
154
  }
137
155
  function configImpactVisibleTargets(pluginName, targets) {
138
156
  return targets.map((target) => ({
139
- pluginName,
157
+ pluginName: target.pluginName ?? pluginName,
140
158
  platform: target.platform,
141
159
  scope: target.scope,
142
160
  }));
@@ -2135,6 +2153,15 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2135
2153
  catalogOperationByEvidence.set(evidence, catalogOperation);
2136
2154
  return evidence;
2137
2155
  }
2156
+ const configReferencePluginIds = intent.kind === 'configSave'
2157
+ ? await withResolvedCatalogPlugin({
2158
+ selector: intent.pluginId, cliVersion: packageInfo.version, env: context.env,
2159
+ ...(catalogOperation ? { operationContext: catalogOperation } : {}),
2160
+ ...(signal ? { signal } : {}),
2161
+ consume: async ({ plugin }) => (await resolvePluginConfigReferenceConsumers({ plugin, env: context.env }))
2162
+ .map((entry) => entry.pluginId ?? `${entry.sourceId}/${entry.manifest.name}`),
2163
+ })
2164
+ : [];
2138
2165
  if (preparation && intent.kind === 'configSave') {
2139
2166
  if (!sessionStatusResult || !catalogOperation) {
2140
2167
  throw operationReviewStale('当前 TUI session 没有可复用的设置证据。');
@@ -2145,7 +2172,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2145
2172
  if (configSnapshot.digest !== sessionStatusResult.payload.catalog.configDigest) {
2146
2173
  throw operationReviewStale('准备设置确认期间来源配置发生变化。');
2147
2174
  }
2148
- const relevantTargets = configAffectedStatusTargets(sessionStatusResult.payload.targets, intent.pluginId, intent.scope);
2175
+ const relevantTargets = configAffectedStatusTargets(sessionStatusResult.payload.targets, intent.pluginId, intent.scope, configReferencePluginIds);
2149
2176
  const preparedCatalogOperation = catalogOperation;
2150
2177
  const selected = await withResolvedCatalogPlugin({
2151
2178
  selector: intent.pluginId,
@@ -2186,43 +2213,37 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2186
2213
  ? configImpactVisibleTargets(plugin.manifest.name, relevantTargets)
2187
2214
  : impact.affectedTargets;
2188
2215
  const commandPackages = impact?.affectedCommandPackages
2189
- ?? (await discoverInstalledPluginManagedCommandPackages({ plugin, scope: intent.scope,
2216
+ ?? (await discoverPluginConfigManagedCommandPackages({ plugin, scope: intent.scope,
2190
2217
  cwd: context.cwd, env: context.env ?? process.env, platformTargets: affectedTargets })).packages;
2218
+ const preApplyAuthorization = configIntentRequestsApply(intent)
2219
+ ? (await resolveConfigPreApplyAuthorization({
2220
+ plugin,
2221
+ scope: intent.scope,
2222
+ cwd: context.cwd,
2223
+ env: context.env,
2224
+ applyTargets: affectedTargets,
2225
+ nativeCliRunner: context.nativeCliRunner,
2226
+ rebuildRuntime: {
2227
+ catalogOperationContext: preparedCatalogOperation,
2228
+ expectedGenerationSetDigest: preparedCatalogOperation.generationSetDigest,
2229
+ inventoryCatalogSourceReferences: operationInventory,
2230
+ },
2231
+ })).targets
2232
+ : [];
2191
2233
  return {
2192
2234
  pluginName: plugin.manifest.name,
2193
2235
  source: sourceEvidenceForPlugin(source, plugin.manifest.name),
2194
2236
  impact,
2195
2237
  commandPackages,
2196
- preApplyAuthorization: configIntentRequestsApply(intent)
2197
- ? (await resolveConfigPreApplyAuthorization({
2198
- plugin,
2199
- scope: intent.scope,
2200
- cwd: context.cwd,
2201
- env: context.env,
2202
- applyTargets: affectedTargets,
2203
- nativeCliRunner: context.nativeCliRunner,
2204
- rebuildRuntime: {
2205
- catalogOperationContext: preparedCatalogOperation,
2206
- expectedGenerationSetDigest: preparedCatalogOperation.generationSetDigest,
2207
- inventoryCatalogSourceReferences: operationInventory,
2208
- },
2209
- })).targets
2210
- : [],
2238
+ preApplyAuthorization,
2239
+ retryStoreDigest: intent.retryApply ? await configRetryStoreDigest({ plugin, scope: intent.scope,
2240
+ targets: affectedTargets, commandPackages, preApplyAuthorization, cwd: context.cwd, env: context.env }) : undefined,
2211
2241
  sharedNativeRenderTargets: intent.retryApply
2212
- ? configRetrySharedNativeRenderTargets(plugin)
2242
+ ? await configRetrySharedNativeRenderTargets(plugin, affectedTargets, context.env)
2213
2243
  : impact.sharedNativeRenderTargets,
2214
2244
  };
2215
2245
  },
2216
2246
  });
2217
- const retryStore = intent.retryApply ? await readPluginConfigStore({
2218
- sourceId: selected.source.sourceId,
2219
- sourceIdentity: selected.source.sourceIdentity,
2220
- logicalIdentity: selected.source.logicalIdentity,
2221
- pluginName: selected.pluginName,
2222
- scope: intent.scope,
2223
- cwd: context.cwd,
2224
- env: context.env,
2225
- }) : undefined;
2226
2247
  signal?.throwIfAborted();
2227
2248
  const relevantRevisions = (sessionStatusResult.targetRevisions ?? []).filter((revision) => relevantTargets.some((target) => target.platform === revision.platform
2228
2249
  && target.scope === revision.scope
@@ -2231,7 +2252,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2231
2252
  const evidence = {
2232
2253
  catalog: {
2233
2254
  configDigest: sessionStatusResult.payload.catalog.configDigest,
2234
- compositeDigest: sessionStatusResult.payload.catalog.compositeDigest,
2255
+ compositeDigest: preparedCatalogOperation.catalog.compositeDigest,
2235
2256
  ...(catalogOperation ? { generationSetDigest: catalogOperation.generationSetDigest } : {}),
2236
2257
  },
2237
2258
  ...(selected.source ? { source: selected.source } : {}),
@@ -2240,12 +2261,12 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2240
2261
  scope: intent.scope,
2241
2262
  ...(selected.source?.manifestDigest ? { schemaIdentity: selected.source.manifestDigest } : {}),
2242
2263
  storeDigest: selected.impact?.storeDigest
2243
- ?? digest({ exists: retryStore?.exists, rawDigest: retryStore?.rawDigest }),
2264
+ ?? selected.retryStoreDigest,
2244
2265
  impactState: selected.impact?.impactState ?? 'known',
2245
2266
  ...(selected.impact?.noEffectiveChange ? { noEffectiveChange: true } : {}),
2246
2267
  ...(selected.commandPackages.length ? { commandPackages: selected.commandPackages } : {}),
2247
2268
  affectedTargets: (selected.impact?.affectedTargets
2248
- ?? relevantTargets).map(({ platform, scope }) => ({ platform, scope })),
2269
+ ?? relevantTargets).map(({ pluginName, platform, scope }) => ({ pluginName, platform, scope })),
2249
2270
  ...(selected.preApplyAuthorization.length > 0
2250
2271
  ? { preApplyAuthorization: selected.preApplyAuthorization }
2251
2272
  : {}),
@@ -2262,7 +2283,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2262
2283
  const statusCatalogOperation = catalogOperation
2263
2284
  ?? (!freshCatalog ? sessionCatalogOperationContext : undefined);
2264
2285
  const status = await statusCommandV8({
2265
- plugins: [...new Set([intent.pluginId,
2286
+ plugins: [...new Set([intent.pluginId, ...configReferencePluginIds,
2266
2287
  ...(intent.kind === 'pluginWrite' && intent.originIssue?.consumerPluginId
2267
2288
  ? [intent.originIssue.consumerPluginId] : [])])],
2268
2289
  ...('platform' in intent ? { platform: intent.platform } : {}),
@@ -2299,7 +2320,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2299
2320
  let operationPlan;
2300
2321
  await preparation?.reporter.emit('catalog');
2301
2322
  const configVisibleTargets = intent.kind === 'configSave'
2302
- ? configAffectedStatusTargets(status.payload.targets, intent.pluginId, intent.scope)
2323
+ ? configAffectedStatusTargets(status.payload.targets, intent.pluginId, intent.scope, configReferencePluginIds)
2303
2324
  : [];
2304
2325
  const selected = await withResolvedCatalogPlugin({
2305
2326
  selector: intent.pluginId,
@@ -2339,38 +2360,46 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2339
2360
  },
2340
2361
  })
2341
2362
  : undefined;
2363
+ const affectedTargets = intent.kind === 'configSave'
2364
+ ? intent.retryApply ? configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets) : impact.affectedTargets
2365
+ : [];
2366
+ const commandPackages = impact?.affectedCommandPackages
2367
+ ?? (intent.kind === 'configSave' ? (await discoverPluginConfigManagedCommandPackages({
2368
+ plugin, scope: intent.scope, cwd: context.cwd, env: context.env ?? process.env,
2369
+ platformTargets: configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets),
2370
+ })).packages : []);
2371
+ const preApplyAuthorization = intent.kind === 'configSave'
2372
+ && configIntentRequestsApply(intent)
2373
+ ? (await resolveConfigPreApplyAuthorization({
2374
+ plugin,
2375
+ scope: intent.scope,
2376
+ cwd: context.cwd,
2377
+ env: context.env,
2378
+ applyTargets: intent.retryApply
2379
+ ? configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets)
2380
+ : impact.affectedTargets,
2381
+ nativeCliRunner: context.nativeCliRunner,
2382
+ rebuildRuntime: {
2383
+ ...(catalogOperation ? { catalogOperationContext: catalogOperation } : {}),
2384
+ ...(catalogOperation?.generationSetDigest
2385
+ ? { expectedGenerationSetDigest: catalogOperation.generationSetDigest }
2386
+ : {}),
2387
+ inventoryCatalogSourceReferences: operationInventory,
2388
+ },
2389
+ })).targets
2390
+ : [];
2342
2391
  return {
2343
2392
  pluginName: plugin.manifest.name,
2344
2393
  source: sourceEvidenceForPlugin(source, plugin.manifest.name),
2345
2394
  impact,
2346
- commandPackages: impact?.affectedCommandPackages
2347
- ?? (intent.kind === 'configSave' ? (await discoverInstalledPluginManagedCommandPackages({
2348
- plugin, scope: intent.scope, cwd: context.cwd, env: context.env ?? process.env,
2349
- platformTargets: configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets),
2350
- })).packages : []),
2351
- preApplyAuthorization: intent.kind === 'configSave'
2352
- && configIntentRequestsApply(intent)
2353
- ? (await resolveConfigPreApplyAuthorization({
2354
- plugin,
2355
- scope: intent.scope,
2356
- cwd: context.cwd,
2357
- env: context.env,
2358
- applyTargets: intent.retryApply
2359
- ? configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets)
2360
- : impact.affectedTargets,
2361
- nativeCliRunner: context.nativeCliRunner,
2362
- rebuildRuntime: {
2363
- ...(catalogOperation ? { catalogOperationContext: catalogOperation } : {}),
2364
- ...(catalogOperation?.generationSetDigest
2365
- ? { expectedGenerationSetDigest: catalogOperation.generationSetDigest }
2366
- : {}),
2367
- inventoryCatalogSourceReferences: operationInventory,
2368
- },
2369
- })).targets
2370
- : [],
2395
+ commandPackages,
2396
+ preApplyAuthorization,
2397
+ retryStoreDigest: intent.kind === 'configSave' && intent.retryApply
2398
+ ? await configRetryStoreDigest({ plugin, scope: intent.scope, targets: affectedTargets,
2399
+ commandPackages, preApplyAuthorization, cwd: context.cwd, env: context.env }) : undefined,
2371
2400
  sharedNativeRenderTargets: intent.kind === 'configSave'
2372
2401
  ? intent.retryApply
2373
- ? configRetrySharedNativeRenderTargets(plugin)
2402
+ ? await configRetrySharedNativeRenderTargets(plugin, configImpactVisibleTargets(plugin.manifest.name, configVisibleTargets), context.env)
2374
2403
  : impact.sharedNativeRenderTargets
2375
2404
  : [],
2376
2405
  };
@@ -2489,7 +2518,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2489
2518
  const evidence = {
2490
2519
  catalog: {
2491
2520
  configDigest: status.payload.catalog.configDigest,
2492
- compositeDigest: status.payload.catalog.compositeDigest,
2521
+ compositeDigest: intent.kind === 'configSave' ? catalogOperation.catalog.compositeDigest : status.payload.catalog.compositeDigest,
2493
2522
  ...(catalogOperation
2494
2523
  ? { generationSetDigest: catalogOperation.generationSetDigest }
2495
2524
  : {}),
@@ -2503,31 +2532,22 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2503
2532
  };
2504
2533
  if (intent.kind === 'configSave') {
2505
2534
  const impact = 'impact' in selected ? selected.impact : undefined;
2506
- const retryStore = intent.retryApply ? await readPluginConfigStore({
2507
- sourceId: selected.source.sourceId,
2508
- sourceIdentity: selected.source.sourceIdentity,
2509
- ...('logicalIdentity' in selected.source
2510
- ? { logicalIdentity: selected.source.logicalIdentity }
2511
- : {}),
2512
- pluginName: selected.pluginName,
2513
- scope: intent.scope,
2514
- cwd: context.cwd,
2515
- env: context.env,
2516
- }) : undefined;
2535
+ const storeDigest = impact?.storeDigest ?? ('retryStoreDigest' in selected ? selected.retryStoreDigest : undefined);
2536
+ if (!storeDigest)
2537
+ throw operationReviewStale('设置操作缺少实际配置输入证据。');
2517
2538
  signal?.throwIfAborted();
2518
2539
  evidence.config = {
2519
2540
  scope: intent.scope,
2520
2541
  ...('manifestDigest' in selected.source
2521
2542
  ? { schemaIdentity: selected.source.manifestDigest }
2522
2543
  : {}),
2523
- storeDigest: impact?.storeDigest
2524
- ?? digest({ exists: retryStore?.exists, rawDigest: retryStore?.rawDigest }),
2544
+ storeDigest,
2525
2545
  impactState: impact?.impactState ?? 'known',
2526
2546
  ...(impact?.noEffectiveChange ? { noEffectiveChange: true } : {}),
2527
2547
  ...('commandPackages' in selected && selected.commandPackages.length
2528
2548
  ? { commandPackages: selected.commandPackages } : {}),
2529
2549
  affectedTargets: (impact?.affectedTargets
2530
- ?? evidenceTargets).map(({ platform, scope }) => ({ platform, scope })),
2550
+ ?? evidenceTargets).map(({ pluginName, platform, scope }) => ({ pluginName, platform, scope })),
2531
2551
  ...(intent.scope === 'project' ? {
2532
2552
  shareability: await inspectConfigShareability({
2533
2553
  sourceId: selected.source.sourceId,
@@ -2887,9 +2907,15 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2887
2907
  delete values[key];
2888
2908
  Object.assign(values, draft.updates);
2889
2909
  const candidateStores = { ...stores, [scope]: { ...edited, values } };
2910
+ const references = await resolvePluginConfigReferenceContext({
2911
+ sourceId: plugin.sourceId, sourceIdentity: plugin.sourceIdentity,
2912
+ logicalIdentity: plugin.catalogLogicalIdentity, manifest: plugin.manifest,
2913
+ scope, cwd: context.cwd, env: context.env,
2914
+ });
2890
2915
  const effective = await resolveEffectivePluginConfigFromStores({
2891
2916
  manifest: plugin.manifest, targetScope: scope,
2892
2917
  projectRoot: resolveAwProjectRoot(context.cwd), stores: candidateStores,
2918
+ referenceContext: references.context,
2893
2919
  });
2894
2920
  // Keep invalid raw sources for Core validation; effective.values omits them.
2895
2921
  // Preserve active branches in other references that reserve source values.
@@ -2907,10 +2933,12 @@ export function createTuiControllerDependencies(context, progressFeed, options =
2907
2933
  const result = { selections: {} };
2908
2934
  for (const scalar of scalars) {
2909
2935
  const ref = scalar.valueRef;
2910
- const selection = getPluginConfigReferenceChoices(definition, scalar, candidate);
2911
- const entries = candidate[ref.field];
2936
+ const selection = getPluginConfigReferenceChoices(definition, scalar, candidate, references.context);
2937
+ const entries = ref.plugin ? references.context.plugins[ref.plugin]?.values?.[ref.field] : candidate[ref.field];
2912
2938
  result.selections[configReferenceKey(scalar)] = {
2913
- ...selection, source: effective.sources[ref.field] ?? 'missing',
2939
+ ...selection, source: (ref.plugin
2940
+ ? references.evidence.find((entry) => entry.plugin === ref.plugin)?.sources[ref.field]
2941
+ : effective.sources[ref.field]) ?? 'missing',
2914
2942
  entries: Array.isArray(entries) ? Object.fromEntries(entries.flatMap((entry) => entry && typeof entry === 'object' && Object.hasOwn(entry, ref.key)
2915
2943
  ? [[JSON.stringify(entry[ref.key]), digest(entry)]] : [])) : {},
2916
2944
  };
@@ -3705,7 +3733,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
3705
3733
  if (!reviewedBatch || !currentEvidence.configBatch || !currentEvidence.source) {
3706
3734
  throw operationReviewStale('确认信息缺少设置批次证据。');
3707
3735
  }
3708
- const approvedApplyTargets = new Set(reviewedBatch.groups.flatMap((group) => group.config.affectedTargets.map((target) => `${target.platform}\0${target.scope}`)));
3736
+ const approvedApplyTargets = new Set(reviewedBatch.groups.flatMap((group) => group.config.affectedTargets.map((target) => `${target.pluginName ?? parsePluginId(intent.pluginId).pluginName}\0${target.platform}\0${target.scope}`)));
3709
3737
  const approvedCommandPackages = new Set(reviewedBatch.groups.flatMap((group) => (group.config.commandPackages ?? []).map((target) => target.packageId)));
3710
3738
  const approvedPreApplyTargets = reviewedBatch.groups.flatMap((group) => group.config.preApplyAuthorization ?? []);
3711
3739
  const results = [];
@@ -3736,7 +3764,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
3736
3764
  if (freshLayerStoreDigest !== reviewedGroup.config.storeDigest) {
3737
3765
  throw operationReviewStale('保存设置期间此设置层的原始内容发生变化。');
3738
3766
  }
3739
- if (freshConfig.affectedTargets.some((target) => !approvedApplyTargets.has(`${target.platform}\0${target.scope}`))
3767
+ if (freshConfig.affectedTargets.some((target) => !approvedApplyTargets.has(`${target.pluginName ?? parsePluginId(intent.pluginId).pluginName}\0${target.platform}\0${target.scope}`))
3740
3768
  || freshConfig.commandPackages?.some((target) => !approvedCommandPackages.has(target.packageId))) {
3741
3769
  throw operationReviewStale('同批前一层变更扩大了未经确认的应用目标。');
3742
3770
  }
@@ -3755,7 +3783,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
3755
3783
  assertSourceEvidenceMatches(freshSource, sourceEvidenceForPlugin(source, plugin.manifest.name));
3756
3784
  const applyTargets = intent.apply
3757
3785
  ? freshConfig.affectedTargets.map((target) => ({
3758
- pluginName: plugin.manifest.name,
3786
+ pluginName: target.pluginName ?? plugin.manifest.name,
3759
3787
  platform: target.platform,
3760
3788
  scope: target.scope,
3761
3789
  }))
@@ -3879,7 +3907,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
3879
3907
  assertSourceEvidenceMatches(currentSource, sourceEvidenceForPlugin(source, plugin.manifest.name));
3880
3908
  const applyTargets = intent.retryApply || intent.apply
3881
3909
  ? currentEvidence.config?.affectedTargets.map((target) => ({
3882
- pluginName: plugin.manifest.name,
3910
+ pluginName: target.pluginName ?? plugin.manifest.name,
3883
3911
  platform: target.platform,
3884
3912
  scope: target.scope,
3885
3913
  })) ?? []