docs: Add comprehensive CLAUDE.md with architecture, commands, and guardrails
This commit is contained in:
@@ -0,0 +1,437 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
**K-ArtSell Aegis v16.0** is a complex financial/investment advisory system built on a **Modular Monolith** with **Vertical Slice** architecture. It enforces strict execution completeness, evidence preservation, and controlled model operations—not production-ready until all validation gates (252+ trading days shadow, OOS testing, PBO/DSR verification) pass.
|
||||
|
||||
**Status:** `IMPLEMENTATION_TEMPLATE / STATIC_VALIDATED / BUILD_DB_E2E_SHADOW_REHEARSAL_REQUIRED`
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- .NET 10 SDK
|
||||
- Node.js 22 / pnpm 10
|
||||
- PostgreSQL 17 (local via Docker Compose)
|
||||
- Docker & Docker Compose
|
||||
|
||||
### Local Development Environment
|
||||
|
||||
```bash
|
||||
# Start PostgreSQL
|
||||
docker-compose up -d
|
||||
|
||||
# Backend: restore, build, migrate, test
|
||||
dotnet restore KArtSell.sln
|
||||
dotnet build KArtSell.sln -c Release
|
||||
dotnet run --project src/KArtSell.DbMigrator -c Release
|
||||
|
||||
# Run backend tests
|
||||
dotnet test KArtSell.sln -c Release --logger trx
|
||||
|
||||
# Run a single test
|
||||
dotnet test --filter "FullyQualifiedName=MyNamespace.MyTest.TestMethod" -c Release
|
||||
|
||||
# Frontend: install, typecheck, test, build
|
||||
cd frontend
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm typecheck
|
||||
pnpm test
|
||||
pnpm build
|
||||
|
||||
# Run frontend E2E tests
|
||||
pnpm exec playwright install --with-deps chromium
|
||||
pnpm e2e
|
||||
|
||||
# Run dev server (watch mode, hot reload)
|
||||
pnpm dev # Backend in another terminal
|
||||
```
|
||||
|
||||
### Database Connection
|
||||
```
|
||||
Host: localhost
|
||||
Port: 5432
|
||||
Database: kartsell
|
||||
User: kartsell
|
||||
Password: kartsell
|
||||
```
|
||||
|
||||
Environment variable: `KARTSELL_POSTGRES=Host=localhost;Port=5432;Database=kartsell;Username=kartsell;Password=kartsell`
|
||||
|
||||
## Architecture
|
||||
|
||||
### Backend: Modular Monolith + Vertical Slices
|
||||
|
||||
#### Module Structure
|
||||
```
|
||||
src/
|
||||
KArtSell.Host/ # Main ASP.NET Core app
|
||||
KArtSell.BuildingBlocks/ # Shared infrastructure (logging, serialization, extensions)
|
||||
KArtSell.DbMigrator/ # DbUp migrations
|
||||
KArtSell.Modules.ModelOperations/ # Model lifecycle, validation, activation
|
||||
KArtSell.Modules.SignalEngine/ # Trading signal generation
|
||||
```
|
||||
|
||||
#### Vertical Slice Template
|
||||
Each feature is a complete, self-contained slice from HTTP endpoint to database, located under `Features/<SliceName>/`:
|
||||
|
||||
```
|
||||
Features/<SliceName>/
|
||||
Endpoint.cs # FastEndpoints route handler (HTTP/contract/status codes)
|
||||
Request.cs # Input model with validation via Zod-like pattern
|
||||
Response.cs # Output model (DTO)
|
||||
Validator.cs # Fluent/Policy validation rules
|
||||
Handler.cs # Use case orchestration (Application layer)
|
||||
Policy.cs # Pure business decision logic (Domain layer)
|
||||
Sql.cs # Dapper queries (Data layer)
|
||||
Mapper.cs # Entity ↔ DTO mapping
|
||||
Jobs/ # Related Hangfire jobs
|
||||
Contracts/ # Event/Job contract definitions
|
||||
Tests/ # Unit/integration tests specific to this slice
|
||||
README.md # Traceability: requirements, ADRs, assumptions
|
||||
```
|
||||
|
||||
**Key rule:** Endpoint handles HTTP concerns (routing, negotiation); Handler handles transaction boundaries; Policy makes decisions; Sql uses Dapper for explicit, schema-qualified queries.
|
||||
|
||||
#### Design Principles
|
||||
- **No Generic Repository:** Each slice writes its own Dapper queries; promotes clarity.
|
||||
- **No Service Layer:** Handler + Policy + Sql replaces it; keeps flow visible.
|
||||
- **Module Isolation:** Modules do not query each other's source tables directly.
|
||||
- Synchronous: Use narrow Read Port services.
|
||||
- Asynchronous: Use Outbox/Inbox event patterns.
|
||||
- **PIT (Point-in-Time) Queries:** Must include `WHERE published_at <= cutoff` and revision resolver.
|
||||
- **Evidence & Audit:** Update/delete are blocked; new state appended as new revision.
|
||||
- **Migrations:** `src/KArtSell.DbMigrator` uses DbUp; file naming: `NNNN_description.sql`. Each module has ordered, checksummed migrations.
|
||||
|
||||
### Frontend: Vue 3 + Vite + Modular Feature Structure
|
||||
|
||||
#### Directory Layout
|
||||
```
|
||||
frontend/src/
|
||||
app/ # Core app initialization, routing, config
|
||||
features/ # Feature modules (one per business capability)
|
||||
<feature>/
|
||||
components/ # Scoped to this feature
|
||||
pages/ # Route-level pages
|
||||
stores/ # Pinia stores (state management)
|
||||
composables/ # Reusable logic (Vue 3 hooks)
|
||||
types/ # TS interfaces for this feature
|
||||
shared/
|
||||
ui/
|
||||
adapter/ # PrimeVue/AG Grid wrappers (mandatory boundary)
|
||||
components/ # Common components (QueryStateBoundary, PermissionGuard, CrudForm, etc.)
|
||||
layouts/ # Page layout templates
|
||||
crud/ # Generic CRUD form logic
|
||||
composables/ # Global composables (useFetch, useAuth, etc.)
|
||||
types/ # Global types, contracts
|
||||
stores/ # Global Pinia stores (auth, user, preferences)
|
||||
design-system/ # Design tokens, typography, color scales (PrimeVue theme overrides)
|
||||
```
|
||||
|
||||
#### State Management Rules
|
||||
| State | Owner | Tool |
|
||||
|-------|-------|------|
|
||||
| API responses, cache, stale, retry | TanStack Query | @tanstack/vue-query |
|
||||
| Session, role, UI preferences | Global store | Pinia |
|
||||
| Form values, errors, touched | Form library | vee-validate + Zod |
|
||||
| URL filters, pagination, sorting | Router | vue-router query/params |
|
||||
| Large data tables, virtual scroll | Server-side row model | AG Grid server mode |
|
||||
|
||||
**Anti-patterns:**
|
||||
- Do NOT duplicate API responses in Pinia.
|
||||
- Do NOT write 401/409/422/429/503 error handling in every screen.
|
||||
- Do NOT manage query cache manually; let TanStack Query handle it.
|
||||
|
||||
#### Component Elevation Criteria
|
||||
Promote to `shared/ui/components/` only when:
|
||||
1. **Same business meaning & permissions** (not just visual similarity).
|
||||
2. **Repeated state/error handling logic** across 3+ consumers.
|
||||
3. **Accessibility & testing** already fully implemented.
|
||||
|
||||
**Always-shared components:**
|
||||
- `QueryStateBoundary` (loading/error/empty states)
|
||||
- `PermissionGuard` (RBAC enforcement)
|
||||
- `CrudForm` (standard CRUD form)
|
||||
- `VersionConflictDialog` (optimistic concurrency)
|
||||
- `DataFreshnessBadge` (cache/stale indicators)
|
||||
- `DataGridShell` (AG Grid wrapper with sorting, filtering, export)
|
||||
|
||||
### Database & Migrations
|
||||
|
||||
#### DbUp
|
||||
- **Run at startup:** `KArtSell.DbMigrator` is the single source of truth.
|
||||
- **Schema ownership:** Each module owns its schema (e.g., `model_operations.*`, `signal_engine.*`).
|
||||
- **Safety:** Migrations are idempotent and checksummed; failed migration rolls back and waits for manual intervention.
|
||||
- **Test:** Each migration has fresh/upgrade/re-run/failure-recovery tests in CI.
|
||||
|
||||
#### Query Patterns
|
||||
```csharp
|
||||
// DO: Schema-qualified, explicit columns, cancellation token
|
||||
const string sql = """
|
||||
SELECT id, name, created_at
|
||||
FROM model_operations.signals
|
||||
WHERE published_at <= @cutoff
|
||||
AND status = @status
|
||||
ORDER BY created_at DESC
|
||||
""";
|
||||
|
||||
// DON'T: SELECT *, generic repository, no token
|
||||
const string sql = "SELECT * FROM signals WHERE status = @status";
|
||||
```
|
||||
|
||||
#### Async Coupling: Outbox/Inbox
|
||||
- **Outbox:** When a command succeeds, events are inserted into `outbox` in the same transaction.
|
||||
- **Inbox:** A Hangfire job polls the outbox, publishes events, and marks them as processed.
|
||||
- **Idempotency:** Each inbox handler is idempotent; replayed events are no-ops.
|
||||
|
||||
### Hangfire (Background Jobs & Scheduling)
|
||||
|
||||
#### Job Design
|
||||
- **Not a business decision maker:** Hangfire executes approved Application Commands, not policies.
|
||||
- **Idempotency key:** Each job must be replayable without side effects.
|
||||
- **Watermark & version set:** Track input/output state across retries.
|
||||
- **Queue isolation:** `q-customer-sla` (business SLA) is separate from `q-research` (non-critical).
|
||||
- **Retry classification:**
|
||||
- `transient` (network glitch, retry immediately)
|
||||
- `permanent` (bad input, log & alert)
|
||||
- `dq` (data quality issue, quarantine for manual review)
|
||||
- `business-hold` (awaiting approval or external event)
|
||||
|
||||
#### Example Job Structure
|
||||
```csharp
|
||||
public class MyJobCommand : ICommand
|
||||
{
|
||||
public string IdempotencyKey { get; set; }
|
||||
public Guid JobRunId { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
Jobs do not call other jobs directly; instead, they emit events or check readiness gates.
|
||||
|
||||
### SignalR (Real-Time Push)
|
||||
|
||||
Used for live notifications (model activation events, approval notifications). Follows Hub/Group pattern with correlation to `CorrelationId` for traceability.
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### xUnit Backend Tests
|
||||
|
||||
#### Test Organization
|
||||
```
|
||||
tests/
|
||||
KArtSell.ArchitectureTests/ # Compile-time architecture rules
|
||||
KArtSell.ModelOperations.UnitTests/
|
||||
KArtSell.SignalEngine.UnitTests/
|
||||
KArtSell.Integration.Tests/ # E2E with real DB (if exists)
|
||||
```
|
||||
|
||||
#### Test Levels
|
||||
1. **Unit:** Pure functions (Policy, Mapper), no I/O. Fast, deterministic.
|
||||
2. **Integration:** Handler + Dapper + real PostgreSQL. Validates transaction boundaries, Outbox/Inbox.
|
||||
3. **Data:** SQL query validation, schema conformance, index effectiveness.
|
||||
4. **E2E:** Full HTTP stack; used sparingly for critical paths.
|
||||
5. **Golden/Frozen OOS:** Before merging algorithm changes, lock baseline and diff against new run.
|
||||
|
||||
#### Run Tests
|
||||
```bash
|
||||
dotnet test KArtSell.sln -c Release
|
||||
dotnet test --filter "Category=Integration" -c Release
|
||||
dotnet test --filter "FullyQualifiedName~UnitTests" -c Release --verbosity quiet
|
||||
```
|
||||
|
||||
### Vitest Frontend Tests
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
pnpm test # Run all tests
|
||||
pnpm test -- --reporter=verbose # Verbose output
|
||||
pnpm test -- <test-file-pattern> # Run subset
|
||||
pnpm test -- --coverage # Coverage report
|
||||
```
|
||||
|
||||
### Playwright E2E
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
pnpm e2e # Run all E2E tests headless
|
||||
pnpm e2e -- --debug # Debug mode (browser stays open)
|
||||
pnpm exec playwright test --headed # Run with browser UI
|
||||
```
|
||||
|
||||
## Observability
|
||||
|
||||
### Logging
|
||||
- **Tool:** Serilog with structured properties.
|
||||
- **Correlation:** All logs are tagged with `CorrelationId`, `JobRunId`, `EvidenceId`.
|
||||
- **Sensitive data:** PII, tokens, API keys are NEVER logged (use redaction middleware).
|
||||
- **Levels:** INFO (user actions), DEBUG (internal flow), WARN (recoverable issues), ERROR (unrecoverable, alert required).
|
||||
|
||||
### Tracing & Metrics
|
||||
- **Tool:** OpenTelemetry for distributed tracing and metrics.
|
||||
- **Spans:** HTTP requests, database queries, job execution, event processing.
|
||||
- **Alerts:** Send to Telegram integration (configured in `KArtSell.Host` startup).
|
||||
|
||||
### Operational Dashboards (Priority Order)
|
||||
1. **Batch SLA:** Job completion times, queue depths (q-customer-sla vs q-research).
|
||||
2. **Data Quality Quarantine:** Jobs marked `dq` by retry classifier.
|
||||
3. **Duplicate Detection:** Outbox duplicate events.
|
||||
4. **Reconciliation Breaks:** Mismatch between expected and actual state (Evidence vs current).
|
||||
5. **Model Drift:** OOS (out-of-sample) performance metrics.
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Adding a New Vertical Slice
|
||||
|
||||
1. **Scaffold the structure:**
|
||||
```bash
|
||||
python tools/scaffold_vertical_slice.py --name MyFeature --module ModelOperations
|
||||
```
|
||||
|
||||
2. **Define the contract** (before code):
|
||||
- Request/Response DTOs in `Contracts/`
|
||||
- Event schema in `Contracts/Events/` if async coupling needed
|
||||
- Validation rules (vee-validate schema on FE, Fluent on BE)
|
||||
|
||||
3. **Implement backend slice:**
|
||||
- `Handler.cs`: Orchestration, transaction handling
|
||||
- `Policy.cs`: Pure business logic
|
||||
- `Sql.cs`: Dapper queries (schema-qualified, no SELECT *)
|
||||
- `Endpoint.cs`: HTTP routing & status codes
|
||||
- `README.md`: Traceability link to requirement/ADR
|
||||
|
||||
4. **Write tests:**
|
||||
- Unit: Policy, Mapper logic
|
||||
- Integration: Handler + Dapper + real DB
|
||||
- Verify Outbox events are created if async
|
||||
|
||||
5. **Implement frontend feature:**
|
||||
- Feature module under `features/<feature>/`
|
||||
- Use `features/<feature>/pages/` for route-level components
|
||||
- Use `shared/ui/adapter/` for any UI component usage
|
||||
- Form validation with vee-validate + Zod schema from BE contract
|
||||
|
||||
6. **Validation gates (pre-merge):**
|
||||
- Architecture tests pass
|
||||
- DB migration is idempotent (fresh/upgrade test)
|
||||
- No SELECT *, no direct cross-module queries
|
||||
- Outbox/Inbox tests if async
|
||||
- Frontend typecheck + test + build
|
||||
- E2E smoke test (if user-facing)
|
||||
|
||||
### Refactoring (Characterized, Isolated, Verified)
|
||||
|
||||
1. **Characterize:** Lock current behavior with tests + perf baseline + Golden data.
|
||||
2. **Isolate:** Separate I/O (Dapper queries, HTTP) from logic (Policy).
|
||||
3. **Transform:** One small change at a time (rename, extract, move).
|
||||
4. **Verify:** All tests pass, no perf regression, backtest algorithm changes against Golden.
|
||||
5. **Simplify:** Delete dead abstractions, feature flags, branches.
|
||||
6. **Observe:** Post-release SLO/DQ/model drift monitoring.
|
||||
7. **Close Debt:** Update Debt ID, leave ADR for future maintainers.
|
||||
|
||||
### Creating a Background Job
|
||||
|
||||
1. **Define the command:**
|
||||
```csharp
|
||||
public class MyJobCommand : ICommand
|
||||
{
|
||||
public Guid IdempotencyKey { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
public string InputData { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
2. **Implement the handler:**
|
||||
- Idempotent: Re-run should be safe and produce same result.
|
||||
- Classify failures: transient/permanent/dq/business-hold.
|
||||
- Emit events to Outbox for async notifications.
|
||||
|
||||
3. **Schedule via Hangfire:**
|
||||
```csharp
|
||||
await backgroundJobClient.EnqueueAsync<MyJobHandler>(h => h.Handle(command));
|
||||
```
|
||||
|
||||
4. **Test retry & replay scenarios:**
|
||||
- Job runs successfully.
|
||||
- Job fails and is retried (verify idempotency).
|
||||
- Job is replayed from cold state (verify determinism).
|
||||
|
||||
## Guardrails & Anti-Patterns
|
||||
|
||||
### Coding Standards (from VIBE_CODING_GUARDRAILS.md)
|
||||
|
||||
**Before requesting code changes, ensure these 8 inputs are present:**
|
||||
1. **Source:** Reference policy, ADR, data contract, requirement ID
|
||||
2. **Slice Spec:** User goal, non-goal, state transitions, RBAC
|
||||
3. **Screen Spec:** Component tree, state management, a11y
|
||||
4. **Contract:** Endpoint paths, event schemas, HTTP status codes, ETag/idempotency handling
|
||||
5. **Data:** Schema, columns, PIT conditions, migration, index plan
|
||||
6. **Tests:** Unit/integration/data/E2E/Golden scenarios + failure cases
|
||||
7. **Ops:** Metrics, alerts, runbooks, rollback procedure, on-call owner
|
||||
8. **Output Rule:** Changed files, commands to verify, assumptions, residual risks
|
||||
|
||||
### Blocking Rules
|
||||
- **No undocumented policy IDs or thresholds.** Every numeric constant must trace to a requirement.
|
||||
- **Pending decisions:** Mark with `DECISION_REQUIRED` or `DESIGN_PROPOSAL` comment.
|
||||
- **One PR = one slice or one refactoring goal.** No mixing feature work + unrelated cleanup.
|
||||
- **Feature changes ≠ refactoring.** Separate PRs: feature, then refactoring, then verify.
|
||||
- **Never hide failing/skipped tests.** If a test fails, fix it or raise an issue.
|
||||
- **SQL review:** Generated SQL must pass schema owner review, PIT validation, index analysis.
|
||||
- **Algorithm changes:** Never merge without Golden/Frozen OOS diff showing no regression.
|
||||
- **Real customer data:** Never include in prompts, fixtures, or logs.
|
||||
|
||||
### Model Operations Specifics
|
||||
- **Model lifecycle:** Freeze → Mature → Score → Diagnose → Hypothesis → Challenger → Validate → Review → Manual Activation. No auto-learning, auto-promotion, or auto-ordering.
|
||||
- **Sell priority:** `HARD_IMPAIRMENT → PORTFOLIO_SURVIVAL → DYNAMIC_PROFIT_FLOOR → CONCENTRATION/LIQUIDITY → OPPORTUNITY_COST → REENTRY_OPTION` (immutable).
|
||||
- **Non-value-loss sell:** Requires ReentryWatch, new CycleId/Lot, step intervals, expiry, dedup.
|
||||
- **Activation gating:** Every model activation requires ModelCard, OOS/PBO/DSR evidence, maker-checker approval, effective_at timestamp, rollback justification.
|
||||
|
||||
## Tools & Scripts
|
||||
|
||||
### Scaffolding
|
||||
```bash
|
||||
python tools/scaffold_vertical_slice.py --name MyFeature --module ModelOperations
|
||||
python tools/scaffold_ui_screen.py --name MyScreen --feature MyFeature
|
||||
```
|
||||
|
||||
### Validation
|
||||
```bash
|
||||
python tools/validate_v16.py # Full v16 validation (contracts, migrations, Python tests)
|
||||
python -m unittest discover # Run all Python unit tests
|
||||
```
|
||||
|
||||
### FastEndpoints
|
||||
- Docs: [FastEndpoints GitHub](https://github.com/FastEndpoints/FastEndpoints)
|
||||
- Pattern: Each endpoint maps to a Vertical Slice; routes are discovered automatically.
|
||||
|
||||
## Documentation & Resources
|
||||
|
||||
### Key Documents
|
||||
- `docs/03_ARCHITECTURE_BE_FE.md` — Modular Monolith, Vertical Slice, Dapper, Hangfire, FE state ownership rules.
|
||||
- `docs/06_VIBE_CODING_GUARDRAILS.md` — AI input packets, blocking rules, refactoring methodology.
|
||||
- `contracts/ui/ui-adapter.v3.json` — FE adapter contract (PrimeVue/AG Grid wrapper boundaries).
|
||||
- `contracts/schedules/model-operations.v3.json` — Job scheduling contract.
|
||||
- `README.md` — Project status, v16 delta, validation gates.
|
||||
|
||||
### Contracts Directory
|
||||
```
|
||||
contracts/
|
||||
ui/ # Frontend adapter & component contracts
|
||||
schedules/ # Job scheduling contracts
|
||||
data/ # Domain data models (PIT envelope, projection)
|
||||
events/ # Async event schemas
|
||||
metrics/ # Outcome metrics schema
|
||||
```
|
||||
|
||||
## Validation Gates (Not Yet Passed)
|
||||
|
||||
Do NOT claim production readiness until:
|
||||
- `.NET 10 restore/build/test` on CI passes consistently
|
||||
- `pnpm frozen install/typecheck/Vitest/build/Playwright` on CI passes
|
||||
- PostgreSQL DbUp fresh/upgrade/re-run/failure-recovery tests pass
|
||||
- Outbox/Inbox crash-recovery & audit reconciliation rehearsal passes
|
||||
- 252+ trading-day shadow run with OOS at multiple market phases
|
||||
- PBO (probability of backtest overfit) and DSR (daily sharpe ratio) evidence
|
||||
|
||||
Before all gates pass: **No production deployment, no advisory-with-automation, no auto-ordering, no auto-model-promotion.**
|
||||
Reference in New Issue
Block a user