diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 9f725b3..7e06bd1 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -17,7 +17,7 @@ Requirements for initial release. Each maps to roadmap phases. - [x] **FOUND-06**: User can cancel any long-running operation mid-execution - [x] **FOUND-07**: All errors surface to the user with actionable messages — no silent failures - [x] **FOUND-08**: Structured logging for diagnostics (Serilog or equivalent) -- [ ] **FOUND-09**: Localization system supporting English and French with dynamic language switching +- [x] **FOUND-09**: Localization system supporting English and French with dynamic language switching - [x] **FOUND-10**: JSON-based local storage for profiles, settings, and templates (compatible with current app's format for migration) - [ ] **FOUND-11**: Self-contained single EXE distribution — no .NET runtime dependency for end users - [x] **FOUND-12**: Configurable data output folder for exports @@ -123,7 +123,7 @@ Which phases cover which requirements. Updated during roadmap creation. | FOUND-06 | Phase 1 | Complete | | FOUND-07 | Phase 1 | Complete | | FOUND-08 | Phase 1 | Complete | -| FOUND-09 | Phase 1 | Pending | +| FOUND-09 | Phase 1 | Complete | | FOUND-10 | Phase 1 | Complete | | FOUND-11 | Phase 5 | Pending | | FOUND-12 | Phase 1 | Complete | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index b9b7494..cc3fce7 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -104,7 +104,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 | Phase | Plans Complete | Status | Completed | |-------|----------------|--------|-----------| -| 1. Foundation | 3/8 | In Progress| | +| 1. Foundation | 4/8 | In Progress| | | 2. Permissions | 0/? | Not started | - | | 3. Storage and File Operations | 0/? | Not started | - | | 4. Bulk Operations and Provisioning | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index d894196..51746a5 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: planning -stopped_at: Completed 01-foundation-03-PLAN.md -last_updated: "2026-04-02T10:13:20.259Z" +stopped_at: Completed 01-foundation-05-PLAN.md +last_updated: "2026-04-02T10:19:35.873Z" last_activity: 2026-04-02 — Roadmap created, requirements mapped, all 42 v1 requirements assigned to phases progress: total_phases: 5 completed_phases: 0 total_plans: 8 - completed_plans: 3 + completed_plans: 4 percent: 13 --- @@ -53,6 +53,7 @@ Progress: [█░░░░░░░░░] 13% | Phase 01-foundation P01 | 4 | 2 tasks | 14 files | | Phase 01-foundation P02 | 1 | 2 tasks | 7 files | | Phase 01-foundation P03 | 8 | 2 tasks | 7 files | +| Phase 01-foundation P05 | 4min | 2 tasks | 8 files | ## Accumulated Context @@ -73,6 +74,8 @@ Recent decisions affecting current work: - [Phase 01-foundation]: Explicit System.IO using required in WPF project — WPF temp build project does not include System.IO in implicit usings; all persistence classes need explicit import - [Phase 01-foundation]: SettingsService validates only 'en' and 'fr' language codes — throws ArgumentException for unsupported codes - [Phase 01-foundation]: LoadAsync on corrupt JSON throws InvalidDataException (not silent empty) — explicit failure protects against silent data loss +- [Phase 01-foundation]: Strings.Designer.cs maintained manually — ResXFileCodeGenerator is VS-only, not run by dotnet build; only ResourceManager accessor needed +- [Phase 01-foundation]: EmbeddedResource uses Update not Include in SDK-style project — SDK auto-includes all .resx; Include causes NETSDK1022 duplicate error ### Pending Todos @@ -86,6 +89,6 @@ None yet. ## Session Continuity -Last session: 2026-04-02T10:13:20.255Z -Stopped at: Completed 01-foundation-03-PLAN.md +Last session: 2026-04-02T10:19:35.870Z +Stopped at: Completed 01-foundation-05-PLAN.md Resume file: None diff --git a/.planning/phases/01-foundation/01-05-SUMMARY.md b/.planning/phases/01-foundation/01-05-SUMMARY.md new file mode 100644 index 0000000..111e81a --- /dev/null +++ b/.planning/phases/01-foundation/01-05-SUMMARY.md @@ -0,0 +1,167 @@ +--- +phase: 01-foundation +plan: 05 +subsystem: localization +tags: [wpf, dotnet10, serilog, localization, resx, i18n, csharp, tdd] + +# Dependency graph +requires: + - 01-02 (LogPanelSink, LanguageChangedMessage) +provides: + - TranslationSource singleton with INotifyPropertyChanged indexer for runtime culture switching + - Strings.resx with 27 Phase 1 EN UI strings + - Strings.fr.resx with same 27 keys stubbed for Phase 5 FR translation + - LoggingIntegrationTests verifying Serilog rolling file sink and LogPanelSink type +affects: + - 01-06 (MainWindow.xaml binds via TranslationSource.Instance[key]) + - 01-07 (SettingsViewModel sets TranslationSource.Instance.CurrentCulture) + - 02-xx (all feature views use localized strings via TranslationSource) + +# Tech tracking +tech-stack: + added: [] + patterns: + - TranslationSource singleton with INotifyPropertyChanged empty-string key (signals all bindings refresh) + - WPF binding: Source={x:Static loc:TranslationSource.Instance}, Path=[key] + - ResourceManager from Strings.Designer.cs — manually maintained for dotnet build (no ResXFileCodeGenerator at build time) + - EmbeddedResource Update (not Include) in SDK-style project — avoids NETSDK1022 duplicate error + - IDisposable test teardown with TranslationSource culture reset — prevents test pollution + +key-files: + created: + - SharepointToolbox/Localization/TranslationSource.cs + - SharepointToolbox/Localization/Strings.resx + - SharepointToolbox/Localization/Strings.fr.resx + - SharepointToolbox/Localization/Strings.Designer.cs + modified: + - SharepointToolbox/SharepointToolbox.csproj + - SharepointToolbox/App.xaml.cs + - SharepointToolbox.Tests/Localization/TranslationSourceTests.cs + - SharepointToolbox.Tests/Integration/LoggingIntegrationTests.cs + +key-decisions: + - "Strings.Designer.cs is maintained manually — ResXFileCodeGenerator is a VS-only tool; dotnet build requires the designer file to pre-exist; only the ResourceManager accessor is needed (no per-key typed properties)" + - "EmbeddedResource uses Update not Include — SDK-style projects auto-include all .resx as EmbeddedResource; using Include causes NETSDK1022 duplicate error" + - "System.IO using added explicitly in test project — xunit test project implicit usings do not cover System.IO; consistent with existing pattern in main project" + +requirements-completed: + - FOUND-08 + - FOUND-09 + +# Metrics +duration: 4min +completed: 2026-04-02 +--- + +# Phase 1 Plan 05: Logging Infrastructure and Dynamic Localization Summary + +**TranslationSource singleton + EN/FR resx + Serilog integration tests — 26 tests pass (24 Unit, 2 Integration), 0 errors, 0 warnings** + +## Performance + +- **Duration:** 4 min +- **Started:** 2026-04-02T10:14:23Z +- **Completed:** 2026-04-02T10:18:08Z +- **Tasks:** 2 +- **Files modified:** 8 + +## Accomplishments + +- TranslationSource singleton implements INotifyPropertyChanged; indexer `[key]` uses ResourceManager for runtime culture switching without restart +- PropertyChanged fires with `string.Empty` PropertyName on culture change — WPF re-evaluates all bindings to TranslationSource.Instance +- Missing key returns `[key]` placeholder — prevents NullReferenceException in WPF bindings +- Same-culture assignment is no-op — equality check prevents spurious PropertyChanged events +- Strings.resx: 27 Phase 1 UI strings (EN): app, toolbar, tab, button, settings, profile, status, and error keys +- Strings.fr.resx: same 27 keys, EN values stubbed, marked `` +- Strings.Designer.cs: ResourceManager accessor for dotnet build compatibility (no VS ResXFileCodeGenerator dependency) +- LoggingIntegrationTests: verifies Serilog creates a rolling log file and writes message content; verifies LogPanelSink implements ILogEventSink +- App.xaml.cs: comment added documenting deferred LogPanelSink DI registration (plan 01-06) + +## Task Commits + +1. **Task 1 RED: Failing tests for TranslationSource** - `8a58140` (test) +2. **Task 1 GREEN: TranslationSource + resx files implementation** - `a287ed8` (feat) +3. **Task 2: Serilog integration tests + App.xaml.cs comment** - `1c532d1` (feat) + +## Files Created/Modified + +- `SharepointToolbox/Localization/TranslationSource.cs` — Singleton; INotifyPropertyChanged indexer; empty-string PropertyChanged; culture equality guard +- `SharepointToolbox/Localization/Strings.resx` — 27 Phase 1 EN string resources +- `SharepointToolbox/Localization/Strings.fr.resx` — 27 keys stubbed with EN values; Phase 5 FR completion +- `SharepointToolbox/Localization/Strings.Designer.cs` — ResourceManager accessor; manually maintained for dotnet build +- `SharepointToolbox/SharepointToolbox.csproj` — EmbeddedResource Update metadata for resx files +- `SharepointToolbox/App.xaml.cs` — LogPanelSink registration comment deferred to plan 01-06 +- `SharepointToolbox.Tests/Localization/TranslationSourceTests.cs` — 6 unit tests; IDisposable teardown for culture reset +- `SharepointToolbox.Tests/Integration/LoggingIntegrationTests.cs` — 2 integration tests; temp dir cleanup in Dispose + +## Decisions Made + +- Strings.Designer.cs maintained manually: `ResXFileCodeGenerator` is a Visual Studio design-time tool not available in `dotnet build`. The designer file only needs the `ResourceManager` property accessor — no per-key typed properties are needed since TranslationSource uses `ResourceManager.GetString(key, culture)` directly. +- `EmbeddedResource Update` instead of `Include`: SDK-style projects implicitly include all `.resx` files as `EmbeddedResource`. Using `Include` causes `NETSDK1022` duplicate build error. `Update` sets metadata on the already-included item. +- Explicit `System.IO` using in test file: test project implicit usings do not cover `System.IO`; consistent with the established pattern for the main project (prior decision FOUND-10). + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] Added explicit System.IO using to LoggingIntegrationTests.cs** +- **Found during:** Task 2 (dotnet build) +- **Issue:** CS0103 — `Path`, `Directory`, `File` not found; test project implicit usings do not include System.IO +- **Fix:** Added `using System.IO;` to the test file +- **Files modified:** `SharepointToolbox.Tests/Integration/LoggingIntegrationTests.cs` +- **Verification:** Build 0 errors, 0 warnings after fix +- **Committed in:** 1c532d1 (Task 2 commit) + +**2. [Rule 3 - Blocking] Used EmbeddedResource Update (not Include) for resx metadata** +- **Found during:** Task 1 GREEN (dotnet build) +- **Issue:** NETSDK1022 duplicate EmbeddedResource — SDK auto-includes all .resx files; explicit Include causes duplicate error +- **Fix:** Changed `` to `` in SharepointToolbox.csproj +- **Files modified:** `SharepointToolbox/SharepointToolbox.csproj` +- **Verification:** Build 0 errors, 0 warnings after fix +- **Committed in:** a287ed8 (Task 1 commit) + +**3. [Rule 3 - Blocking] Created Strings.Designer.cs manually** +- **Found during:** Task 1 GREEN (dotnet build) +- **Issue:** `Strings` class does not exist in context — ResXFileCodeGenerator is VS-only, not run by dotnet build CLI +- **Fix:** Created Strings.Designer.cs with ResourceManager accessor manually; only the `ResourceManager` property is needed (TranslationSource uses it directly) +- **Files modified:** `SharepointToolbox/Localization/Strings.Designer.cs` +- **Verification:** Build 0 errors after fix; TranslationSourceTests pass +- **Committed in:** a287ed8 (Task 1 commit) + +--- + +**Total deviations:** 3 auto-fixed (all Rule 3 — blocking build issues) +**Impact on plan:** All fixes minor; no scope creep; no behavior change from plan intent. + +## Issues Encountered + +None beyond the auto-fixed deviations above. + +## User Setup Required + +None — no external service configuration required. + +## Next Phase Readiness + +- TranslationSource.Instance ready for WPF XAML binding in plan 01-06 (MainWindow) +- All 27 Phase 1 UI string keys defined in EN resx +- FR resx keyset matches EN — Phase 5 can add translations without key changes +- Serilog rolling file sink verified working; LogPanelSink type verified ILogEventSink-compatible +- Plan 01-06 can proceed immediately + +## Self-Check: PASSED + +- FOUND: SharepointToolbox/Localization/TranslationSource.cs +- FOUND: SharepointToolbox/Localization/Strings.resx +- FOUND: SharepointToolbox/Localization/Strings.fr.resx +- FOUND: SharepointToolbox/Localization/Strings.Designer.cs +- FOUND: SharepointToolbox.Tests/Localization/TranslationSourceTests.cs +- FOUND: SharepointToolbox.Tests/Integration/LoggingIntegrationTests.cs +- FOUND: .planning/phases/01-foundation/01-05-SUMMARY.md +- Commit 8a58140: test(01-05): add failing tests for TranslationSource singleton +- Commit a287ed8: feat(01-05): implement TranslationSource singleton + EN/FR resx files +- Commit 1c532d1: feat(01-05): add Serilog integration tests and App.xaml.cs LogPanelSink comment + +--- +*Phase: 01-foundation* +*Completed: 2026-04-02*