# Copilot Instructions
## Build & Test Commands
```powershell
# Build
dotnet build Catalog.slnx
# Run all tests
dotnet test MaddoShared.Tests
# Run a single test
dotnet test MaddoShared.Tests --filter "FullyQualifiedName~MethodName"
# Benchmarks (modes: quick | all | parallel | chunks | sizes | stress)
.\run-benchmarks.ps1 quick
# Publish release build (self-contained Windows EXE)
dotnet publish "imagecatalog\ImageCatalog 2.csproj" -c Release -r win-x64 --self-contained
```
## Architecture
This is an Avalonia image cataloging application targeting .NET 10.0-windows.
### Projects
| Project | Purpose |
|---------|---------|
| **imagecatalog** | Main desktop application — Avalonia with Fluent theme (`AvaloniaMainWindow`) |
| **MaddoShared** | Shared image processing library (the core) |
| **MaddoShared.Tests** | Unit tests for MaddoShared |
| **MaddoShared.Benchmarks** | BenchmarkDotNet performance benchmarks |
| **WPFCatalog** | Alternate WPF UI (secondary) |
| **ImageCatalogCS / ImageCatalogParallel** | Legacy/experimental variants |
| **CatalogLib / CatalogLibVb / CatalogVbLib** | Legacy VB.NET libraries |
The main app launches Avalonia directly. Dialog events (`SelectSourceFolderRequested`, etc.) are subscribed in `AvaloniaMainWindow` code-behind. `DataModel.UiInvoker` must be set by the active UI to enable cross-thread UI updates (Avalonia sets this to `Dispatcher.UIThread.Invoke`).
### Core Flow
1. User configures paths/settings in the UI (`DataModel.cs` — MVVM ViewModel)
2. `ProcessImagesCommand` triggers `ImageCreationService`
3. `ImageCreationService` processes files in parallel chunks, with configurable concurrency and batch size (GC flush between chunks)
4. Each file is handled by the ImageSharp `IImageCreator` implementation
5. Output: resized/watermarked/overlaid images written to a destination folder hierarchy
### Key Abstractions (MaddoShared)
- **`IImageCreator`** — single async method to process one image; implemented by `ImageCreatorImageSharp` (SixLabors.ImageSharp)
- **`ImageCreationService`** — parallel orchestrator; uses `AsyncEnumerator` with chunking; loads logo once, clones per thread for thread safety
- **`ImageState`** — per-file processing context (input path, EXIF orientation, thumbnail sizes, overlays, logo, rotation)
- **`PicSettings`** — 50+ property configuration model (dimensions, fonts, colors, JPEG quality, watermark, logo positioning)
- **`FileHelperSharp`** — recursive file enumeration with folder-per-N-files mapping and counter formatting
## Conventions
### C# Style
- File-scoped namespaces everywhere: `namespace MaddoShared;`
- Nullable reference types enabled (`enable`)
- Implicit usings enabled
- `ConfigureAwait(false)` on all `await` calls in library code
### Dependency Injection
- Constructor injection throughout; loggers typed as `ILogger`
- Main app wires services in `Program.cs` via `IServiceCollection`
### Testing
- MSTest with `[TestClass]` / `[TestMethod]`
- FluentAssertions for assertions
- Moq for mocking
- Factory helper pattern in tests: `CreateService(Action configure = null)` methods for flexible test setup
### Async / Parallelism
- All image I/O is `async Task`
- `ImageCreationService` uses configurable `MaxDegreeOfParallelism` and `ChunkSize`; explicit `GC.Collect()` between chunks to manage memory under batch load
### Versioning & CI
- Semantic versioning via **GitVersion** (mode: `ContinuousDelivery`, current base: `3.2.0`)
- GitLab CI pipeline: builds → single-file self-contained EXE → GitLab Release
- Private NuGet packages scoped to `AIFotoONLUS.*` prefix, routed to the GitLab package registry (see `NuGet.Config`)