Add Cursor rules for story kickoff, authority, styles, and testing.

Introduce project rules: Jira story kickoff and docs/plans workflow, server
authority boundaries, GDScript and C# style guides, and testing expectations
including integration tests when persistence is in scope. All use
alwaysApply where requested so they stay in context.

Made-with: Cursor
pull/2/head
don 2026-03-29 20:48:51 -04:00
parent cbf15fc8bb
commit 80082a1eac
5 changed files with 192 additions and 0 deletions

View File

@ -0,0 +1,30 @@
---
description: Server-authoritative simulation; client sends intents; transport-only networking; no client-trusted outcomes.
alwaysApply: true
---
# Architecture — authority & client boundaries (Neon Sprawl)
Canonical background: [`docs/architecture/tech_stack.md`](docs/architecture/tech_stack.md). This rule is the **non-negotiable slice** for day-to-day implementation.
## Where truth lives
- **Authoritative game state and rules** live on the **C# / ASP.NET Core** server (zones, combat resolution, inventory, economy, progression, anything audit-worthy).
- The **Godot** client is responsible for **input, presentation, camera, UI, and local feel** (e.g. interpolation, cosmetic prediction only if explicitly designed)—not for deciding final outcomes of gameplay systems.
## Network shape
- **WebSocket** or **TCP** is **transport only**. Do not put authoritative simulation in Godots **high-level multiplayer** templates or patterns that imply peers co-own game state.
- Prefer a clear boundary: client emits **intents** (e.g. `MoveIntent`, `UseAbilityIntent`); server validates, simulates, persists as needed, and responds with **state deltas or snapshots**. Names are examples—follow whatever contracts exist in-repo.
## What the client must not “decide”
- Do not treat the client as source of truth for **loot, trades, crafting results, currency, or anti-cheat-sensitive** behavior. Those paths belong on the server with validation and, where required, **database transactions** (see tech stack doc).
## Exceptions
- **Prototype-only, client-local** behavior is allowed when a Jira story or plan explicitly scopes it (e.g. **no server yet**, “client-only milestone”) and docs/README call out that it is **temporary** until authoritative sync exists. Do not silently expand client-only shortcuts into permanent architecture.
## When unsure
- Default to **server validates + owns outcome**; add a short note in the story plan or PR if you introduce a deliberate exception.

View File

