|
| 1 | +# Agent Guidelines |
| 2 | + |
| 3 | +## Repository Overview |
| 4 | + |
| 5 | +**AuroraScienceHub.Geopack** — a high-performance C# port of the Fortran Geopack-2008dp geomagnetic field library by N. A. Tsyganenko. Produces three NuGet packages: |
| 6 | + |
| 7 | +- `AuroraScienceHub.Geopack.Contracts` |
| 8 | +- `AuroraScienceHub.Geopack` |
| 9 | +- `AuroraScienceHub.Geopack.ExternalFieldModels` |
| 10 | + |
| 11 | +This is a **library repository** — no runnable app. License: GPL-3.0-or-later. |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## Project Structure |
| 16 | + |
| 17 | +``` |
| 18 | +src/ |
| 19 | +├── Contracts/ # AuroraScienceHub.Geopack.Contracts |
| 20 | +├── Geopack/ # AuroraScienceHub.Geopack (depends on Contracts) |
| 21 | +└── ExternalFieldModels/ # AuroraScienceHub.Geopack.ExternalFieldModels (depends on Contracts) |
| 22 | +UnitTests/ # Single test project at ROOT — not under tests/ |
| 23 | +benchmarks/ # BenchmarkDotNet project, not part of CI |
| 24 | +Geopack.slnx # Solution file |
| 25 | +``` |
| 26 | + |
| 27 | +`src/Directory.Build.props` sets `IsPackable=True`, `PublishAot=True`, `IsAotCompatible=True` for all packages. Root `Directory.Build.props` sets `IsPackable=False` by default. |
| 28 | + |
| 29 | +--- |
| 30 | + |
| 31 | +## Commands |
| 32 | + |
| 33 | +```bash |
| 34 | +dotnet restore |
| 35 | +dotnet build # warnings-as-errors; must be clean |
| 36 | +dotnet format --verify-no-changes # run before committing; CI enforces this |
| 37 | +dotnet test |
| 38 | +dotnet pack --configuration Release |
| 39 | +``` |
| 40 | + |
| 41 | +CI runs in this order: **restore → format → build → test → pack**. |
| 42 | +Run `dotnet format` before `dotnet build` locally to avoid spurious failures. |
| 43 | + |
| 44 | +### Focused test runs |
| 45 | + |
| 46 | +```bash |
| 47 | +dotnet test --filter "ClassName=GeopackTests" |
| 48 | +dotnet test --filter "FullyQualifiedName~Recalc" |
| 49 | +``` |
| 50 | + |
| 51 | +--- |
| 52 | + |
| 53 | +## Build Configuration |
| 54 | + |
| 55 | +Source of truth is `Directory.Build.props` and `global.json`, not README or CI workflow. |
| 56 | + |
| 57 | +- **Target frameworks:** `net8.0;net10.0` (multi-targeted) |
| 58 | +- **SDK pin:** `10.0.100`, roll-forward `patch` (`global.json`) — CI currently uses 9.0.x (discrepancy in workflow, local dev requires .NET 10 SDK) |
| 59 | +- **Nullable:** enabled; **TreatWarningsAsErrors:** enabled |
| 60 | +- **Versioning:** `PackageBaseVersion` in root `Directory.Build.props` + `MinVerVersionOverride` injected by CI bash script. Do **not** set `<Version>` or `<PackageVersion>` in any `.csproj`. |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +## Code Style (`.editorconfig` enforced as errors) |
| 65 | + |
| 66 | +- **`var` is banned** — always use explicit types (`var` triggers an error) |
| 67 | +- Private/internal fields: `_camelCase` prefix (error) |
| 68 | +- Constants: `PascalCase` (error) |
| 69 | +- Static private/internal fields: `s_` prefix (suggestion, not error) |
| 70 | +- Allman braces (`csharp_new_line_before_open_brace = all`) |
| 71 | +- `using` directives outside namespace |
| 72 | +- 4-space indent for C#; 2-space for XML/props/csproj |
| 73 | + |
| 74 | +--- |
| 75 | + |
| 76 | +## Testing |
| 77 | + |
| 78 | +- **Framework:** xUnit v3 + Shouldly only. **No Moq, no AutoFixture** — this repo has no mocking needs. |
| 79 | +- **Test project path:** `UnitTests/` at the repo root (not `tests/UnitTests/`) |
| 80 | +- **Assembly name:** `AuroraScienceHub.Geopack.UnitTests` |
| 81 | + |
| 82 | +### Reference data |
| 83 | + |
| 84 | +Tests validate against Fortran-generated `.dat` files compiled with Intel Fortran Compiler (`ifx`). These are embedded resources: |
| 85 | + |
| 86 | +- Location: `UnitTests/Geopack/TestData/*.dat` |
| 87 | +- Embedded as: `AuroraScienceHub.Geopack.UnitTests.Geopack.TestData.<FileName>.dat` |
| 88 | +- Fortran sources for regeneration: `UnitTests/Geopack/FortranSource/`, `UnitTests/ExternalFieldModels/FortranSource/` |
| 89 | + |
| 90 | +Tests use `TestDataFixture` (xUnit collection fixture) to load `.dat` data once per test run — loading is expensive, do not move tests outside the collection. |
| 91 | + |
| 92 | +Precision constant for Geopack tests: `8E-12`. For ExternalFieldModels: `1E-13`. |
| 93 | + |
| 94 | +### Test naming conventions |
| 95 | + |
| 96 | +- Class: `{ClassUnderTest}Tests` (partial classes per method group, e.g., `GeopackTests.Recalc.cs`) |
| 97 | +- Method: `{Method}_{Scenario}_{ExpectedBehavior}` |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +## NuGet Dependencies |
| 102 | + |
| 103 | +All versions managed centrally in `Directory.Packages.props`. Never add `Version=` to individual `.csproj` files. When adding a dependency, justify it — BCL is preferred. |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## CI/CD |
| 108 | + |
| 109 | +`.github/workflows/dotnet.yml`: |
| 110 | + |
| 111 | +| Trigger | Result | |
| 112 | +|---|---| |
| 113 | +| Push to any non-`main` branch | Pre-release → GitHub Packages | |
| 114 | +| Push to `main` | `{base}.{runNumber}` → NuGet.org | |
| 115 | +| Semver tag (`*.*.*`) | Stable `{base}` → NuGet.org | |
| 116 | + |
| 117 | +Version is computed via bash script in CI using `MinVerVersionOverride`, not MinVer git-tag discovery. Do not rely on `git tag` for versioning locally. |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +## Public API Constraints |
| 122 | + |
| 123 | +Published packages have downstream consumers. Treat any public API change as a potential breaking change: |
| 124 | +- Prefer additive changes |
| 125 | +- Never rename or remove public types/members without explicit approval |
| 126 | +- All public types and members require XML doc comments |
| 127 | +- Use `internal sealed` by default; expose only what consumers need |
| 128 | + |
| 129 | +## Do's and Don'ts |
| 130 | + |
| 131 | +### Do |
| 132 | + |
| 133 | +- ✅ Use central package management (`Directory.Packages.props`) for all dependencies |
| 134 | +- ✅ Follow existing patterns in the codebase |
| 135 | +- ✅ Use XML doc comments on public API surface |
| 136 | +- ✅ Use `internal` and `sealed` modifiers by default; only expose what consumers need |
| 137 | +- ✅ Preserve public API compatibility for published packages unless a breaking change is explicitly requested |
| 138 | +- ✅ Validate changes compile with warnings-as-errors enabled |
| 139 | +- ✅ Use async/await for all I/O operations |
| 140 | +- ✅ Write tests for new functionality before or alongside implementation |
| 141 | +- ✅ Keep functions small and focused |
| 142 | +- ✅ Keep packages focused — one responsibility per package |
| 143 | + |
| 144 | +### Don't |
| 145 | + |
| 146 | +- ❌ Suppress warnings with `#pragma` or `<NoWarn>` without justification |
| 147 | +- ❌ Add `Version` attributes to individual `.csproj` files |
| 148 | +- ❌ Modify `Directory.Build.props` or `Directory.Packages.props` without explicit request |
| 149 | +- ❌ Add dependencies that duplicate BCL functionality |
| 150 | +- ❌ Add dependencies without justification |
| 151 | +- ❌ Leave empty catch blocks or swallow exceptions silently |
| 152 | +- ❌ Use `dynamic` or reflection where generics/interfaces suffice |
| 153 | +- ❌ Break public API contracts (this is a library — consumers depend on stability) |
| 154 | +- ❌ Rename, remove, or materially change behavior of published public APIs without explicit approval |
| 155 | +- ❌ Skip nullable annotations on public APIs |
| 156 | + |
| 157 | +--- |
| 158 | + |
| 159 | +## Success Indicators |
| 160 | + |
| 161 | +These principles are working if you see: |
| 162 | + |
| 163 | +- Fewer unnecessary changes in diffs |
| 164 | +- Fewer rewrites due to overcomplication |
| 165 | +- Clarifying questions come before implementation (not after mistakes) |
| 166 | +- Clean, minimal PRs without drive-by refactoring |
| 167 | +- Tests that document expected behavior |
0 commit comments