|
| 1 | +# Copilot Instructions for Equinox |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +Equinox is a set of low-dependency F# libraries for event-sourced processing against stream-based stores. |
| 6 | +It is **not a framework**; consumers compose the libraries to fit their needs. |
| 7 | + |
| 8 | +Related repositories: |
| 9 | +- [FsCodec](https://github.com/jet/FsCodec) — encoding/decoding events |
| 10 | +- [Propulsion](https://github.com/jet/propulsion) — projections and reactions |
| 11 | +- [dotnet-templates](https://github.com/jet/dotnet-templates) — starter project templates |
| 12 | + |
| 13 | +## Repository Layout |
| 14 | + |
| 15 | +| Path | Contents | |
| 16 | +|------|----------| |
| 17 | +| `src/Equinox` | Core library: `Decider`, `Cache`, optimistic concurrency | |
| 18 | +| `src/Equinox.Core` | Shared utilities: `TaskCell`, `Batcher` | |
| 19 | +| `src/Equinox.CosmosStore` | Azure Cosmos DB adapter | |
| 20 | +| `src/Equinox.DynamoStore` | Amazon DynamoDB adapter | |
| 21 | +| `src/Equinox.EventStoreDb` | EventStoreDB (gRPC) adapter | |
| 22 | +| `src/Equinox.MessageDb` | MessageDB (Postgres) adapter | |
| 23 | +| `src/Equinox.MemoryStore` | In-memory store for testing | |
| 24 | +| `src/Equinox.EventStore` | Legacy EventStore TCP adapter (deprecated) | |
| 25 | +| `src/Equinox.SqlStreamStore*` | SqlStreamStore adapters (unmaintained upstream) | |
| 26 | +| `src/Equinox.*.Prometheus` | Prometheus metrics sinks | |
| 27 | +| `tests/` | Unit and integration tests (xUnit v3, MTP v2) | |
| 28 | +| `samples/` | Tutorial scripts, TodoBackend, sample store | |
| 29 | +| `tools/Equinox.Tool` | CLI tool for provisioning and benchmarking | |
| 30 | + |
| 31 | +## Language and Style |
| 32 | + |
| 33 | +- The codebase is **F#**. Follow existing conventions when editing. |
| 34 | +- 4-space indentation, LF line endings, trim trailing whitespace (see `.editorconfig`). |
| 35 | +- `TreatWarningsAsErrors` is enabled globally — all warnings are errors. |
| 36 | +- Prefer minimal dependencies; Equinox intentionally keeps its dependency footprint small. |
| 37 | +- Do not add comments unless they match the existing style or explain something non-obvious. |
| 38 | + |
| 39 | +## Building and Testing |
| 40 | + |
| 41 | +- **SDK**: .NET 10 (see `global.json` for exact version; `rollForward: latestMajor`). |
| 42 | +- **Test runner**: Microsoft Testing Platform v2 (configured in `global.json` `"test"` section). |
| 43 | +- **Build**: |
| 44 | + ```sh |
| 45 | + dotnet build -c Release |
| 46 | + ``` |
| 47 | +- **Test** (CI style): |
| 48 | + ```sh |
| 49 | + dotnet test -c Release --report-xunit-trx --ignore-exit-code 8 --results-directory tests/trx |
| 50 | + ``` |
| 51 | + Exit code 8 means all tests in an assembly were skipped (expected in CI without Docker stores). |
| 52 | +- **Repository build**: |
| 53 | + ```sh |
| 54 | + dotnet build -c Release |
| 55 | + ``` |
| 56 | +- Integration test skip flags (set to `true` to skip): |
| 57 | + - `EQUINOX_INTEGRATION_SKIP_EVENTSTORE` |
| 58 | + - `EQUINOX_INTEGRATION_SKIP_COSMOS` |
| 59 | +- CI-only packaging behavior is activated when either `CI=true` or Azure Pipelines provides `TF_BUILD`; packable projects under `src/` and `tools/` enable documentation-file generation and package validation from their local `Directory.Build.props`. |
| 60 | +- CI runs on Azure Pipelines across Windows, Linux, and macOS. |
| 61 | + |
| 62 | +## Key Design Patterns |
| 63 | + |
| 64 | +- **Decider pattern**: Domain logic lives in `decide`/`interpret` functions that take state and return events. |
| 65 | + The `Decider<'event, 'state>` type manages the optimistic concurrency loop. |
| 66 | +- **`IEventCodec`**: All serialization is expressed via `FsCodec.IEventCodec`. Use `FsCodec.SystemTextJson.Codec` or `FsCodec.NewtonsoftJson.Codec`. |
| 67 | +- **Access Strategies**: Each store adapter provides strategies for snapshots/unfolds |
| 68 | + (e.g., `RollingState`, `Snapshot`, `Tip with Unfolds` for CosmosStore). |
| 69 | +- **Caching**: `Equinox.Cache` wraps `System.Runtime.Caching.MemoryCache` to minimize store round-trips. |
| 70 | +- **Store agnosticism**: Domain code should never reference a specific store package. |
| 71 | + Store wiring is the responsibility of the application composition root. |
| 72 | + |
| 73 | +## PR and Contribution Guidelines |
| 74 | + |
| 75 | +- See `CONTRIBUTING.md` — new features start at −100 points; keep changes focused. |
| 76 | +- Ensure tests pass before submitting. Do not remove or weaken existing tests. |
| 77 | +- Use `CHANGELOG.md` conventions when documenting user-facing changes. |
0 commit comments