fix(01-foundation): revise plans based on checker feedback
- 01-03: wave 2 → wave 3 (depends on 01-02 which is also wave 2; must be wave 3) - 01-06: add ProgressUpdatedMessage.cs to files_modified; add third StatusBarItem (progress %) to XAML per locked CONTEXT.md decision; add ProgressUpdatedMessage subscription in MainWindowViewModel.OnActivated() - 01-08: add comment to empty <files> element (auto task with no file output) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
phase: 01-foundation
|
phase: 01-foundation
|
||||||
plan: 03
|
plan: 03
|
||||||
type: execute
|
type: execute
|
||||||
wave: 2
|
wave: 3
|
||||||
depends_on:
|
depends_on:
|
||||||
- 01-01
|
- 01-01
|
||||||
- 01-02
|
- 01-02
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ depends_on:
|
|||||||
- 01-04
|
- 01-04
|
||||||
- 01-05
|
- 01-05
|
||||||
files_modified:
|
files_modified:
|
||||||
|
- SharepointToolbox/Core/Messages/ProgressUpdatedMessage.cs
|
||||||
- SharepointToolbox/ViewModels/FeatureViewModelBase.cs
|
- SharepointToolbox/ViewModels/FeatureViewModelBase.cs
|
||||||
- SharepointToolbox/ViewModels/MainWindowViewModel.cs
|
- SharepointToolbox/ViewModels/MainWindowViewModel.cs
|
||||||
- SharepointToolbox/ViewModels/ProfileManagementViewModel.cs
|
- SharepointToolbox/ViewModels/ProfileManagementViewModel.cs
|
||||||
@@ -53,6 +54,10 @@ must_haves:
|
|||||||
to: "SharepointToolbox/Core/Messages/TenantSwitchedMessage.cs"
|
to: "SharepointToolbox/Core/Messages/TenantSwitchedMessage.cs"
|
||||||
via: "WeakReferenceMessenger.Default.Send on ComboBox selection change"
|
via: "WeakReferenceMessenger.Default.Send on ComboBox selection change"
|
||||||
pattern: "TenantSwitchedMessage"
|
pattern: "TenantSwitchedMessage"
|
||||||
|
- from: "SharepointToolbox/ViewModels/MainWindowViewModel.cs"
|
||||||
|
to: "SharepointToolbox/Core/Messages/ProgressUpdatedMessage.cs"
|
||||||
|
via: "Messenger.Register<ProgressUpdatedMessage> in OnActivated — updates StatusBar observable properties"
|
||||||
|
pattern: "ProgressUpdatedMessage"
|
||||||
---
|
---
|
||||||
|
|
||||||
<objective>
|
<objective>
|
||||||
@@ -113,6 +118,7 @@ public sealed class LanguageChangedMessage : ValueChangedMessage<string>
|
|||||||
<task type="auto" tdd="true">
|
<task type="auto" tdd="true">
|
||||||
<name>Task 1: FeatureViewModelBase + unit tests</name>
|
<name>Task 1: FeatureViewModelBase + unit tests</name>
|
||||||
<files>
|
<files>
|
||||||
|
SharepointToolbox/Core/Messages/ProgressUpdatedMessage.cs,
|
||||||
SharepointToolbox/ViewModels/FeatureViewModelBase.cs,
|
SharepointToolbox/ViewModels/FeatureViewModelBase.cs,
|
||||||
SharepointToolbox.Tests/ViewModels/FeatureViewModelBaseTests.cs
|
SharepointToolbox.Tests/ViewModels/FeatureViewModelBaseTests.cs
|
||||||
</files>
|
</files>
|
||||||
@@ -248,6 +254,8 @@ public sealed class LanguageChangedMessage : ValueChangedMessage<string>
|
|||||||
```csharp
|
```csharp
|
||||||
[ObservableProperty] private TenantProfile? _selectedProfile;
|
[ObservableProperty] private TenantProfile? _selectedProfile;
|
||||||
[ObservableProperty] private string _connectionStatus = "Not connected";
|
[ObservableProperty] private string _connectionStatus = "Not connected";
|
||||||
|
[ObservableProperty] private string _progressStatus = string.Empty;
|
||||||
|
[ObservableProperty] private int _progressPercentage;
|
||||||
public ObservableCollection<TenantProfile> TenantProfiles { get; } = new();
|
public ObservableCollection<TenantProfile> TenantProfiles { get; } = new();
|
||||||
|
|
||||||
// ConnectCommand: calls SessionManager.GetOrCreateContextAsync(SelectedProfile)
|
// ConnectCommand: calls SessionManager.GetOrCreateContextAsync(SelectedProfile)
|
||||||
@@ -257,6 +265,22 @@ public sealed class LanguageChangedMessage : ValueChangedMessage<string>
|
|||||||
// LoadProfilesAsync: called on startup, loads from ProfileService
|
// LoadProfilesAsync: called on startup, loads from ProfileService
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Override `OnActivated()` to register for `ProgressUpdatedMessage` from any active feature ViewModel:
|
||||||
|
```csharp
|
||||||
|
protected override void OnActivated()
|
||||||
|
{
|
||||||
|
base.OnActivated();
|
||||||
|
Messenger.Register<ProgressUpdatedMessage>(this, (r, m) =>
|
||||||
|
{
|
||||||
|
r.ProgressStatus = m.Value.Message;
|
||||||
|
r.ProgressPercentage = m.Value.Total > 0
|
||||||
|
? (int)(100.0 * m.Value.Current / m.Value.Total)
|
||||||
|
: 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This wires the StatusBar operation text and progress % to live updates from any running feature operation.
|
||||||
|
|
||||||
**ProfileManagementViewModel.cs**: Wraps ProfileService for dialog binding.
|
**ProfileManagementViewModel.cs**: Wraps ProfileService for dialog binding.
|
||||||
- `ObservableCollection<TenantProfile> Profiles`
|
- `ObservableCollection<TenantProfile> Profiles`
|
||||||
- `AddCommand`, `RenameCommand`, `DeleteCommand`
|
- `AddCommand`, `RenameCommand`, `DeleteCommand`
|
||||||
@@ -269,7 +293,8 @@ public sealed class LanguageChangedMessage : ValueChangedMessage<string>
|
|||||||
- On language change: updates `TranslationSource.Instance.CurrentCulture` + calls `SettingsService.SetLanguageAsync`
|
- On language change: updates `TranslationSource.Instance.CurrentCulture` + calls `SettingsService.SetLanguageAsync`
|
||||||
- `RunOperationAsync`: not applicable — stub throws `NotSupportedException` (Settings tab has no long-running operation)
|
- `RunOperationAsync`: not applicable — stub throws `NotSupportedException` (Settings tab has no long-running operation)
|
||||||
|
|
||||||
**MainWindow.xaml** — Full shell layout as locked in CONTEXT.md:
|
**MainWindow.xaml** — Full shell layout as locked in CONTEXT.md.
|
||||||
|
StatusBar MUST have three fields per the locked decision (tenant name | operation status text | progress percentage):
|
||||||
```xml
|
```xml
|
||||||
<Window Title="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[app.title]}"
|
<Window Title="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[app.title]}"
|
||||||
MinWidth="900" MinHeight="600">
|
MinWidth="900" MinHeight="600">
|
||||||
@@ -288,11 +313,13 @@ public sealed class LanguageChangedMessage : ValueChangedMessage<string>
|
|||||||
Command="{Binding ClearSessionCommand}" />
|
Command="{Binding ClearSessionCommand}" />
|
||||||
</ToolBar>
|
</ToolBar>
|
||||||
|
|
||||||
<!-- StatusBar -->
|
<!-- StatusBar: three fields per locked layout decision -->
|
||||||
<StatusBar DockPanel.Dock="Bottom" Height="24">
|
<StatusBar DockPanel.Dock="Bottom" Height="24">
|
||||||
<StatusBarItem Content="{Binding SelectedProfile.Name}" />
|
<StatusBarItem Content="{Binding SelectedProfile.Name}" />
|
||||||
<Separator />
|
<Separator />
|
||||||
<StatusBarItem Content="{Binding ConnectionStatus}" />
|
<StatusBarItem Content="{Binding ConnectionStatus}" />
|
||||||
|
<Separator />
|
||||||
|
<StatusBarItem Content="{Binding ProgressPercentage, StringFormat={}{0}%}" />
|
||||||
</StatusBar>
|
</StatusBar>
|
||||||
|
|
||||||
<!-- Log Panel -->
|
<!-- Log Panel -->
|
||||||
@@ -370,7 +397,7 @@ public sealed class LanguageChangedMessage : ValueChangedMessage<string>
|
|||||||
<verify>
|
<verify>
|
||||||
<automated>cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj 2>&1 | tail -5</automated>
|
<automated>cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj 2>&1 | tail -5</automated>
|
||||||
</verify>
|
</verify>
|
||||||
<done>Build succeeds with 0 errors. MainWindow.xaml contains RichTextBox x:Name="LogPanel". All 8 tab headers use TranslationSource bindings. Global exception handlers registered in App.xaml.cs.</done>
|
<done>Build succeeds with 0 errors. MainWindow.xaml contains RichTextBox x:Name="LogPanel". StatusBar has three StatusBarItems (tenant name, connection status, progress %). All 8 tab headers use TranslationSource bindings. Global exception handlers registered in App.xaml.cs.</done>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
</tasks>
|
</tasks>
|
||||||
@@ -379,13 +406,15 @@ public sealed class LanguageChangedMessage : ValueChangedMessage<string>
|
|||||||
- `dotnet build SharepointToolbox.sln` passes with 0 errors
|
- `dotnet build SharepointToolbox.sln` passes with 0 errors
|
||||||
- `dotnet test --filter "Category=Unit"` all pass
|
- `dotnet test --filter "Category=Unit"` all pass
|
||||||
- MainWindow.xaml contains `x:Name="LogPanel"` RichTextBox
|
- MainWindow.xaml contains `x:Name="LogPanel"` RichTextBox
|
||||||
|
- MainWindow.xaml StatusBar has three StatusBarItems: SelectedProfile.Name | ConnectionStatus | ProgressPercentage%
|
||||||
- App.xaml.cs registers `DispatcherUnhandledException` and `TaskScheduler.UnobservedTaskException`
|
- App.xaml.cs registers `DispatcherUnhandledException` and `TaskScheduler.UnobservedTaskException`
|
||||||
- FeatureViewModelBase contains no `async void` methods (anti-pattern violation)
|
- FeatureViewModelBase contains no `async void` methods (anti-pattern violation)
|
||||||
- ObservableCollection is never modified from Task.Run (pattern 7 compliance)
|
- ObservableCollection is never modified from Task.Run (pattern 7 compliance)
|
||||||
|
- MainWindowViewModel.OnActivated() subscribes to ProgressUpdatedMessage and updates ProgressStatus + ProgressPercentage
|
||||||
</verification>
|
</verification>
|
||||||
|
|
||||||
<success_criteria>
|
<success_criteria>
|
||||||
Application compiles and launches to a visible WPF shell. FeatureViewModelBase tests green. All ViewModels registered in DI. Log panel wired to Serilog.
|
Application compiles and launches to a visible WPF shell. FeatureViewModelBase tests green. All ViewModels registered in DI. Log panel wired to Serilog. StatusBar shows all three fields including live progress percentage.
|
||||||
</success_criteria>
|
</success_criteria>
|
||||||
|
|
||||||
<output>
|
<output>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ Output: Confirmed working foundation. Green light for Phase 2.
|
|||||||
|
|
||||||
<task type="auto">
|
<task type="auto">
|
||||||
<name>Task 1: Run full test suite and verify zero failures</name>
|
<name>Task 1: Run full test suite and verify zero failures</name>
|
||||||
<files></files>
|
<files><!-- no files created or modified — test-execution-only task --></files>
|
||||||
<action>
|
<action>
|
||||||
Run the complete test suite:
|
Run the complete test suite:
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user