This release ships three major feature areas behind a lightweight control-layer architecture, plus lifecycle hygiene fixes, testability improvements, and tooling to make future features fast to add.
AppLogger.Warningtypo —AppLogger.Warn(non-existent) inOivViewModelwas replaced with the correctAppLogger.Warning, resolving a build error introduced in the OIV creator pipeline.- Installer failure classification —
FileNotFoundException/DirectoryNotFoundExceptionnow correctly surface asMissingFile; genericIOExceptionsurfaces asInvalidArchivewith a user-actionable message. Ordering is preserved (specific before generic). - WebView ZIP staging — browser downloads no longer trigger installs automatically. A ZIP staged via Browse is held for explicit user confirmation in the Install tab before any file is written.
- ViewModel lifecycle —
InstallViewModelandBrowseViewModelnow detach fromModDownloadBridgeon dispose, preventing ghost subscriptions when views are closed and reopened.
Lightweight feature-slice abstractions added to Core/:
IAppCommand/AsyncAppCommand— cancellable, observable commands that disable themselves while running.IFeatureController/IFeatureModule— standard interfaces for feature slices; each slice owns its controller and registers commands.
IInstallController+InstallWorkflowControllerown detection, staging, plan building, and confirm-install orchestration.InstallViewModeldelegates all install workflow steps to the controller; it no longer callsModDetector,SmartInstallPlanner, orInstallQueuedirectly.ConfirmedInstallmodel carries the result of a user-confirmed install intent.
ILibraryController+LibraryWorkflowControllerown bulk enable/disable and undo-restoration workflows.LibraryViewModeldelegates bulk toggle operations to the controller.BulkToggleStatemodel carries the snapshot needed for undo.
- New
Features/OivCreatorTemplates/slice withIOivTemplateControllerandOivTemplateController. - Template selection has zero side effects — metadata and files are unchanged until the user clicks Apply.
- Apply builds an immutable
OivTemplateApplyPlanfrom a snapshot DTO and mutates only non-user-edited fields (IsUserEditedflag respected perOivFileEntry). - Undo restores the pre-apply snapshot (one level).
- Add File after Apply suggests a safe install path (editable);
PathSafety.GetSafePathvalidates all suggestions. OivView.xamlgains a "TEMPLATE (OPTIONAL)" section with Apply/Undo buttons and aTemplateApplyStatusfeedback label.
- New
Features/Updates/slice withIUpdateController,UpdateWorkflowController, andUpdateFeatureModule. SettingsViewModel.CheckForUpdatesCommanddelegates toIUpdateController.CheckForUpdatesAsync; no download or apply logic exists anywhere in the controller or ViewModel.UpdateCheckResultdomain type carries version, availability flag, release URL, and offline status.UpdateCheckService.CheckAsyncis nowvirtualto support test subclassing without a full mock framework.
IFileDialogService/OpenFileDialogServiceadded toServices/;OivViewModel.AddCreatorFileuses the interface.- Suggest-on-add tests are now fully deterministic via
FakeFileDialogService— no Win32 dialog involvement.
ArchitectureGuardTestsenforce that ViewModels do not enqueue installs or callFileInstallerdirectly; allowlist covers the legacy batch-reinstall path.ControlLayerTestscover:AsyncAppCommanddisables while running;InstallViewModeldelegates detect/review to controller;BrowseViewModelandInstallViewModeldispose correctly.
tools/New-FeatureSlice.ps1scaffolds a new feature slice (controller, module, interface, models, tests) in one command. Supports-WithArchitectureTestflag.Features/_Template/README.mddocuments the copy/pasteable slice pattern.docs/feature-slice-template.mdadded.docs/architecture.md,docs/common-tasks.md,docs/dependencies.md, anddocs/ui-smoke-pr-check.mdupdated to reflect new patterns and triage notes.
CLAUDE.mdgains a Verification (Hard Constraint) section requiring the executable to be launched before claiming a fix is complete, and a Release Packaging section listing what to strip from release ZIPs..github/pull_request_template.mdadded with UI smoke checklist fields.AGENTS.mdadded for agentic worker instructions.
dotnet build LSPDFRManager.sln # 0 errors
dotnet test LSPDFRManager.Tests/... # 734/734 passed
dotnet test --filter "OivTemplate|OivViewModel|OivCreator|ArchitectureGuard|UpdateWorkflow" # 63/63 passed
Manual WPF/WebView smoke run required before production use — see docs/ui-smoke-pr-check.md.