Skip to content

Commit 7c1ca92

Browse files
committed
Refactors agent guidelines for clarity
Streamlines agent guidelines by introducing a top-level `AGENTS.md` file and refactoring existing guidelines into more specific, scoped files. This improves discoverability and focuses guidance for different areas of the project.
1 parent 6333333 commit 7c1ca92

File tree

5 files changed

+176
-65
lines changed

5 files changed

+176
-65
lines changed

.github/copilot-instructions.md

Lines changed: 0 additions & 24 deletions
This file was deleted.

AGENTS.md

Lines changed: 151 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
# Agent Guidelines for the Exceptionless Repository
22

3-
You are contributing to **Exceptionless**, a real-time error monitoring platform. Backend services run on .NET 10; the SPA lives in `src/Exceptionless.Web/ClientApp` (Svelte 5 + TypeScript).
3+
You are an expert engineer working on Exceptionless, a production-grade real-time error monitoring platform handling billions of requests. Your changes must maintain backward compatibility, performance, and reliability. Approach each task methodically: research existing patterns, make surgical changes, and validate thoroughly.
44

5-
## Quick Start
6-
7-
Run `Exceptionless.AppHost` from your IDE. Aspire automatically starts all required services (Elasticsearch, Redis, Mailpit) with proper ordering. The Aspire dashboard opens at the assigned localhost port.
5+
**Craftsmanship Mindset**: Every line of code should be intentional, readable, and maintainable. Write code you'd be proud to have reviewed by senior engineers. Prefer simplicity over cleverness. When in doubt, favor explicitness and clarity.
86

9-
**Alternative (infrastructure only):**
7+
## Quick Start
108

11-
```bash
12-
cd docker && docker compose up -d elasticsearch redis mail
13-
```
9+
Run `Exceptionless.AppHost` from your IDE. Aspire automatically starts all required services (Elasticsearch, Redis) with proper ordering. The Aspire dashboard opens at the assigned localhost port, resources and logs can be accessed via the Aspire MCP.
1410

1511
## Scoped Guidance
1612

@@ -27,7 +23,7 @@ Follow the AGENTS.md closest to the code you're changing:
2723

2824
### Prerequisites
2925

30-
- **.NET SDK 10.0** — pinned in `global.json`
26+
- **.NET SDK 10.0**
3127
- **Node 24+**
3228
- **npm** — use the committed `package-lock.json`
3329

@@ -56,46 +52,168 @@ npm run build
5652
## Project Structure
5753

5854
```text
59-
src/
55+
src
6056
├── Exceptionless.AppHost # Aspire orchestrator (start here for full stack)
6157
├── Exceptionless.Core # Domain logic and services
6258
├── Exceptionless.Insulation # Concrete implementations (Elasticsearch, Redis, etc.)
6359
├── Exceptionless.Web # ASP.NET Core API + SPA host
6460
│ └── ClientApp # Svelte 5 SPA (primary client)
6561
│ └── ClientApp.angular # Angular SPA (legacy client)
6662
└── Exceptionless.Job # Background workers
67-
68-
tests/ # C# integration/unit tests + HTTP samples
69-
docker/ # Compose files for local services
70-
build/ # Scripts and templates
63+
tests # C# integration/unit tests + HTTP samples
64+
docker # Compose files for local services
65+
build # Scripts and templates
7166
```
7267

7368
## Coding Standards
7469

