10 KiB
phase, verified, status, score, re_verification
| phase | verified | status | score | re_verification |
|---|---|---|---|---|
| 06-global-site-selection | 2026-04-07T00:00:00Z | passed | 7/7 truths verified | false |
Phase 06: Global Site Selection Verification Report
Phase Goal: Administrators can select one or more target sites once from the toolbar and have every feature tab use that selection by default Verified: 2026-04-07 Status: PASSED Re-verification: No — initial verification
Goal Achievement
Observable Truths
| # | Truth | Status | Evidence |
|---|---|---|---|
| 1 | GlobalSitesChangedMessage exists following the ValueChangedMessage pattern | VERIFIED | GlobalSitesChangedMessage.cs — sealed class ... : ValueChangedMessage<IReadOnlyList<SiteInfo>> |
| 2 | FeatureViewModelBase receives message, stores GlobalSites, exposes virtual hook | VERIFIED | FeatureViewModelBase.cs lines 30, 82–83, 90–103 — property, registration, private receiver, virtual override |
| 3 | MainWindowViewModel owns GlobalSelectedSites, broadcasts message, clears on tenant/session | VERIFIED | MainWindowViewModel.cs lines 43–75, 102–103, 146 — collection, CollectionChanged broadcast, clear paths |
| 4 | Toolbar shows "Select Sites" button bound to OpenGlobalSitePickerCommand and a live count label | VERIFIED | MainWindow.xaml lines 26–31; MainWindow.xaml.cs lines 25–29 — button, TextBlock, dialog factory wired |
| 5 | Localization keys present in EN and FR for all 5 toolbar strings | VERIFIED | Strings.resx lines 308–320; Strings.fr.resx lines 308–320 — 5 keys each |
| 6 | All 6 consuming tab VMs override OnGlobalSitesChanged with local-override protection | VERIFIED | Grep confirms override in: PermissionsViewModel, StorageViewModel, SearchViewModel, DuplicatesViewModel, FolderStructureViewModel, TransferViewModel; BulkMembersViewModel confirmed excluded (no match) |
| 7 | 10 unit tests pass covering the full contract; no regressions in existing suite | VERIFIED | dotnet test --filter GlobalSiteSelection → 10 Passed; full suite → 144 Passed, 22 Skipped, 0 Failed |
Score: 7/7 truths verified
Required Artifacts
| Artifact | Provides | Status | Details |
|---|---|---|---|
SharepointToolbox/Core/Messages/GlobalSitesChangedMessage.cs |
Messenger message for global site selection | VERIFIED | Exists, substantive (9 lines, ValueChangedMessage<IReadOnlyList>), registered in FeatureViewModelBase |
SharepointToolbox/ViewModels/FeatureViewModelBase.cs |
Base class with GlobalSites property and virtual hook | VERIFIED | Contains GlobalSites, OnGlobalSitesChanged, registration in OnActivated |
SharepointToolbox/ViewModels/MainWindowViewModel.cs |
Global site selection state, command, broadcast | VERIFIED | Contains GlobalSelectedSites, OpenGlobalSitePickerCommand, GlobalSitesSelectedLabel, BroadcastGlobalSites |
SharepointToolbox/MainWindow.xaml |
Toolbar with Select Sites button and count label | VERIFIED | Contains OpenGlobalSitePickerCommand binding and GlobalSitesSelectedLabel TextBlock |
SharepointToolbox/MainWindow.xaml.cs |
SitePickerDialog factory wiring | VERIFIED | Contains OpenGlobalSitePickerDialog factory lambda |
SharepointToolbox/Localization/Strings.resx |
EN localization keys | VERIFIED | 5 keys: toolbar.selectSites, toolbar.selectSites.tooltip, toolbar.selectSites.tooltipDisabled, toolbar.globalSites.count, toolbar.globalSites.none |
SharepointToolbox/Localization/Strings.fr.resx |
FR localization keys | VERIFIED | Same 5 keys with French translations |
SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs |
Multi-site global consumption | VERIFIED | OnGlobalSitesChanged override, _hasLocalSiteOverride, reset in OnTenantSwitched |
SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs |
Single-site global consumption | VERIFIED | OnGlobalSitesChanged, OnSiteUrlChanged partial, _hasLocalSiteOverride, reset in OnTenantSwitched |
SharepointToolbox/ViewModels/Tabs/SearchViewModel.cs |
Single-site global consumption | VERIFIED | OnGlobalSitesChanged confirmed present |
SharepointToolbox/ViewModels/Tabs/DuplicatesViewModel.cs |
Single-site global consumption | VERIFIED | OnGlobalSitesChanged confirmed present |
SharepointToolbox/ViewModels/Tabs/FolderStructureViewModel.cs |
Single-site global consumption | VERIFIED | OnGlobalSitesChanged confirmed present |
SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs |
Single-site (SourceSiteUrl) global consumption | VERIFIED | OnGlobalSitesChanged, _hasLocalSourceSiteOverride, OnSourceSiteUrlChanged confirmed present |
SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs |
10 unit tests for full contract | VERIFIED | All 10 tests pass |
Key Link Verification
| From | To | Via | Status | Details |
|---|---|---|---|---|
FeatureViewModelBase.cs |
GlobalSitesChangedMessage.cs |
Messenger.Register<GlobalSitesChangedMessage> in OnActivated |
WIRED | Line 82: Messenger.Register<GlobalSitesChangedMessage>(this, (r, m) => ...) |
MainWindowViewModel.cs |
GlobalSitesChangedMessage.cs |
WeakReferenceMessenger.Default.Send in BroadcastGlobalSites |
WIRED | Lines 180–182: WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(...)) |
MainWindow.xaml |
MainWindowViewModel.cs |
Command binding for OpenGlobalSitePickerCommand | WIRED | Line 27: Command="{Binding OpenGlobalSitePickerCommand}" |
MainWindow.xaml.cs |
SitePickerDialog.xaml.cs |
Dialog factory lambda using DI | WIRED | Lines 25–29: viewModel.OpenGlobalSitePickerDialog = () => { var factory = serviceProvider.GetRequiredService<Func<TenantProfile, SitePickerDialog>>(); ... } |
PermissionsViewModel.cs |
FeatureViewModelBase.cs |
Override of OnGlobalSitesChanged virtual method | WIRED | Line 161: protected override void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites) |
StorageViewModel.cs |
FeatureViewModelBase.cs |
Override of OnGlobalSitesChanged virtual method | WIRED | Line 100: protected override void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites) |
GlobalSiteSelectionTests.cs |
MainWindowViewModel.cs |
Tests broadcast and clear behavior | WIRED | Test 10 uses GlobalSelectedSites; Tests 1–9 send via WeakReferenceMessenger |
GlobalSiteSelectionTests.cs |
StorageViewModel.cs |
Tests single-site consumption and local override | WIRED | Tests 3–5, 8 exercise OnGlobalSitesChanged via messenger send |
Requirements Coverage
| Requirement | Source Plans | Description | Status | Evidence |
|---|---|---|---|---|
| SITE-01 | 06-01, 06-02, 06-03, 06-04, 06-05 | User can select one or multiple target sites from toolbar and all feature tabs use that selection as default | SATISFIED | Message contract (06-01), MainWindowViewModel broadcast (06-02), toolbar UI (06-03), tab VM consumption (06-04), unit tests (06-05) — full end-to-end chain verified |
| SITE-02 | 06-04, 06-05 | User can override global site selection per-tab for single-site operations | SATISFIED | _hasLocalSiteOverride field in all 6 consuming VMs; OnSiteUrlChanged / OnSourceSiteUrlChanged partial methods detect user typing; tests 4, 7 verify local override prevents global overwrite |
No orphaned requirements — REQUIREMENTS.md maps only SITE-01 and SITE-02 to Phase 6, and both are claimed and satisfied by the plans.
Anti-Patterns Found
None. Files scanned for TODO/FIXME/HACK/PLACEHOLDER, empty implementations, and stub returns:
- "placeholder" occurrences in
MainWindow.xaml.csare code comments (// Replace ... placeholder with the DI-resolved ...) describing the construction pattern — they are not stub implementations. - "placeholder" in export service HTML strings is an HTML
<input placeholder=...>attribute — unrelated to implementation stubs. - No empty handlers,
return null,return {}, orconsole.log-only implementations found. - Build: 0 errors, 0 warnings.
Human Verification Required
The following items cannot be verified programmatically and require a running instance of the application:
1. Select Sites button visual presence and position
Test: Launch the application, connect to a tenant profile. Observe the main toolbar. Expected: A "Select Sites" button is visible after the Clear Session button separator, followed by a gray label showing "No sites selected" (or the FR equivalent if app is in French). Why human: XAML rendering and visual layout cannot be verified from static file analysis.
2. SitePickerDialog opens on button click
Test: Click the "Select Sites" toolbar button while connected to a tenant. Expected: The SitePickerDialog opens, displaying the sites for the connected tenant. Selecting sites and clicking OK updates the count label (e.g., "2 site(s) selected"). Why human: Dialog opening requires a live DI container, real window handle, and SharePoint connectivity.
3. Button disabled state when no profile is connected
Test: Launch the application without selecting a tenant profile (or deselect the current one). Expected: The "Select Sites" button appears visually disabled and cannot be clicked. Why human: WPF CanExecute rendering requires a live UI; IsEnabled binding cannot be observed statically.
4. Tab pre-fill behavior end-to-end
Test: Select 2 sites globally. Navigate to the Storage tab, Search tab, Permissions tab, and Transfer tab. Expected: Storage/Search SiteUrl fields show the first selected site URL; Permissions SelectedSites shows both sites; Transfer SourceSiteUrl shows the first site URL. Why human: UI binding rendering from pre-filled ViewModel state requires a running application.
5. Local override does not disrupt global selection
Test: With 2 global sites selected, go to the Storage tab and type a custom URL in the site URL field. Switch to the Permissions tab. Expected: Permissions tab still shows the 2 globally selected sites. The Storage tab keeps the manually typed URL. The toolbar still shows "2 site(s) selected." Why human: Cross-tab state isolation requires observing live UI across multiple tab switches.
Gaps Summary
No gaps. All 7 observable truths are verified. All 14 required artifacts exist, are substantive, and are wired. All 8 key links are confirmed. Both requirements (SITE-01, SITE-02) are satisfied with full traceability. The test suite confirms correctness with 10 new passing tests and 0 regressions.
Verified: 2026-04-07 Verifier: Claude (gsd-verifier)