first commit
This commit is contained in:
223
rules.md
Normal file
223
rules.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# rules.md
|
||||
|
||||
**必须强制执行的约束。违反时立即终止并报错。**
|
||||
|
||||
---
|
||||
|
||||
## Code Style - Imports
|
||||
|
||||
### Python
|
||||
```python
|
||||
# Group order: stdlib → third-party → local
|
||||
import json
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
import redis
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.config import settings
|
||||
from app.models.user import User
|
||||
from app.schemas.user import UserCreate
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
```typescript
|
||||
// Group order: React → Third-party → Local
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import axios from 'axios';
|
||||
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import { api } from '@/services/api';
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Sort alphabetically within groups
|
||||
- Use absolute imports for external packages, relative for local modules
|
||||
- **NEVER** use wildcard imports (`from module import *`)
|
||||
|
||||
---
|
||||
|
||||
## Code Style - Formatting
|
||||
|
||||
- **Python:** 4-space indentation, Black formatter, max line 100
|
||||
- **TypeScript:** 2-space indentation, Prettier, max line 100
|
||||
- Run formatter **before committing**
|
||||
- No trailing whitespace
|
||||
- Empty line at end of file
|
||||
|
||||
---
|
||||
|
||||
## Code Style - Type Hints
|
||||
|
||||
```python
|
||||
# Use strict typing - NO Any
|
||||
from typing import List, Dict, Optional, Union
|
||||
from datetime import datetime
|
||||
|
||||
def get_gpu_clusters(
|
||||
country: Optional[str] = None,
|
||||
min_gpu_count: int = 0,
|
||||
) -> List[Dict[str, Union[str, int, float]]]:
|
||||
...
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Use type hints throughout
|
||||
- **NEVER** use `Any` - use `unknown` or specific unions
|
||||
- Define interfaces/types for all data structures
|
||||
- Generic types preferred over type casting
|
||||
|
||||
---
|
||||
|
||||
## Code Style - Naming Conventions
|
||||
|
||||
| Pattern | Usage | Example |
|
||||
|---------|-------|---------|
|
||||
| `camelCase` | Variables, functions, methods | `gpuCluster`, `getData()` |
|
||||
| `PascalCase` | Classes, components, types | `GPUCluster`, `DataSourceConfig` |
|
||||
| `SCREAMING_SNAKE_CASE` | Constants, env vars | `API_KEY`, `DATABASE_URL` |
|
||||
| `kebab-case` | File names, CSS | `data-source-config.css` |
|
||||
|
||||
**Rules:**
|
||||
- Descriptive names - avoid abbreviations except well-known ones (id, ok, err)
|
||||
- Max function length: 50 lines
|
||||
- Max file length: 500 lines
|
||||
|
||||
---
|
||||
|
||||
## Code Style - Error Handling
|
||||
|
||||
```python
|
||||
# Use custom exceptions
|
||||
class DataSourceError(Exception):
|
||||
"""Raised when data source fetch fails"""
|
||||
pass
|
||||
|
||||
# Proper error handling with logging
|
||||
try:
|
||||
data = await fetch_data(source)
|
||||
except requests.RequestException as e:
|
||||
logger.error(f"Failed to fetch from {source}: {e}")
|
||||
raise DataSourceError(f"Source {source} unavailable") from e
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- **NEVER swallow errors silently**
|
||||
- Use custom exceptions for domain errors
|
||||
-区分可恢复错误和不可恢复错误
|
||||
- Log errors with appropriate level (warn/error)
|
||||
- Include context in all error messages
|
||||
- Propagate errors to caller unless explicitly handled
|
||||
|
||||
---
|
||||
|
||||
## Security - NON-NEGOTIABLE
|
||||
|
||||
- **NEVER** commit `.env`, secrets, keys, or credentials
|
||||
- Use environment variables for all credentials
|
||||
- Validate and sanitize all user inputs
|
||||
- Use parameterized queries for database operations (SQL injection prevention)
|
||||
- JWT tokens with short expiration (15 min)
|
||||
- Redis for token blacklist (logout support)
|
||||
- Hash passwords with bcrypt/argon2 - **NEVER** store plain text
|
||||
|
||||
---
|
||||
|
||||
## Git Workflow
|
||||
|
||||
```bash
|
||||
# Create feature branch
|
||||
git checkout -b feature/data-collector-huggingface
|
||||
|
||||
# Commit message format
|
||||
git commit -m "feat: add Hugging Face data collector"
|
||||
git commit -m "fix: resolve WebSocket heartbeat timeout"
|
||||
git commit -m "docs: update API documentation"
|
||||
|
||||
# Before opening PR
|
||||
git fetch origin && git rebase origin/main
|
||||
pytest && npm run lint
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Feature branches from main
|
||||
- Clear commit messages - "Add user authentication", not "fix"
|
||||
- **NEVER** force push to main
|
||||
- Run tests and lint **before** committing
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
**Rules:**
|
||||
- Verify package legitimacy before adding
|
||||
- Prefer well-maintained, widely-used libraries
|
||||
- Pin dependency versions in `requirements.txt` and `package.json`
|
||||
- Review security advisories with `pip-audit` and `npm audit`
|
||||
- **NEVER** add unknown packages
|
||||
|
||||
---
|
||||
|
||||
## Data Collector Pattern - MANDATORY
|
||||
|
||||
```python
|
||||
class BaseCollector:
|
||||
async def fetch(self) -> List[Dict]:
|
||||
"""Fetch data from source"""
|
||||
...
|
||||
|
||||
def transform(self, raw_data: Dict) -> NormalizedData:
|
||||
"""Transform to internal format"""
|
||||
...
|
||||
|
||||
async def run(self):
|
||||
"""Full pipeline: fetch -> transform -> save"""
|
||||
raw = await self.fetch()
|
||||
data = self.transform(raw)
|
||||
await self.save(data)
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Each data source has its own collector class
|
||||
- Collectors **MUST** inherit from `BaseCollector`
|
||||
- Implement `fetch()` and `transform()` methods
|
||||
- Support incremental and full sync modes
|
||||
|
||||
---
|
||||
|
||||
## WebSocket Communication - MANDATORY
|
||||
|
||||
```python
|
||||
# Data frame format
|
||||
{
|
||||
"timestamp": "2024-01-15T10:30:00Z",
|
||||
"type": "update", # or "full"
|
||||
"payload": {
|
||||
"gpu_clusters": [...],
|
||||
"submarine_cables": [...],
|
||||
"ixp_nodes": [...]
|
||||
}
|
||||
}
|
||||
|
||||
# Heartbeat every 30 seconds
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- UE5 communicates via WebSocket (not REST)
|
||||
- Send data frames at configured intervals (default: 5 minutes)
|
||||
- Include camera position in control frames
|
||||
- Support auto-cruise and manual interaction modes
|
||||
|
||||
---
|
||||
|
||||
## General Guidelines
|
||||
|
||||
- Keep functions small and focused (single responsibility)
|
||||
- Write self-documenting code; comment **why**, not what
|
||||
- One concern per file/module
|
||||
- Dependency injection for testability
|
||||
- Feature flags for incomplete features
|
||||
- Use config files for environment-specific settings
|
||||
Reference in New Issue
Block a user