| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 2 | 1 | 0% |
| Commands | 0 | 0 | 0 | — |
| Section tags | 0 | 2 | 1 | 0% |
What each file covers
Sections
0 shared · 2 only in A · 1 only in B- − API Route Conventions
- − Error → status mapping (be consistent)
- + Claude Code
Commands
neither file has anySection tags
0 shared · 2 only in A · 1 only in B- − code-style
- − api
- + agent-behaviour
Line diff
jleist-clemson/acheron · .cursor/rules/api-routes.mdc
@@ −1 @@
1---
2description: FastAPI route conventions for the events API
3globs: app/api/**/*.py
4alwaysApply: false
5---
6
7# API Route Conventions
8
9- Routes are thin: validate input, call a service/store, shape the response.
10 No persistence, aggregation, or business logic in a handler.
11- Pull dependencies off `app.state` via the `Depends(_helper)` pattern (e.g.
12 `_mongo`, `_es`, `_cache`, `_ingestion`); don't reach into globals.
13- The events routes declare a Pydantic `response_model` from
14 `app/api/schemas.py`; `/health` (a status-code-driven `JSONResponse`) and
15 `/metrics` (a loose ops snapshot) are intentionally exempt. Nullable fields are
16 **always present** in the response (return explicit `null`, e.g. `total`,
17 `bucket`, `computed_at`) for a stable shape.
18
19# Error → status mapping (be consistent)
20
21Stores raise native exceptions; the route catches and maps them. Log at the
22boundary with the exception type, then raise `HTTPException`.
23
24| Condition | Status |
25|---|---|
26| Mongo (source of truth) unavailable | `503` |
27| Elasticsearch (derived) unavailable | `502` |
28| Queue full (backpressure) | `429` |
29| Service shutting down | `503` |
30
31```python
32try:
33 events, has_more, total = await mongo.find_events(...)
34except PyMongoError as exc:
35 logger.error("Mongo query failed (%s): %s", type(exc).__name__, exc)
36 raise HTTPException(status_code=503, detail="Event store temporarily unavailable")
37```
38
jleist-clemson/acheron · CLAUDE.md
@@ +1 @@
1@AGENTS.md
2
3@.claude/rules/python-standards.md
4@.claude/rules/api-routes.md
5@.claude/rules/testing.md
6@.claude/rules/elasticsearch-mapping.md
7@.claude/rules/background-tasks.md
8
9## Claude Code
10
11Shared, vendor-neutral project context lives in `AGENTS.md` (imported above).
12Project conventions live in `.claude/rules/` and are **imported above** so they
13load every session — Claude Code has no glob-scoped rules directory, so each
14file simply names the paths it applies to in an "Applies to" line. They mirror
15the Cursor rules in `.cursor/rules/` (which *are* glob-scoped via `globs:`); if
16you change a convention, update **both** mirrors and the relevant section of
17`ARCHITECTURE.md` so the tools and docs don't drift.
18
@@ −1 +1 @@
1−---
2−description: FastAPI route conventions for the events API
3−globs: app/api/**/*.py
4−alwaysApply: false
5−---
1+@AGENTS.md
62
7−# API Route Conventions
3+@.claude/rules/python-standards.md
4+@.claude/rules/api-routes.md
5+@.claude/rules/testing.md
6+@.claude/rules/elasticsearch-mapping.md
7+@.claude/rules/background-tasks.md
88
9−- Routes are thin: validate input, call a service/store, shape the response.
10− No persistence, aggregation, or business logic in a handler.
11−- Pull dependencies off `app.state` via the `Depends(_helper)` pattern (e.g.
12− `_mongo`, `_es`, `_cache`, `_ingestion`); don't reach into globals.
13−- The events routes declare a Pydantic `response_model` from
14− `app/api/schemas.py`; `/health` (a status-code-driven `JSONResponse`) and
15− `/metrics` (a loose ops snapshot) are intentionally exempt. Nullable fields are
16− **always present** in the response (return explicit `null`, e.g. `total`,
17− `bucket`, `computed_at`) for a stable shape.
9+## Claude Code
1810
19−# Error → status mapping (be consistent)
20−
21−Stores raise native exceptions; the route catches and maps them. Log at the
22−boundary with the exception type, then raise `HTTPException`.
23−
24−| Condition | Status |
25−|---|---|
26−| Mongo (source of truth) unavailable | `503` |
27−| Elasticsearch (derived) unavailable | `502` |
28−| Queue full (backpressure) | `429` |
29−| Service shutting down | `503` |
30−
31−```python
32−try:
33− events, has_more, total = await mongo.find_events(...)
34−except PyMongoError as exc:
35− logger.error("Mongo query failed (%s): %s", type(exc).__name__, exc)
36− raise HTTPException(status_code=503, detail="Event store temporarily unavailable")
37−```
11+Shared, vendor-neutral project context lives in `AGENTS.md` (imported above).
12+Project conventions live in `.claude/rules/` and are **imported above** so they
13+load every session — Claude Code has no glob-scoped rules directory, so each
14+file simply names the paths it applies to in an "Applies to" line. They mirror
15+the Cursor rules in `.cursor/rules/` (which *are* glob-scoped via `globs:`); if
16+you change a convention, update **both** mirrors and the relevant section of
17+`ARCHITECTURE.md` so the tools and docs don't drift.
3818
