1176 lines
24 KiB
Markdown
1176 lines
24 KiB
Markdown
# AGENTS.md — Ashen Realms
|
||
|
||
## Purpose
|
||
|
||
This file defines the default working rules for AI coding agents contributing to **Ashen Realms**.
|
||
|
||
Ashen Realms is a modern, browser-based dark-fantasy PvE RPG inspired by the structure and long-term progression of classic browser MMORPGs, while using a modern UI, server-authoritative game logic, and a data-driven architecture.
|
||
|
||
Agents must treat the existing project documentation and implemented code as the source of truth. Do not redesign core systems, introduce new architecture, or generalize systems beyond current requirements unless explicitly requested.
|
||
|
||
---
|
||
|
||
# 1. Project Priorities
|
||
|
||
When making implementation decisions, use this priority order:
|
||
|
||
1. Preserve the core gameplay loop.
|
||
2. Preserve server authority and data integrity.
|
||
3. Keep systems simple enough for the current development stage.
|
||
4. Prefer reusable domain systems over content-specific special cases.
|
||
5. Maintain UI consistency with the existing visual language.
|
||
6. Keep implementation testable and understandable.
|
||
7. Avoid speculative architecture for future MMO-scale requirements.
|
||
|
||
Core gameplay loop:
|
||
|
||
```text
|
||
Explore
|
||
→ Travel
|
||
→ Hunt / Search
|
||
→ Choose encounter
|
||
→ Fight
|
||
→ Receive loot / progression
|
||
→ Improve character
|
||
→ Defeat stronger challenges
|
||
→ Discover new locations
|
||
```
|
||
|
||
The project should first be a good RPG and only later become a larger MMO.
|
||
|
||
---
|
||
|
||
# 2. Required Reading Before Major Changes
|
||
|
||
Before implementing or changing a larger gameplay, architecture, persistence, or UI feature, inspect the relevant documentation in `docs/`.
|
||
|
||
Important project documents include:
|
||
|
||
```text
|
||
docs/design-manifest.md
|
||
docs/vertical-slice-world-content-design.md
|
||
docs/balancing-items-loot-design.md
|
||
docs/ui-visual-design-specification.md
|
||
```
|
||
|
||
Additional feature specifications may exist in `docs/` and override older assumptions where they explicitly redefine a system.
|
||
|
||
Do not rely only on this file when a more specific feature specification exists.
|
||
|
||
---
|
||
|
||
# 3. Source-of-Truth Order
|
||
|
||
If multiple sources conflict, use the following precedence unless the task explicitly says otherwise:
|
||
|
||
1. Explicit requirements in the current task.
|
||
2. Newer dedicated feature specification.
|
||
3. Newer project documentation.
|
||
4. Existing implemented behavior and tests.
|
||
5. `AGENTS.md`.
|
||
6. Older design documents.
|
||
|
||
Do not silently reconcile conflicting requirements.
|
||
|
||
If a conflict affects behavior or data design, point it out before making a broad architectural reinterpretation.
|
||
|
||
---
|
||
|
||
# 4. Current Technical Architecture
|
||
|
||
Ashen Realms is implemented as a **modular monolith**.
|
||
|
||
## Stack
|
||
|
||
```text
|
||
Frontend: Angular
|
||
Backend: NestJS
|
||
Language: TypeScript
|
||
Database: PostgreSQL
|
||
ORM: TypeORM
|
||
Monorepo: npm Workspaces
|
||
API: REST
|
||
Deployment: one Ashen Realms application container
|
||
Database: separate persistent PostgreSQL service
|
||
```
|
||
|
||
Typical repository structure:
|
||
|
||
```text
|
||
apps/
|
||
web/
|
||
api/
|
||
|
||
packages/
|
||
shared/
|
||
game-content/
|
||
|
||
docs/
|
||
```
|
||
|
||
Production behavior:
|
||
|
||
```text
|
||
Browser
|
||
↓
|
||
NestJS
|
||
├── /api/* → REST API
|
||
└── /* → built Angular application
|
||
↓
|
||
PostgreSQL
|
||
```
|
||
|
||
NestJS is the only runtime process in the application container.
|
||
|
||
Do not introduce a second production web server for Angular.
|
||
|
||
---
|
||
|
||
# 5. Server Authority Is Mandatory
|
||
|
||
Critical gameplay logic is server-authoritative.
|
||
|
||
The client may display state and send intentions, but must not decide authoritative gameplay results.
|
||
|
||
The server owns at least:
|
||
|
||
- character state
|
||
- current HP
|
||
- effective stats
|
||
- combat state
|
||
- combat results
|
||
- damage
|
||
- enemy actions
|
||
- loot rolls
|
||
- inventory
|
||
- equipment
|
||
- currencies
|
||
- reputation / progression
|
||
- travel state
|
||
- travel completion
|
||
- encounter generation
|
||
- quest progress
|
||
- item ownership
|
||
- regeneration state
|
||
|
||
Client requests should express actions, not results.
|
||
|
||
Good:
|
||
|
||
```json
|
||
{
|
||
"action": "ATTACK"
|
||
}
|
||
```
|
||
|
||
Bad:
|
||
|
||
```json
|
||
{
|
||
"action": "ATTACK",
|
||
"damage": 42
|
||
}
|
||
```
|
||
|
||
Never trust client-provided values that the server can calculate or validate itself.
|
||
|
||
---
|
||
|
||
# 6. API Rules
|
||
|
||
All API routes use the prefix:
|
||
|
||
```text
|
||
/api
|
||
```
|
||
|
||
Frontend requests must use relative URLs.
|
||
|
||
Good:
|
||
|
||
```ts
|
||
this.http.get('/api/characters/me');
|
||
```
|
||
|
||
Bad:
|
||
|
||
```ts
|
||
this.http.get('http://localhost:3000/api/characters/me');
|
||
```
|
||
|
||
Use consistent domain errors.
|
||
|
||
Example:
|
||
|
||
```json
|
||
{
|
||
"statusCode": 400,
|
||
"code": "INVALID_TRAVEL_TARGET",
|
||
"message": "The selected location is not connected to the current location."
|
||
}
|
||
```
|
||
|
||
Prefer stable machine-readable error codes over UI-dependent text matching.
|
||
|
||
---
|
||
|
||
# 7. Data and Persistence Rules
|
||
|
||
## TypeORM
|
||
|
||
Use TypeORM migrations for schema changes.
|
||
|
||
Production must not use:
|
||
|
||
```ts
|
||
synchronize: true
|
||
```
|
||
|
||
Schema workflow:
|
||
|
||
```text
|
||
change entity
|
||
→ create/generate migration
|
||
→ inspect migration
|
||
→ run migration
|
||
→ run tests
|
||
```
|
||
|
||
Never accept unexpected destructive migration output without reviewing it.
|
||
|
||
## Content vs Player State
|
||
|
||
Keep static or semi-static game content separate from player-specific persistent state.
|
||
|
||
Examples of content definitions:
|
||
|
||
```text
|
||
LocationDefinition
|
||
LocationConnection
|
||
MonsterDefinition
|
||
ItemDefinition
|
||
LootTable
|
||
NPC definition
|
||
Quest definition
|
||
Shop definition
|
||
```
|
||
|
||
Examples of player state:
|
||
|
||
```text
|
||
User
|
||
Character
|
||
CharacterItem
|
||
CharacterEquipment
|
||
Travel
|
||
Hunt
|
||
HuntEncounter
|
||
Combat
|
||
CombatEvent
|
||
QuestProgress
|
||
Reputation
|
||
```
|
||
|
||
Do not duplicate content definitions into every player record.
|
||
|
||
---
|
||
|
||
# 8. Stable Content Keys
|
||
|
||
Content should have stable human-readable keys in addition to database IDs where appropriate.
|
||
|
||
Examples:
|
||
|
||
```text
|
||
south-gate
|
||
burned-road
|
||
ash-rat
|
||
road-bandit
|
||
worn-short-sword
|
||
```
|
||
|
||
Use stable keys for seeds, cross-content references, configuration, and tests where this improves maintainability.
|
||
|
||
Do not hard-code random UUIDs across fixtures or content definitions.
|
||
|
||
Seeds must be idempotent whenever practical.
|
||
|
||
Running a seed repeatedly must not create duplicate content.
|
||
|
||
---
|
||
|
||
# 9. Gameplay Systems Should Be Data-Driven
|
||
|
||
Repeated game content should be modeled as data rather than one-off code.
|
||
|
||
This applies especially to:
|
||
|
||
- locations
|
||
- travel connections
|
||
- monsters
|
||
- encounter pools
|
||
- items
|
||
- loot
|
||
- NPCs
|
||
- shops
|
||
- abilities
|
||
- quests
|
||
- reputation requirements
|
||
- enemy categories
|
||
- drop categories
|
||
|
||
Prefer:
|
||
|
||
```text
|
||
shared mechanic + content configuration
|
||
```
|
||
|
||
over:
|
||
|
||
```text
|
||
if monster == "special-monster-x" then custom branch
|
||
```
|
||
|
||
However, do not over-generalize before multiple real use cases exist.
|
||
|
||
A special case is acceptable when the abstraction would be more complex than the current requirement.
|
||
|
||
---
|
||
|
||
# 10. Combat Design Rules
|
||
|
||
Combat is round-based.
|
||
|
||
The player chooses one main action per turn.
|
||
|
||
The combat system should remain deterministic where the current rules define deterministic behavior.
|
||
|
||
Core values currently revolve around:
|
||
|
||
```text
|
||
HP
|
||
Attack
|
||
Weapon Damage
|
||
Armor
|
||
```
|
||
|
||
The original V1 combat model uses:
|
||
|
||
```text
|
||
Raw Damage = Weapon Damage + Attack
|
||
```
|
||
|
||
and armor mitigation based on:
|
||
|
||
```text
|
||
Damage = Raw Damage × 60 / (60 + Armor)
|
||
```
|
||
|
||
Minimum successful damage:
|
||
|
||
```text
|
||
1
|
||
```
|
||
|
||
Do not add systems such as critical hits, dodge, accuracy, random damage ranges, elemental resistance, mana, or complex action points unless a newer dedicated specification introduces them.
|
||
|
||
Enemy difficulty should come primarily from:
|
||
|
||
- meaningful stats
|
||
- telegraphed actions
|
||
- status effects
|
||
- defensive states
|
||
- interrupts
|
||
- phase behavior
|
||
- encounter composition
|
||
|
||
not hidden randomness.
|
||
|
||
---
|
||
|
||
# 11. Combat Engine Separation
|
||
|
||
Pure combat rules should be kept separate from persistence and HTTP concerns.
|
||
|
||
Preferred structure:
|
||
|
||
```text
|
||
CombatController
|
||
↓
|
||
CombatService
|
||
↓
|
||
CombatEngineService
|
||
```
|
||
|
||
`CombatEngineService` should ideally:
|
||
|
||
- receive game state
|
||
- receive an action
|
||
- return resulting state/events
|
||
- avoid direct database access
|
||
- be easy to unit test
|
||
|
||
`CombatService` should:
|
||
|
||
- load persistent state
|
||
- validate ownership and turn rules
|
||
- invoke the engine
|
||
- persist events/state
|
||
- handle victory/defeat
|
||
- trigger loot/progression
|
||
- commit atomically where necessary
|
||
|
||
Do not bury combat formulas inside controllers or Angular components.
|
||
|
||
---
|
||
|
||
# 12. Realtime and Event Delivery
|
||
|
||
Realtime communication is an event transport layer, not the authoritative game state itself.
|
||
|
||
The project is moving toward a central game-event connection suitable for systems such as:
|
||
|
||
- multiplayer combat
|
||
- delayed NPC actions
|
||
- pets / companions
|
||
- turn notifications
|
||
- combat state changes
|
||
- selected character-state updates
|
||
|
||
Prefer one authenticated realtime connection with typed event channels/messages rather than one independent socket connection per feature.
|
||
|
||
Examples of event families:
|
||
|
||
```text
|
||
combat.*
|
||
character.*
|
||
travel.*
|
||
system.*
|
||
```
|
||
|
||
The server remains authoritative.
|
||
|
||
The client must still be able to recover state through normal APIs after reconnecting.
|
||
|
||
Do not make correctness depend solely on receiving every realtime event.
|
||
|
||
---
|
||
|
||
# 13. Travel Rules
|
||
|
||
Travel is server-authoritative.
|
||
|
||
The server calculates:
|
||
|
||
```text
|
||
startedAt
|
||
arrivesAt
|
||
origin
|
||
target
|
||
travel state
|
||
possible encounter
|
||
```
|
||
|
||
The client may render a countdown using the server-provided timestamp.
|
||
|
||
Never move the character merely because a browser timer reached zero.
|
||
|
||
Travel completion must be validated or finalized by the server.
|
||
|
||
Travel duration is part of the game-world feeling, not just an arbitrary cooldown.
|
||
|
||
---
|
||
|
||
# 14. Hunting and Encounters
|
||
|
||
The player does not directly request arbitrary monsters to fight.
|
||
|
||
Preferred flow:
|
||
|
||
```text
|
||
start hunt/search
|
||
→ server creates valid encounter choices
|
||
→ player selects one encounter
|
||
→ combat starts from that persisted encounter
|
||
```
|
||
|
||
Use encounter IDs or equivalent server-issued references.
|
||
|
||
Do not allow:
|
||
|
||
```text
|
||
POST /combat
|
||
{
|
||
"monsterId": "anything-the-client-wants"
|
||
}
|
||
```
|
||
|
||
without server-side validation that the encounter is actually available to that character.
|
||
|
||
---
|
||
|
||
# 15. Progression Direction
|
||
|
||
Ashen Realms is evolving away from a classic:
|
||
|
||
```text
|
||
kill monster
|
||
→ receive XP + money
|
||
→ level up
|
||
```
|
||
|
||
model.
|
||
|
||
Current project direction emphasizes:
|
||
|
||
- reputation / renown
|
||
- region reputation
|
||
- world-level progression
|
||
- monster materials
|
||
- exchanging materials through NPCs / merchants
|
||
- reputation-gated offers
|
||
- meaningful inventory/bag constraints
|
||
- loot and equipment as primary combat progression
|
||
|
||
When touching XP, direct monster currency rewards, level gating, merchants, drops, or progression, inspect the newest progression/reputation specifications before using older V1 assumptions.
|
||
|
||
Do not reintroduce old XP-based progression just because older design documents still contain it.
|
||
|
||
---
|
||
|
||
# 16. Item and Loot Philosophy
|
||
|
||
Items must be understandable and meaningful.
|
||
|
||
Prefer handcrafted items with fixed identity over random-affix chaos.
|
||
|
||
A good item should create a visible upgrade or gameplay decision.
|
||
|
||
Loot should be targeted enough that the player can understand why a specific enemy is worth fighting.
|
||
|
||
General principle:
|
||
|
||
```text
|
||
Drops create excitement.
|
||
Deterministic progression prevents frustration.
|
||
```
|
||
|
||
Bosses and important content should not regularly produce meaningless rewards.
|
||
|
||
Avoid huge undifferentiated loot tables.
|
||
|
||
---
|
||
|
||
# 17. Bags and Material Categories
|
||
|
||
The project uses or plans constrained bags for certain material categories.
|
||
|
||
This system is intended to make carrying capacity part of progression without turning the full inventory into weight micromanagement.
|
||
|
||
When implementing drops and inventory:
|
||
|
||
- distinguish normal inventory from specialized material storage where specified
|
||
- support monster/drop categories as data
|
||
- do not hard-code category behavior into individual monsters
|
||
- keep quest/story items separate from normal inventory capacity where appropriate
|
||
|
||
Inspect the dedicated bag-system specification before implementing or modifying this system.
|
||
|
||
---
|
||
|
||
# 18. NPC Model
|
||
|
||
NPCs may combine multiple capabilities.
|
||
|
||
Avoid rigid inheritance such as:
|
||
|
||
```text
|
||
BaseNpc
|
||
├── MerchantNpc
|
||
└── QuestGiverNpc
|
||
```
|
||
|
||
when an NPC can logically be both.
|
||
|
||
Prefer composition/capabilities, for example:
|
||
|
||
```text
|
||
NPC
|
||
+ dialogue
|
||
+ merchant capability
|
||
+ quest capability
|
||
+ reputation relationship
|
||
+ location presence
|
||
```
|
||
|
||
Shared NPC data may include:
|
||
|
||
- stable key
|
||
- name
|
||
- location
|
||
- portrait/artwork
|
||
- dialogue
|
||
- availability
|
||
- reputation relationship
|
||
- interaction capabilities
|
||
|
||
Use the dedicated NPC specification where available.
|
||
|
||
---
|
||
|
||
# 19. UI Design Direction
|
||
|
||
Ashen Realms must not look like a generic web dashboard or mobile game.
|
||
|
||
The intended style is:
|
||
|
||
```text
|
||
classic browser RPG structure
|
||
+
|
||
modern premium dark-fantasy presentation
|
||
```
|
||
|
||
Key characteristics:
|
||
|
||
- desktop-first
|
||
- persistent top bar
|
||
- left-side navigation
|
||
- large central artwork/content area
|
||
- contextual right-side panel
|
||
- restrained footer/status area
|
||
- dark metal / stone / leather materials
|
||
- muted colors
|
||
- limited functional accents
|
||
- strong fantasy artwork
|
||
- readable information density
|
||
- clear interaction states
|
||
|
||
Avoid:
|
||
|
||
- SaaS dashboard visuals
|
||
- white cards
|
||
- glassmorphism
|
||
- neon cyberpunk styling
|
||
- generic Angular Material appearance
|
||
- excessive rounded mobile cards
|
||
- stacked mobile-game popups
|
||
- arbitrary component-specific visual languages
|
||
|
||
---
|
||
|
||
# 20. UI Reuse Rules
|
||
|
||
Before creating a new screen or component:
|
||
|
||
1. inspect existing shared layout/components
|
||
2. inspect similar screens
|
||
3. inspect design tokens/styles
|
||
4. reuse existing UI primitives where appropriate
|
||
|
||
Likely reusable components include concepts such as:
|
||
|
||
```text
|
||
AppShell
|
||
TopBar
|
||
SideNavigation
|
||
Footer
|
||
Panel
|
||
PanelHeader
|
||
Button variants
|
||
HealthBar
|
||
CharacterHeader
|
||
DangerBadge
|
||
EncounterCard
|
||
ItemIcon
|
||
ItemTooltip
|
||
CombatActionButton
|
||
CombatLog
|
||
PotionSlot
|
||
StatusEffectIcon
|
||
```
|
||
|
||
Do not duplicate the same visual pattern independently in multiple feature folders.
|
||
|
||
---
|
||
|
||
# 21. Artwork Is Part of the Product
|
||
|
||
Large artworks are a primary part of the game experience.
|
||
|
||
UI layout should preserve visual space for:
|
||
|
||
- locations
|
||
- monsters
|
||
- characters
|
||
- NPCs
|
||
- combat scenes
|
||
- items
|
||
|
||
Do not convert major game screens into dense tables or grids merely because that is easier to implement.
|
||
|
||
Gameplay information must be clear, but the world should remain visually dominant.
|
||
|
||
---
|
||
|
||
# 22. Frontend Responsibilities
|
||
|
||
Angular is responsible for:
|
||
|
||
- rendering server state
|
||
- user input
|
||
- local UI state
|
||
- routing
|
||
- animations
|
||
- countdown display
|
||
- displaying realtime events
|
||
- presenting combat events
|
||
- accessibility and interaction states
|
||
|
||
Angular is not authoritative for:
|
||
|
||
- damage
|
||
- loot
|
||
- inventory ownership
|
||
- travel completion
|
||
- combat results
|
||
- stat calculation
|
||
- progression rewards
|
||
- encounter validity
|
||
|
||
Prefer typed API contracts.
|
||
|
||
Do not leak TypeORM entities directly into frontend assumptions.
|
||
|
||
---
|
||
|
||
# 23. Shared Package Rules
|
||
|
||
`packages/shared` should contain only genuine cross-boundary contracts and shared enums/types.
|
||
|
||
Good examples:
|
||
|
||
```text
|
||
DTO contracts
|
||
shared enums
|
||
event message contracts
|
||
API-facing types
|
||
```
|
||
|
||
Do not place:
|
||
|
||
- NestJS services
|
||
- Angular components
|
||
- TypeORM entities
|
||
- repository implementations
|
||
- backend-only business logic
|
||
|
||
inside `packages/shared`.
|
||
|
||
`packages/game-content` may contain shared content schemas/enums where this is genuinely useful.
|
||
|
||
---
|
||
|
||
# 24. Testing Expectations
|
||
|
||
Changes to domain logic require tests.
|
||
|
||
High-value test targets include:
|
||
|
||
- combat calculations
|
||
- character effective stats
|
||
- travel validation
|
||
- regeneration logic
|
||
- encounter generation
|
||
- loot rolls
|
||
- inventory/equipment rules
|
||
- reputation changes
|
||
- bag capacity rules
|
||
- quest progression
|
||
- realtime event handling
|
||
|
||
Use deterministic random sources in tests for random game systems.
|
||
|
||
Do not write tests that rely on uncontrolled `Math.random()` behavior.
|
||
|
||
For API flows, prefer integration tests around real validation boundaries.
|
||
|
||
For frontend features, test behavior and state handling rather than fragile implementation details.
|
||
|
||
---
|
||
|
||
# 25. Bug-Fix Workflow
|
||
|
||
When fixing a bug:
|
||
|
||
1. understand the actual failure
|
||
2. identify the authoritative layer
|
||
3. reproduce with a focused test where practical
|
||
4. implement the smallest correct fix
|
||
5. run relevant tests
|
||
6. run lint/build where appropriate
|
||
7. verify no adjacent behavior regressed
|
||
|
||
Do not treat symptoms in Angular if the actual bug is an invalid backend state transition.
|
||
|
||
Do not disable validation merely to make an API call pass.
|
||
|
||
---
|
||
|
||
# 26. Feature Workflow
|
||
|
||
For non-trivial features:
|
||
|
||
1. read the relevant spec
|
||
2. inspect the current implementation
|
||
3. identify affected domain boundaries
|
||
4. define the smallest complete slice
|
||
5. add/adjust tests
|
||
6. implement backend/domain behavior
|
||
7. add persistence/migration if needed
|
||
8. expose API/realtime contract
|
||
9. implement frontend behavior
|
||
10. verify end-to-end behavior
|
||
11. update documentation if behavior or architecture changed
|
||
|
||
Prefer vertical slices over large disconnected infrastructure work.
|
||
|
||
---
|
||
|
||
# 27. Scope Discipline
|
||
|
||
Do not add systems merely because they may be useful later.
|
||
|
||
For V1 and early development, avoid introducing without explicit need:
|
||
|
||
- microservices
|
||
- Kafka
|
||
- RabbitMQ
|
||
- Redis
|
||
- event sourcing
|
||
- CQRS frameworks
|
||
- GraphQL
|
||
- Kubernetes-specific architecture
|
||
- generic plugin systems
|
||
- unnecessary abstraction layers
|
||
- premature distributed locking
|
||
- generic workflow engines
|
||
- complex state machines when simple domain state is enough
|
||
|
||
The default question is:
|
||
|
||
```text
|
||
What is the smallest correct design for the current feature?
|
||
```
|
||
|
||
---
|
||
|
||
# 28. Avoid Premature MMO Architecture
|
||
|
||
Future features may include:
|
||
|
||
- parties
|
||
- multiplayer combat
|
||
- companions
|
||
- pets
|
||
- chat
|
||
- guilds
|
||
- trading
|
||
- PvP
|
||
- auctions
|
||
- crafting
|
||
- admin balancing tools
|
||
|
||
Current code should avoid blocking those ideas, but should not fully implement infrastructure for them before needed.
|
||
|
||
Design extensible domain boundaries, not speculative subsystems.
|
||
|
||
---
|
||
|
||
# 29. Transaction Boundaries
|
||
|
||
Use database transactions for operations that must succeed atomically.
|
||
|
||
Examples:
|
||
|
||
```text
|
||
combat victory
|
||
→ reward generation
|
||
→ inventory grant
|
||
→ reputation/material changes
|
||
→ combat completion
|
||
```
|
||
|
||
or:
|
||
|
||
```text
|
||
equip item
|
||
→ validate ownership
|
||
→ replace current slot
|
||
→ persist equipment state
|
||
```
|
||
|
||
Do not leave the character in partially updated gameplay states.
|
||
|
||
---
|
||
|
||
# 30. Concurrency and Idempotency
|
||
|
||
Assume clients may retry requests or send duplicate requests.
|
||
|
||
Important state-changing actions should reject or safely handle duplicates.
|
||
|
||
Examples:
|
||
|
||
- completing the same travel twice
|
||
- resolving the same combat turn twice
|
||
- claiming the same reward twice
|
||
- submitting the same quest completion twice
|
||
- buying the same transaction twice because of retry
|
||
|
||
Where useful, enforce correctness with:
|
||
|
||
- explicit status transitions
|
||
- database constraints
|
||
- version checks
|
||
- unique keys
|
||
- transaction locking
|
||
|
||
Do not rely solely on the UI disabling a button.
|
||
|
||
---
|
||
|
||
# 31. Character Stats
|
||
|
||
Effective character stats must have a clear authoritative calculation path.
|
||
|
||
Prefer a dedicated service such as:
|
||
|
||
```text
|
||
CharacterStatsService
|
||
```
|
||
|
||
It should combine:
|
||
|
||
```text
|
||
base character values
|
||
+ equipment
|
||
+ item bonuses
|
||
+ active effects
|
||
+ future set bonuses/buffs where applicable
|
||
```
|
||
|
||
Do not independently calculate effective stats in combat, profile, inventory, and UI code.
|
||
|
||
Use one domain source of truth.
|
||
|
||
---
|
||
|
||
# 32. HP and Regeneration
|
||
|
||
Persistent HP and regeneration are server-owned state.
|
||
|
||
If regeneration is timestamp-based, calculate authoritative HP using server timestamps and persisted regeneration anchors/state.
|
||
|
||
Realtime updates may improve the UI, but must not be required for correctness.
|
||
|
||
A reconnect or normal API refresh must be able to reconstruct the correct current HP.
|
||
|
||
Do not implement HP regeneration as a browser-only interval.
|
||
|
||
---
|
||
|
||
# 33. Naming and Language
|
||
|
||
Code, API contracts, identifiers, database names, and new game-content source text should default to **English** unless an existing subsystem explicitly uses another convention.
|
||
|
||
Prefer clear domain names over abbreviations.
|
||
|
||
Good:
|
||
|
||
```text
|
||
currentLocationId
|
||
reputationRequirement
|
||
travelDurationSeconds
|
||
monsterCategory
|
||
```
|
||
|
||
Avoid unclear names such as:
|
||
|
||
```text
|
||
loc
|
||
repReq
|
||
dur
|
||
mc
|
||
```
|
||
|
||
Public-facing gameplay text should move toward English consistently as the project is migrated.
|
||
|
||
---
|
||
|
||
# 34. TypeScript Rules
|
||
|
||
Prefer:
|
||
|
||
- strict types
|
||
- explicit domain types
|
||
- discriminated unions where useful
|
||
- enums/unions for finite domain states
|
||
- immutable inputs for pure engines where practical
|
||
- dependency injection for external/random/time sources when testing benefits
|
||
|
||
Avoid:
|
||
|
||
- `any`
|
||
- magic strings scattered across services
|
||
- duplicated status literals
|
||
- deeply nested untyped JSON blobs for core domain state
|
||
|
||
JSONB is acceptable for flexible snapshots/events when the schema is still clearly typed in TypeScript.
|
||
|
||
---
|
||
|
||
# 35. Time Handling
|
||
|
||
Use server timestamps for authoritative gameplay timing.
|
||
|
||
Examples:
|
||
|
||
- travel
|
||
- cooldowns
|
||
- HP regeneration
|
||
- timed encounter state
|
||
- buffs/debuffs
|
||
- scheduled NPC/combat actions
|
||
|
||
Prefer storing absolute timestamps such as:
|
||
|
||
```text
|
||
startedAt
|
||
arrivesAt
|
||
expiresAt
|
||
lastRegeneratedAt
|
||
```
|
||
|
||
The frontend may derive display countdowns from those values.
|
||
|
||
Do not persist countdown seconds that decrement every second unless there is a strong domain reason.
|
||
|
||
---
|
||
|
||
# 36. Logging
|
||
|
||
Use structured backend logging for meaningful domain and infrastructure failures.
|
||
|
||
Useful context may include:
|
||
|
||
- character ID
|
||
- combat ID
|
||
- travel ID
|
||
- encounter ID
|
||
- action
|
||
- domain error code
|
||
|
||
Do not log secrets, tokens, passwords, or full sensitive authentication payloads.
|
||
|
||
Avoid noisy per-frame or per-second logs.
|
||
|
||
---
|
||
|
||
# 37. Security Basics
|
||
|
||
Never trust client ownership claims.
|
||
|
||
Always verify:
|
||
|
||
- the authenticated user owns the character
|
||
- the character owns the item
|
||
- the encounter belongs to the character
|
||
- the combat belongs to the character
|
||
- the requested transition is currently legal
|
||
|
||
Secrets belong in environment variables.
|
||
|
||
Never commit real secrets.
|
||
|
||
Do not expose internal stack traces or database details as user-facing API errors.
|
||
|
||
---
|
||
|
||
# 38. Documentation Updates
|
||
|
||
Update documentation when a change:
|
||
|
||
- alters architecture
|
||
- changes a core gameplay rule
|
||
- replaces an older system
|
||
- introduces a reusable domain pattern
|
||
- creates a new persistent data model
|
||
- changes API/realtime conventions
|
||
- invalidates an existing implementation spec
|
||
|
||
Do not update documentation for trivial refactors that do not change behavior.
|
||
|
||
When replacing an old system, prefer clearly marking the old assumption obsolete rather than leaving contradictory active docs.
|
||
|
||
---
|
||
|
||
# 39. Do Not Silently Change Game Design
|
||
|
||
Coding agents may identify possible improvements, but they should not silently:
|
||
|
||
- rebalance items
|
||
- change travel times
|
||
- change drop chances
|
||
- change combat formulas
|
||
- alter progression rules
|
||
- replace reputation requirements
|
||
- redesign UI flows
|
||
- add/remove player capabilities
|
||
|
||
unless the requested task includes that design change.
|
||
|
||
If implementation requires choosing an unspecified behavior, choose the smallest reversible option and make the assumption explicit.
|
||
|
||
---
|
||
|
||
# 40. Definition of Done
|
||
|
||
A feature is complete when applicable:
|
||
|
||
- requirements from the relevant spec are implemented
|
||
- authoritative logic is on the server
|
||
- persistence is correct
|
||
- migrations exist and were reviewed
|
||
- ownership and transition validation exists
|
||
- tests cover important domain behavior
|
||
- frontend uses the authoritative API/state
|
||
- realtime is recoverable after reconnect where used
|
||
- build passes
|
||
- lint passes
|
||
- relevant tests pass
|
||
- no unrelated architecture was introduced
|
||
- documentation is updated when behavior changed
|
||
|
||
Do not claim completion if relevant tests or builds are failing.
|
||
|
||
---
|
||
|
||
# 41. Final Decision Filter
|
||
|
||
Before adding code, ask:
|
||
|
||
1. Does this improve the current core loop?
|
||
2. Is this required by the current specification?
|
||
3. Is the server still authoritative?
|
||
4. Can this be modeled as reusable data instead of a one-off?
|
||
5. Am I solving a current problem rather than a hypothetical future problem?
|
||
6. Does this fit the existing architecture?
|
||
7. Does the UI still feel like Ashen Realms rather than a generic web app?
|
||
8. Can the implementation be tested cleanly?
|
||
9. Does this preserve player progress and data integrity?
|
||
10. Is there a smaller correct implementation?
|
||
|
||
When in doubt:
|
||
|
||
> Prefer the smallest server-authoritative, data-driven solution that fits the current specification.
|