resolveProviderQueueScopes function

ProviderQueueResolution resolveProviderQueueScopes(
  1. List<ProviderQueueScopeInput> inputs
)

Resolves the queue across scopes: env > project > user > legacy.

Pass one ProviderQueueScopeInput per scope in any order; only present scopes matter. When none is present the result is unset (the legacy provider:+model: boot continues byte-identical — AC10).

Shadowed scopes are named in the notices (AC2); a shadowed scope whose queue is semantically identical to the winner collapses into the winner's notice (UT-scope-stack: "project+user identical queues → single notice, no dupes").

Implementation

ProviderQueueResolution resolveProviderQueueScopes(
  List<ProviderQueueScopeInput> inputs,
) {
  final present = inputs.where((input) => input.isPresent).toList()
    ..sort((a, b) => a.scope.index.compareTo(b.scope.index));
  if (present.isEmpty) {
    return const ProviderQueueResolution(
      scope: ProviderQueueScope.user,
      entries: [],
      notices: [],
    );
  }
  final winner = present.first;
  final entries = winner.parse?.entries ?? const <ProviderQueueEntry>[];
  final notices = <String>[
    'note: provider queue (${entries.length} '
        '${entries.length == 1 ? 'entry' : 'entries'}) from '
        '${_scopeLabel(winner.scope)} — the queue is the main model',
  ];
  final shadowed = present.sublist(1);
  for (final scope in shadowed) {
    final sameQueue = _sameEntries(scope.parse?.entries, entries);
    notices.add(
      sameQueue
          ? 'note: provider queue — ${_scopeLabel(scope.scope)} declares the '
                'same queue (shadowed, no duplicate)'
          : 'note: provider queue — ${_scopeLabel(scope.scope)} is shadowed '
                'by ${_scopeLabel(winner.scope)}',
    );
  }
  return ProviderQueueResolution(
    scope: winner.scope,
    entries: entries,
    notices: notices,
  );
}