|
1 | | -# Repository Guidelines |
2 | | - |
3 | | -This repo provides an Orleans-backed SignalR backplane. Use the conventions below to keep contributions consistent and easy to review. |
4 | | - |
5 | | -## Project Structure & Module Organization |
6 | | -- `ManagedCode.Orleans.SignalR.Core` — core types, options, and helpers shared by all modules. |
7 | | -- `ManagedCode.Orleans.SignalR.Client` — client integration extensions. |
8 | | -- `ManagedCode.Orleans.SignalR.Server` — Orleans grains and server-side plumbing. |
9 | | -- `ManagedCode.Orleans.SignalR.Tests` — xUnit tests and a minimal test host under `TestApp/`. |
10 | | -- `ManagedCode.Orleans.SignalR.slnx` and `Directory.Build.props` — solution and central build settings (net9.0, C# 13, analyzers, nullable). |
11 | | - |
12 | | -## Build, Test, and Development Commands |
13 | | -- Restore/build: `dotnet restore` • `dotnet build -c Debug` |
14 | | -- Run tests: `dotnet test -c Debug` (xUnit; Coverlet collector is enabled for coverage) |
15 | | -- Filter tests: `dotnet test --filter "FullyQualifiedName~PartitioningTests"` |
16 | | -- Pack NuGet: `dotnet pack -c Release` |
17 | | -- Format: `dotnet format` (run before committing) |
18 | | - |
19 | | -## Coding Style & Naming Conventions |
20 | | -- C#: 4‑space indent; file‑scoped namespaces; `Nullable` enabled; `EnableNETAnalyzers=true`. |
21 | | -- Naming: PascalCase for types/members; camelCase for locals/parameters; interfaces prefixed `I`. |
22 | | -- Domain naming: Orleans grain classes end with `Grain` (e.g., `SignalRGroupGrain`); namespaces start with `ManagedCode.Orleans.SignalR.*`. |
23 | | -- Prefer explicit access modifiers, `readonly` where applicable, and expression‑bodied members when clearer. |
24 | | - |
25 | | -## Testing Guidelines |
26 | | -- Framework: xUnit with `[Fact]`/`[Theory]`. Tests live in `ManagedCode.Orleans.SignalR.Tests` and end with `*Tests.cs`. |
27 | | -- Cluster tests: use Orleans TestingHost utilities; keep tests deterministic and isolated. |
28 | | -- Coverage: keep or increase coverage on core logic. Example: `dotnet test -c Debug --collect:"XPlat Code Coverage"`. |
29 | | - |
30 | | -## Commit & Pull Request Guidelines |
31 | | -- Commits: short, imperative subject lines. History shows concise tags like “fix”, “tests”, “refactoring” — keep using them. |
32 | | - - Examples: `fix: avoid deadlock in invocation`, `tests: improve group partitioning suite`. |
33 | | -- PRs: include a clear description, linked issues, rationale, and how you tested. Add/adjust tests with behavior changes and update README if public APIs change. |
34 | | -- CI hygiene: run `dotnet build` and `dotnet test` locally and ensure `dotnet format` yields no diffs before opening a PR. |
35 | | - |
36 | | -## Security & Configuration Tips |
37 | | -- Do not commit secrets or connection strings. Tests should use the provided in‑memory/TestHost setup. |
38 | | -- Configuration lives in code and `Directory.Build.props`; discuss before introducing new external dependencies. |
| 1 | +# AGENTS.md |
39 | 2 |
|
| 3 | +Project: Orleans.SignalR (ManagedCode.Orleans.SignalR) |
| 4 | +Stack: C# (LangVersion 14) on .NET 10 (net10.0), Microsoft Orleans 9.2.1, ASP.NET Core SignalR 10.0.0, xUnit 2.9.3, Shouldly 4.3.0, Coverlet 6.0.4 |
| 5 | + |
| 6 | +Follows [MCAF](https://mcaf.managed-code.com/) |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## Conversations (Self-Learning) |
| 11 | + |
| 12 | +Learn the user's habits, preferences, and working style. Extract rules from conversations, save to "## Rules to follow", and generate code according to the user's personal rules. |
| 13 | + |
| 14 | +**Update requirement (core mechanism):** |
| 15 | + |
| 16 | +Before doing ANY task, evaluate the latest user message. |
| 17 | +If you detect a new rule, correction, preference, or change -> update `AGENTS.md` first. |
| 18 | +Only after updating the file you may produce the task output. |
| 19 | +If no new rule is detected -> do not update the file. |
| 20 | + |
| 21 | +**When to extract rules:** |
| 22 | + |
| 23 | +- prohibition words (never, don't, stop, avoid) or similar -> add NEVER rule |
| 24 | +- requirement words (always, must, make sure, should) or similar -> add ALWAYS rule |
| 25 | +- memory words (remember, keep in mind, note that) or similar -> add rule |
| 26 | +- process words (the process is, the workflow is, we do it like) or similar -> add to workflow |
| 27 | +- future words (from now on, going forward) or similar -> add permanent rule |
| 28 | + |
| 29 | +**Preferences -> add to Preferences section:** |
| 30 | + |
| 31 | +- positive (I like, I prefer, this is better) or similar -> Likes |
| 32 | +- negative (I don't like, I hate, this is bad) or similar -> Dislikes |
| 33 | +- comparison (prefer X over Y, use X instead of Y) or similar -> preference rule |
| 34 | + |
| 35 | +**Corrections -> update or add rule:** |
| 36 | + |
| 37 | +- error indication (this is wrong, incorrect, broken) or similar -> fix and add rule |
| 38 | +- repetition frustration (don't do this again, you ignored, you missed) or similar -> emphatic rule |
| 39 | +- manual fixes by user -> extract what changed and why |
| 40 | + |
| 41 | +**Strong signal (add IMMEDIATELY):** |
| 42 | + |
| 43 | +- swearing, frustration, anger, sarcasm -> critical rule |
| 44 | +- ALL CAPS, excessive punctuation (!!!, ???) -> high priority |
| 45 | +- same mistake twice -> permanent emphatic rule |
| 46 | +- user undoes your changes -> understand why, prevent |
| 47 | + |
| 48 | +**Ignore (do NOT add):** |
| 49 | + |
| 50 | +- temporary scope (only for now, just this time, for this task) or similar |
| 51 | +- one-off exceptions |
| 52 | +- context-specific instructions for current task only |
| 53 | + |
| 54 | +**Rule format:** |
| 55 | + |
| 56 | +- One instruction per bullet |
| 57 | +- Tie to category (Testing, Code, Docs, etc.) |
| 58 | +- Capture WHY, not just what |
| 59 | +- Remove obsolete rules when superseded |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## Rules to follow (Mandatory, no exceptions) |
| 64 | + |
| 65 | +### Commands |
| 66 | + |
| 67 | +- build: `dotnet restore` then `dotnet build -c Debug` |
| 68 | +- test: `dotnet test -c Debug` |
| 69 | +- format: `dotnet format` |
| 70 | +- coverage: `dotnet test -c Debug --collect:"XPlat Code Coverage"` |
| 71 | + |
| 72 | +### Task Delivery (ALL TASKS) |
| 73 | + |
| 74 | +- Always start from the architecture map in `docs/Architecture/Overview.md`: |
| 75 | + - confirm the Mermaid diagrams exist and are up to date (if missing/outdated -> update them first): |
| 76 | + - system/module map (blocks/modules + dependency direction) |
| 77 | + - interfaces/contracts map (APIs/events/interfaces between modules) |
| 78 | + - key classes/types map (high-signal types only; not an inventory) |
| 79 | + - `docs/Architecture/Overview.md` is the primary "start here" card for humans and AI agents: |
| 80 | + - diagram elements must use real names (no placeholders like "Module A") |
| 81 | + - every diagram element must be anchored to reality via links in the same file (feature docs, ADRs, code paths, or entry-point files) |
| 82 | + - keep diagrams readable; if a diagram becomes "spaghetti", split by boundary and link out |
| 83 | + - keep the file short: prefer diagrams + a tiny link index over large tables or inventories (optimize token footprint) |
| 84 | + - identify the impacted boundary/module(s) and entry points |
| 85 | + - follow the links to the relevant ADR(s) and Feature doc(s) (do not read everything) |
| 86 | +- Scope first (prevent context overload): |
| 87 | + - use `docs/Architecture/Overview.md` -> "Scoping (read first)" |
| 88 | + - write **in scope / out of scope** (what will change and what must not change) |
| 89 | + - if you cannot identify scope from the architecture map -> stop and fix the map (or ask one clarifying question) |
| 90 | +- Context engineering (hard requirement): |
| 91 | + - keep only the context needed for the task (avoid repo-wide scanning and "read everything") |
| 92 | + - if you need a doc/module that isn't reachable from `docs/Architecture/Overview.md`, update the overview to link it |
| 93 | +- Skills (workflow packages): |
| 94 | + - if the task matches an existing skill's description, follow that skill's workflow instead of improvising |
| 95 | + - if a skill is missing or drifting from reality, update the skill so the fix is permanent |
| 96 | +- Analyze first (no coding yet): |
| 97 | + - what exists today (facts only) |
| 98 | + - what must change / must not change |
| 99 | + - unknowns and risks (what must be clarified) |
| 100 | +- Create a written plan before implementation: |
| 101 | + - for architecture/decision work: keep the plan as `## Implementation plan (step-by-step)` in the ADR |
| 102 | + - for behaviour work: keep the plan as `## Implementation plan (step-by-step)` in the Feature doc |
| 103 | + - update the plan while executing (tick items / update statuses as work is completed) |
| 104 | +- Implement code and tests together |
| 105 | +- If `build` is separate from `test`, run `build` before `test` |
| 106 | +- Verification timing (optimize time + tokens): |
| 107 | + - do not run `test`/`coverage` "just because" before you wrote/changed code or tests (exception: reproducing a bug / confirming baseline) |
| 108 | + - while iterating, run the smallest meaningful scope (new/changed tests first) |
| 109 | + - run broader suites only when you have something real to verify (avoid re-running the same command without changes) |
| 110 | + - run coverage once per change (it is heavier than tests) |
| 111 | +- Run tests in layers: new/changed -> related suite -> broader regressions |
| 112 | +- After tests pass: run format |
| 113 | +- After format: run build (final check) |
| 114 | +- Summarize changes and test results before marking complete |
| 115 | +- Always run required builds and tests yourself; do not ask the user to execute them (explicit user directive) |
| 116 | +- Commit messages are short and imperative; common prefixes in history include `fix:`, `tests:`, and `code style` |
| 117 | + |
| 118 | +### Documentation (ALL TASKS) |
| 119 | + |
| 120 | +- All docs live in `docs/` (or `.wiki/`) |
| 121 | +- Global architecture entry point: `docs/Architecture/Overview.md` (read first) |
| 122 | +- Single source of truth (no duplication): |
| 123 | + - each important fact/rule/diagram lives in exactly one canonical place; other docs should link, not copy |
| 124 | + - `docs/Architecture/Overview.md` is coarse and navigational (diagrams + links), not the place for detailed behaviour |
| 125 | + - detailed behaviour belongs in `docs/Features/*`; detailed decisions/invariants belong in `docs/ADR/*` |
| 126 | + - if you need detail, follow the link; only add new text when there is no canonical place yet |
| 127 | +- When creating docs from templates: |
| 128 | + - copy the template into its real docs location |
| 129 | + - replace all placeholders and remove all template notes (real docs must be clean: no `TEMPLATE ONLY`) |
| 130 | +- Update feature docs when behaviour changes |
| 131 | +- Update ADRs when architecture changes |
| 132 | +- Diagrams are mandatory in docs: |
| 133 | + - `docs/Architecture/Overview.md`: Mermaid diagrams for system/modules + interfaces/contracts + key classes/types (must render) |
| 134 | + - every diagram element has a real reference link in the same file (docs/code), so an agent can navigate without repo-wide scanning |
| 135 | + - `docs/Features/*`: at least one Mermaid diagram for the main flow |
| 136 | + - `docs/ADR/*`: at least one Mermaid diagram for the decision |
| 137 | +- Mermaid hygiene (Mermaid often breaks if you freestyle it): |
| 138 | + - diagrams must render in repo Markdown preview (broken Mermaid is treated as broken documentation) |
| 139 | + - prefer simple Mermaid syntax (`flowchart` / `sequenceDiagram`); use short ASCII-only IDs |
| 140 | + - if `classDiagram` is flaky in your renderer, replace it with a `flowchart` that shows the same relationships |
| 141 | + - if a diagram doesn't render, simplify it until it does (no "close enough") |
| 142 | + |
| 143 | +### Testing (ALL TASKS) |
| 144 | + |
| 145 | +- Framework: xUnit + Shouldly; tests live in `ManagedCode.Orleans.SignalR.Tests` and end with `*Tests.cs` |
| 146 | +- Integration tests use Orleans TestingHost with fixtures in `ManagedCode.Orleans.SignalR.Tests/Cluster` and the minimal host in `ManagedCode.Orleans.SignalR.Tests/TestApp` |
| 147 | +- Prefer TDD for new behaviour and bugfixes: write a failing test first, then implement the smallest change to make it pass, then refactor safely |
| 148 | +- Every behaviour change needs sufficient automated tests to cover its cases; one is the minimum, not the target |
| 149 | +- Each public API endpoint has at least one test; complex endpoints have tests for different inputs and errors |
| 150 | +- Integration tests must exercise real flows end-to-end, not just call endpoints in isolation |
| 151 | +- Prefer integration/API/UI tests over unit tests |
| 152 | +- Prefer the minimum set of high-value tests that proves behaviour; invest in diagrams for understanding and safe change |
| 153 | +- No mocks for internal systems (DB, queues, caches) - use containers |
| 154 | +- Mocks only for external third-party systems |
| 155 | +- Never delete or weaken a test to make it pass |
| 156 | +- Each test verifies a real flow or scenario, not just calls a function - tests without meaningful assertions are forbidden |
| 157 | +- Check code coverage to see which functionality is actually tested; coverage is for finding gaps, not a number to chase |
| 158 | +- Flaky tests are failures: fix the test or the underlying behaviour, don't "retry until green" |
| 159 | + |
| 160 | +### Autonomy |
| 161 | + |
| 162 | +- Start work immediately - no permission seeking |
| 163 | +- Questions only for architecture blockers not covered by ADR |
| 164 | +- Report only when task is complete |
| 165 | + |
| 166 | +### Advisor stance (ALL TASKS) |
| 167 | + |
| 168 | +- Stop being agreeable: be direct and honest; no flattery, no validation, no sugar-coating |
| 169 | +- Challenge weak reasoning; point out missing assumptions and trade-offs |
| 170 | +- If something is underspecified/contradictory/risky - say so and list what must be clarified |
| 171 | +- Never guess or invent. If unsure, say "I don't know" and propose how to verify |
| 172 | +- Quality and security first: tests + static analysis are gates; treat security regressions as blockers |
| 173 | + |
| 174 | +### Code Style |
| 175 | + |
| 176 | +- Style rules: `.editorconfig` (Allman braces, file-scoped namespaces, var usage, underscore prefix for private/internal fields, primary constructors preferred) |
| 177 | +- Language/runtime: `net10.0`, C# 14, `Nullable` enabled, `EnableNETAnalyzers=true`, `TreatWarningsAsErrors=true` |
| 178 | +- Naming: PascalCase for types/constants, camelCase for locals/parameters, async methods end with Async (except Hubs/Controllers) |
| 179 | +- Avoid `this.` qualification; prefer predefined types (`int` over `Int32`) |
| 180 | +- Never use `ConfigureAwait(false)` |
| 181 | +- No magic literals - extract to constants, enums, config |
| 182 | + |
| 183 | +### Critical (NEVER violate) |
| 184 | + |
| 185 | +- Never commit secrets, keys, connection strings |
| 186 | +- Never mock internal systems in integration tests |
| 187 | +- Never skip tests to make PR green |
| 188 | +- Never force push to main |
| 189 | +- Never approve or merge (human decision) |
| 190 | + |
| 191 | +### Boundaries |
| 192 | + |
| 193 | +**Protected areas:** |
| 194 | +- Public API surface: `ManagedCode.Orleans.SignalR.Core/Interfaces`, `ManagedCode.Orleans.SignalR.Core/Config/OrleansSignalROptions.cs`, `ManagedCode.Orleans.SignalR.Core/HubContext`, `ManagedCode.Orleans.SignalR.Client/Extensions` |
| 195 | +- Lifetime manager and routing: `ManagedCode.Orleans.SignalR.Core/SignalR/OrleansHubLifetimeManager.cs`, `ManagedCode.Orleans.SignalR.Core/Helpers/PartitionHelper.cs` |
| 196 | +- Server grains and persistence: `ManagedCode.Orleans.SignalR.Server/*Grain.cs`, `ManagedCode.Orleans.SignalR.Server/Storage` |
| 197 | +- Test infrastructure: `ManagedCode.Orleans.SignalR.Tests/Cluster`, `ManagedCode.Orleans.SignalR.Tests/TestApp` |
| 198 | + |
| 199 | +**Always:** |
| 200 | + |
| 201 | +- Read AGENTS.md and docs before editing code |
| 202 | +- Run tests before commit |
| 203 | + |
| 204 | +**Ask first:** |
| 205 | + |
| 206 | +- Changing public API contracts |
| 207 | +- Adding new dependencies |
| 208 | +- Modifying database schema |
| 209 | +- Deleting code files |
| 210 | + |
| 211 | +--- |
| 212 | + |
| 213 | +## Preferences |
| 214 | + |
| 215 | +### Likes |
| 216 | + |
| 217 | +### Dislikes |
| 218 | + |
| 219 | +- Leaving placeholder text in docs or AGENTS; replace with real values |
0 commit comments