75-
- Follow `.editorconfig` (4 spaces, file-scoped namespaces, usings outside namespaces, braces for all control blocks).
76-
- **C#:** Use explicit types when obvious; `var` is acceptable elsewhere per `.editorconfig`. Private fields `_camelCase`, static fields `s_camelCase`, public members PascalCase. Honor nullable annotations; keep files trimmed with a final newline.
77-
- **TypeScript/Svelte:** Follow ESLint/Prettier config and the frontend AGENTS. Use kebab-case filenames, prefer named imports, avoid namespace imports except allowed barrels/shadcn. Always await async work and keep single-line control statements wrapped in braces.
78-
- **Accessibility:** Meet WCAG 2.2 AA; ensure keyboard navigation, semantic landmarks, correct roles/labels, and proper alt text. Follow the frontend AGENTS for detailed patterns.
79-
- Avoid unnecessary abstractions; match existing patterns before introducing new ones.
80-
- **Comments:** Keep minimal; prefer self-explanatory code and existing patterns.
70+
### Style & Formatting
71+
72+
- Follow `.editorconfig` rules strictly—4 spaces, file-scoped namespaces, usings outside namespaces, braces for all control blocks
73+
- Run formatters before committing: `dotnet format` for C#, `npm run format` for frontend
74+
- Match existing file style; minimize diffs
75+
- No code comments unless necessary—code should be self-explanatory
76+
77+
### C# Conventions
78+
79+
- **Naming:** Private fields `_camelCase`. public members PascalCase
80+
- **Types:** Use explicit types when obvious; `var` is acceptable elsewhere per `.editorconfig`
81+
- **Nullable:** Honor nullable annotations and treat warnings as errors
82+
- **Async:** Use `Async` suffix, pass `CancellationToken` through call chains, prefer `ValueTask<T>` for hot paths
83+
- **Resources:** Always dispose properly with `using` statements or `IAsyncDisposable`
84+
85+
### TypeScript/Svelte Conventions
86+
87+
- Follow ESLint/Prettier config strictly
88+
- Use kebab-case filenames, prefer named imports
89+
- Avoid namespace imports except allowed barrels/shadcn
90+
- Always await Promises; handle errors with try/catch
91+
- Avoid `any`—use interfaces/types and type guards
92+
93+
### Single Responsibility
94+
95+
- Each class/component has one reason to change
96+
- Methods do one thing well; extract when doing multiple things
97+
- Keep files focused: one primary type per file
98+
- Separate concerns: don't mix I/O, business logic, and presentation
99+
- If a method needs a comment explaining what it does, it should probably be extracted
100+
101+
### Accessibility (WCAG 2.2 AA)
102+
103+
- Semantic landmarks and keyboard-first navigation
104+
- Correct roles/labels and proper alt text
105+
- Follow the frontend AGENTS for detailed patterns
81106

82107
## Making Changes
83108

84-
- Keep diffs surgical and match surrounding patterns. Ask before adding new files or changing structure.
85-
- Preserve existing behavior unless explicitly changing it; assume uncommitted code is correct.
86-
- Run the relevant build/test commands (backend and/or frontend) before handing off changes.
87-
- Flag user-visible changes. Prefer small, logical commits.
88-
- Use context7 when you need code generation, setup/config steps, or library/API docs.
109+
### Before Starting
110+
111+
1. **Gather context**: Read related files, search for similar implementations, understand the full scope
112+
2. **Research patterns**: Find existing usages of the code you're modifying using grep/semantic search
113+
3. **Understand completely**: Know the problem, side effects, and edge cases before coding
114+
4. **Plan the approach**: Choose the simplest solution that satisfies all requirements
115+
5. **Check dependencies**: Verify you understand how changes affect dependent code
116+
117+
### Pre-Implementation Analysis
118+
119+
Before writing any implementation code, think critically:
120+
121+
1. **What could go wrong?** Consider race conditions, null references, edge cases, resource exhaustion
122+
2. **What are the failure modes?** Network failures, timeouts, out-of-memory, concurrent access
123+
3. **What assumptions am I making?** Validate each assumption against the codebase
124+
4. **Is this the root cause?** Don't fix symptoms—trace to the core problem
125+
5. **Will this scale?** Consider performance under load, memory allocation patterns
126+
6. **Is there existing code that does this?** Search before creating new utilities
127+
128+
### Test-First Development
129+
130+
**Always write or extend tests before implementing changes:**
89131

90-
## Dependencies & Security
132+
1. **Find existing tests first**: Search for tests covering the code you're modifying
133+
2. **Extend existing tests**: Add test cases to existing test classes/methods when possible for maintainability
134+
3. **Write failing tests**: Create tests that demonstrate the bug or missing feature
135+
4. **Implement the fix**: Write minimal code to make tests pass
136+
5. **Refactor**: Clean up while keeping tests green
137+
6. **Verify edge cases**: Add tests for boundary conditions and error paths
91138