@ -0,0 +1,45 @@
---
description: C# naming and layout aligned with Microsoft coding conventions and .NET idioms.
globs: "**/*.cs"
alwaysApply: true
---
# C# style (Neon Sprawl)
Follow Microsofts **[C# Coding Conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions)** and **[C# identifier rules](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names)**. Prefer clarity and consistency with existing server code.
## Naming
- **Types** (classes, structs, records, interfaces, enums, delegates): `PascalCase`.
- **Interfaces:** prefix with `I` (e.g. `IPlayerSession`).
- **Methods, properties, events, public fields:** `PascalCase`.
- **Parameters, local variables:** `camelCase`.
- **Private instance fields:** `camelCase` (no leading underscore), unless an existing file consistently does otherwise—then match the file. If a parameter or local shadows a field, use `this.` or rename for clarity.
- **Static fields:** `camelCase` for private/internal static fields; `PascalCase` for `public static` members (including `readonly`/constants) per Microsoft guidance; stay consistent within a project.
- **Async methods:** suffix with `Async` (e.g. `LoadProfileAsync`).
## Layout and syntax
- **Braces:** opening brace `{` on a **new line** for types and members (Allman-style), per common Microsoft examples.
- **Indentation:** **4 spaces** per level; no tabs unless the file already uses tabs—never mix.
- **`var`:** use when the type is obvious from the right-hand side; use explicit types when it improves readability or for literals where the type matters.
- **File-scoped namespaces** (`namespace X;`) for new single-namespace files when the SDK/version allows.
- **Pattern matching / nullability:** prefer modern C# features where they simplify code; honor **nullable reference type** annotations when the project enables them.
## Members
- Prefer **expression-bodied** members only when they stay one clear idea.
- **LINQ:** favor readability over micro-chains; break complex queries across lines.
- **Exception handling:** catch specific exceptions; avoid empty `catch`; log or rethrow with context when appropriate.
## `Program.cs` and minimal APIs
- Top-level statements and minimal APIs are fine for small apps; extract registration/build logic into extension methods or dedicated types when the file grows.
## Documentation
- Use **`///` XML doc comments** on public APIs (types and members) when behavior or contracts are not obvious.
## Tooling
- Prefer fixes that satisfy built-in **.NET analyzers** / `dotnet format` (if adopted) rather than fighting IDE warnings without reason.

View File

@ -0,0 +1,45 @@
---
description: GDScript naming, formatting, and Godot-idiomatic patterns (Godot docs style guide).
globs: "**/*.gd"
alwaysApply: true
---
# GDScript style (Neon Sprawl)
Follow the [Godot GDScript style guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html). Prefer clarity and consistency with existing scripts in the repo.
## Naming
- **Functions, variables, signals:** `snake_case`.
- **Classes** (`class_name`, custom resources): `PascalCase`.
- **Constants** (`const`): `ALL_CAPS` when they are true fixed values; otherwise match Godot/node conventions used nearby.
- **“Private” / internal:** leading underscore `_like_this` for members meant as implementation detail (not enforced by the language).
## Types and API
- Add **static types** on parameters, locals, and return values where reasonable (`-> void`, `var x: int`, etc.).
- Prefer **`@export`** (Godot 4) over legacy `export` syntax.
- Use **`@onready`** for node references set after the scene tree is ready when that pattern fits.
## Formatting
- **One statement per line**; break long lines for readability (Godot line length is flexible—aim for ~100 characters unless a longer string is clearer).
- **Indentation:** use **tabs** for new Godot work (editor default). Do not mix tabs and spaces in the same file; match the file if it already uses spaces.
- **Blank lines:** separate functions with two blank lines; sparing single blank lines inside functions for logical groups.
- **Trailing commas** in multi-line collections/function args when it improves diffs.
## Structure
- **`class_name`** only when the type must be referenced globally; otherwise anonymous `extends` is fine.
- Order loosely: `extends` → `class_name` → `signals` → `enums` → `const` → `export/@export` → `onready` → other vars → `_ready` / lifecycle → public methods → private helpers.
- Virtual overrides (`_ready`, `_process`, `_physics_process`, etc.): keep small; extract helpers with leading `_`.
## Comments
- Use `#` comments; document non-obvious **why**, not what the next line literally does.
- Doc comments: Godot 4 supports `##` above declarations for the in-editor help—use for public-ish APIs when helpful.
## Anti-patterns
- Avoid `get_node()` string paths repeated everywhere; use `@onready`, exports, or groups when scale demands it.
- Prefer typed collections and enums over “magic” string/int state when it stays readable.

View File

@ -0,0 +1,42 @@
---
description: When starting Jira story work, load issue + repo context first; no implementation code until a plan exists under docs/plans/.
alwaysApply: true
---
# Story kickoff (Jira)
When the user starts work on a **Jira story** (e.g. issue key `NS-14`, phrases like “begin work on story”, “implement NS-…”), run this sequence **before** writing or changing application code.
## 1. Load Jira context
- Fetch the issue when possible (e.g. Atlassian MCP `getJiraIssue`), or use a URL / pasted description the user provides.
- Capture summary, description, acceptance criteria, and anything explicitly **out of scope**.
## 2. Load codebase context (read-only)
- Open only what the story implies: entry scenes/scripts, related modules, configs, tests/CI, and relevant [`docs/`](docs/) files.
- **No edits** and **no new implementation or test files** in this phase.
## 3. No implementation yet
- Do not add or change source, Godot scenes/project, game data pipelines, or automated tests until step 4 is done **and** the user has moved past planning in chat (e.g. explicit go-ahead to implement).
## 4. Planning document
- Add **`docs/plans/{JIRA_KEY}-implementation-plan.md`** (example: `docs/plans/NS-14-implementation-plan.md`). Create `docs/plans/` if it does not exist.
- Prefer committing this plan on **`main`** so it exists even before a feature branch; it counts as documentation-style work per [git workflow](git-workflow.mdc).
**Required sections** in that file:
- Story reference (key, title, link if available)
- Goal, scope, and out-of-scope (from Jira)
- Acceptance criteria checklist (from Jira)
- Technical approach (concise)
- **Files to add** (paths)
- **Files to modify** (paths and one-line rationale each)
- **Tests** — what will be added or changed; if none, say why (e.g. no harness yet, manual verification only)
- Open questions / risks (if any)
## 5. After the plan
- Implement only after the user confirms. For code, scenes, data, or CI changes, use a **branch** and follow [git workflow](git-workflow.mdc).

View File

@ -0,0 +1,30 @@
---
description: Unit vs integration tests; integration when data persistence/mutation exists; C# xUnit; Godot manual until harness.
alwaysApply: true
---
# Testing expectations (Neon Sprawl)
## C# server
- **Non-trivial logic** (validation, simulation rules, serialization boundaries, idempotency, security-sensitive paths) should have **automated tests** once a test project exists in the repo.
- **Default framework:** **xUnit** for new test projects unless the repo already standardizes on something else—stay consistent with existing `*.Tests` projects.
- **No test project yet:** It is acceptable to ship a small change without a suite only while the server is mostly scaffolding. When you add the **first** testable module, **add a `NeonSprawl.Server.Tests` (or equivalent) project** and start covering that area; do not leave new core logic permanently untested.
- **Bug fixes:** Prefer a **regression test** when the fix is non-obvious or has broken before.
## Integration testing (data manipulation)
- Once the server **reads or writes durable state** (e.g. **PostgreSQL** via EF Core, Dapper, or similar; migrations; transactional inventory/progression/economy paths), expect **integration tests** that exercise the **real persistence boundary**, not only mocked repositories.
- Cover at least: **happy path**, **constraints / failures** (unique keys, FKs, expected rollbacks), and **idempotent or retry-safe** behavior where the design requires it.
- **How to run them:** Prefer a project-standard approach (dedicated test database, **Testcontainers**, or CI service container) documented in `server/` README or `docs/`—do not leave integration tests machine-only without notes.
- **Spike exception:** A story may defer integration tests only when persistence is explicitly **out of scope**; call that out in the plan and add tests when data manipulation lands.
## Godot client (GDScript)
- Until the project adopts a harness (**GUT**, Godot unit tests, or CI export checks), rely on **manual verification** for gameplay and scene changes.
- For non-trivial client work, note **how you verified** (steps or scenario) in the PR or story plan so reviewers can repeat it.
## Cross-cutting
- If **CI** is added later, treat its **required** steps (e.g. `dotnet test`, schema validation) as gates: fix failures or update workflows/docs intentionally—do not silence checks without a recorded reason.
- When a story is **explicitly client-only or spike** (no server), match that scope in tests too (manual client checks only), and call out temporariness per [architecture authority](architecture-authority.mdc).