92-
- **NuGet:** Feeds are defined in `NuGet.Config` (Feedz + local `build/packages`); do not add new sources unless requested.
93-
- **SDK:** Shared settings live in `src/Directory.Build.props`; keep target frameworks/versioning consistent.
94-
- **npm:** Keep `package-lock.json` in sync and use `npm ci` for reproducible installs.
95-
- **Secrets:** Do not commit secrets. Follow secure coding practices and sanitize inputs.
139+
**Why extend existing tests?** Consolidates related test logic, reduces duplication, improves discoverability, maintains consistent test patterns.
140+
141+
### While Coding
142+
143+
- **Minimize diffs**: Change only what's necessary, preserve formatting and structure
144+
- **Preserve behavior**: Don't break existing functionality or change semantics unintentionally
145+
- **Build incrementally**: Run builds after each logical change to catch errors early
146+
- **Test continuously**: Run tests frequently to verify correctness
147+
- **Match style**: Follow the patterns in surrounding code exactly
148+
149+
### Validation
150+
151+
Before marking work complete, verify:
152+
153+
1. **Builds successfully**: Both backend and frontend compile without errors
154+
2. **All tests pass**: No test failures in affected areas
155+
3. **No new warnings**: Check build output for new compiler/linter warnings
156+
4. **API compatibility**: Public API changes are intentional and backward-compatible when possible
157+
5. **Breaking changes flagged**: Clearly identify any breaking changes for review
158+
159+
## Error Handling
160+
161+
- **Validate inputs**: Check for null, empty strings, invalid ranges at method entry
162+
- **Fail fast**: Throw exceptions immediately for invalid arguments (don't propagate bad data)
163+
- **Meaningful messages**: Include parameter names and expected values in exception messages
164+
- **Don't swallow exceptions**: Log and rethrow, or let propagate unless you can handle properly
165+
- **Use guard clauses**: Early returns for invalid conditions, keep happy path unindented
166+
167+
## Security
168+
169+
- **Validate all inputs**: Use guard clauses, check bounds, validate formats before processing
170+
- **Sanitize external data**: Never trust data from queues, caches, user input, or external sources
171+
- **No sensitive data in logs**: Never log passwords, tokens, keys, or PII
172+
- **Use secure defaults**: Default to encrypted connections, secure protocols, restricted permissions
173+
- **Follow OWASP guidelines**: Review [OWASP Top 10](https://owasp.org/www-project-top-ten/)
174+
- **No deprecated APIs**: Avoid obsolete cryptography, serialization, or framework features
175+
176+
## Dependencies
177+
178+
- **NuGet:** Feeds are defined in `NuGet.Config` (Feedz + local `build/packages`); do not add new sources unless requested
179+
- **SDK:** Shared settings live in `src/Directory.Build.props`; keep target frameworks/versioning consistent
180+
- **npm:** Keep `package-lock.json` in sync and use `npm ci` for reproducible installs
181+
- **Secrets:** Do not commit secrets; use environment variables or secret managers
96182

97183
## Testing Philosophy
98184

99-
- Write tests for new functionality and fix failures related to your changes; do not remove existing tests.
100-
- Keep tests fast, isolated, and self-checking. Use Arrange/Act/Assert and descriptive names.
101-
- Prefer the most targeted test layer (unit > integration > e2e) while covering critical paths end-to-end where it matters.
185+
Tests are not just validation—they're **executable documentation** and **design tools**. Well-tested code is:
186+
187+
- **Trustworthy**: Confidence to refactor and extend
188+
- **Documented**: Tests show how the API should be used
189+
- **Resilient**: Edge cases are covered before they become production bugs
190+
191+
### Test Principles (FIRST)
192+
193+
- **Fast**: Tests execute quickly
194+
- **Isolated**: No dependencies on external services or execution order
195+
- **Repeatable**: Consistent results every run
196+
- **Self-checking**: Tests validate their own outcomes
197+
- **Timely**: Write tests alongside code
198+
199+
### Test Layers
200+
201+
Prefer the most targeted test layer while covering critical paths end-to-end:
202+
203+
1. **Unit tests**: Fast, isolated, test single units of logic
204+
2. **Integration tests**: Test component interactions with real dependencies
205+
3. **E2E tests**: Test complete user workflows through the UI
206+
207+
## Resilience & Reliability
208+
209+
- **Expect failures**: Network calls fail, resources exhaust, concurrent access races
210+
- **Timeouts everywhere**: Never wait indefinitely; use cancellation tokens
211+
- **Retry with backoff**: Use exponential backoff with jitter for transient failures
212+
- **Graceful degradation**: Return cached data, default values, or partial results when appropriate
213+
- **Idempotency**: Design operations to be safely retryable
214+
- **Resource limits**: Bound queues, caches, and buffers to prevent memory exhaustion
215+
216+
## Resources
217+
218+
- Use context7 when you need code generation, setup/config steps, or library/API docs
219+
- Check existing patterns in the codebase before introducing new ones

src/AGENTS.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
# Backend Guidelines (C#)
22

3-
## Patterns & Practices
3+
## Architecture & Layering
44

5-
- Respect existing layering: keep domain logic in `Exceptionless.Core`, concrete implementations in `Exceptionless.Insulation`, hosting concerns in `Exceptionless.Web`, and background work in `Exceptionless.Job`.
6-
- Reuse existing services and option classes; prefer dependency injection over static access.
7-
- When touching configuration, prefer appsettings and options binding; avoid hardcoding secrets or connection info.
5+
```text
6+
Exceptionless.Core → Domain logic, services, interfaces
7+
Exceptionless.Insulation → Concrete implementations (ES, Redis, etc.)
8+
Exceptionless.Web → ASP.NET Core host, controllers, middleware
9+
Exceptionless.Job → Background Jobs
10+
```
11+
12+
- Keep domain logic in `Core`; concrete implementations in `Insulation`
13+
- Prefer dependency injection over static access
14+
- Use appsettings and options binding; never hardcode secrets
815

916
## Dependencies
1017

11-
- NuGet feeds come from `NuGet.Config`; do not add sources unless requested. Keep versions aligned with `src/Directory.Build.props`.
12-
- Avoid introducing new packages unless necessary; prefer existing dependencies already in the solution.
18+
- NuGet feeds from `NuGet.Config`; do not add sources unless requested
19+
- Keep versions aligned with `src/Directory.Build.props`
20+
- Avoid new packages unless necessary; prefer existing dependencies

src/Exceptionless.Web/AGENTS.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Web API Guidelines (Exceptionless.Web)
22

3-
## Scope
4-
53
Applies to the ASP.NET Core host in `src/Exceptionless.Web`, including controllers, middleware, configuration, and API-facing code. The Svelte SPA lives in `ClientApp`; the legacy Angular client is under `ClientApp.angular` (avoid changes there unless explicitly requested).
64

75
## API Development

tests/AGENTS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ dotnet test --filter "ClassName~OrganizationTests"
1919
dotnet test --filter "Category=Integration"
2020
```
2121

22+
## Test-First Workflow
23+
24+
1. **Search for existing tests**: Find tests covering the code you're modifying
25+
2. **Extend existing test classes**: Add new `[Fact]` or `[Theory]` cases to existing files for maintainability
26+
3. **Write the failing test first**: Verify it fails for the right reason
27+
4. **Implement minimal code**: Just enough to pass the test
28+
5. **Add edge case tests**: Null inputs, empty collections, boundary values
29+
6. **Run full test suite**: Ensure no regressions
30+
31+
**Why extend existing tests?** Consolidates related test logic, reduces duplication, improves discoverability.
32+
2233
## Framework & Best Practices
2334

2435
- Use xUnit as the primary testing framework

0 commit comments

Comments
 (0)