|
1 | 1 | # Code Style and Conventions |
2 | 2 |
|
3 | | -## Python Style (API, Core, Tests) |
4 | | -- **Linter/Formatter**: Ruff (enforces PEP 8) |
5 | | -- **Line Length**: 120 characters |
| 3 | +## Python (API, Core, Tests) |
| 4 | +- **Linter/Formatter**: Ruff (line-length=120, target=py314) |
| 5 | +- **Rules**: E, F, W, I, C, B (ignores E501, C901, B008) |
| 6 | +- **Excludes**: plots/, scripts/, .git, .venv, __pycache__, dist, temp |
6 | 7 | - **Type Hints**: Required for all functions |
7 | | -- **Docstrings**: Google style for all public functions |
8 | | -- **Import Order**: Standard library → Third-party → Local |
9 | | - |
10 | | -### Example (for API/core code): |
11 | | -```python |
12 | | -def get_spec_by_id(spec_id: str, db: Session) -> Spec: |
13 | | - """ |
14 | | - Retrieve a spec by its ID. |
15 | | -
|
16 | | - Args: |
17 | | - spec_id: The unique spec identifier |
18 | | - db: Database session |
19 | | -
|
20 | | - Returns: |
21 | | - Spec object if found |
22 | | -
|
23 | | - Raises: |
24 | | - NotFoundError: If spec doesn't exist |
25 | | - """ |
26 | | - pass |
27 | | -``` |
| 8 | +- **Docstrings**: Google style for public functions |
| 9 | +- **Import Order**: stdlib → third-party → local (enforced by ruff I) |
| 10 | +- **Async**: SQLAlchemy async, pytest-asyncio (auto mode) |
| 11 | + |
| 12 | +## TypeScript (Frontend) |
| 13 | +- **Linter**: ESLint 10 with typescript-eslint |
| 14 | +- **Strict mode**: Enabled in tsconfig |
| 15 | +- **Target**: ES2020, bundler module resolution |
| 16 | +- **Path alias**: `@/` → `./src/` |
| 17 | +- **Components**: PascalCase files (e.g., `PlotCard.tsx`), function components only |
| 18 | +- **Hooks**: camelCase with `use` prefix (e.g., `useSpecs.ts`) |
| 19 | +- **Utils/Types**: camelCase files (e.g., `api.ts`) |
| 20 | +- **Exports**: Named exports (no default exports) |
| 21 | +- **Styling**: MUI `sx` prop + Emotion `styled()`, no CSS modules |
| 22 | +- **State**: Local state + custom hooks (no Redux/Zustand) |
| 23 | +- **API calls**: Plain `fetch()` in `utils/api.ts` |
| 24 | + |
| 25 | +## Agentic Layer Conventions |
| 26 | +- **Script headers**: uv inline script metadata (dependencies declared in-file) |
| 27 | +- **CLI**: Click for all workflow scripts |
| 28 | +- **Console output**: Rich library, stderr for UI, stdout for state JSON |
| 29 | +- **State**: `WorkflowState` persisted at `agentic/runs/{run_id}/state.json` |
| 30 | +- **Templates**: `agentic/commands/*.md` with `$1`, `$2`, `$ARGUMENTS` placeholders |
| 31 | +- **Execution**: `prompt_claude_code_with_retry()` in `agent.py` |
| 32 | +- **Data types**: `TestResult`, `ReviewResult`, `ReviewIssue` in `agent.py` |
| 33 | +- **JSON parsing**: `parse_json()` handles markdown-fenced JSON from LLM output |
28 | 34 |
|
29 | 35 | ## Plot Implementation Style (KISS) |
30 | | -Plot implementations should be simple, readable scripts - like matplotlib gallery examples: |
31 | | - |
32 | 36 | ```python |
33 | 37 | """ |
34 | | -scatter-basic: Basic Scatter Plot |
35 | | -Library: matplotlib |
| 38 | +spec-id: Plot Title |
| 39 | +Library: library-name |
36 | 40 | """ |
37 | | - |
38 | 41 | import matplotlib.pyplot as plt |
39 | 42 | import numpy as np |
40 | 43 |
|
41 | 44 | # Data |
42 | 45 | np.random.seed(42) |
43 | 46 | x = np.random.randn(100) |
44 | | -y = x * 0.8 + np.random.randn(100) * 0.5 |
45 | 47 |
|
46 | 48 | # Plot |
47 | 49 | fig, ax = plt.subplots(figsize=(16, 9)) |
48 | | -ax.scatter(x, y, alpha=0.7, s=50, color='#306998') |
49 | | - |
50 | | -ax.set_xlabel('X Value') |
51 | | -ax.set_ylabel('Y Value') |
52 | | -ax.set_title('Basic Scatter Plot') |
53 | | -ax.grid(True, alpha=0.3) |
54 | | - |
| 50 | +ax.scatter(x, y) |
| 51 | +ax.set_title('Title') |
55 | 52 | plt.tight_layout() |
56 | 53 | plt.savefig('plot.png', dpi=300, bbox_inches='tight') |
57 | 54 | ``` |
58 | | - |
59 | | -### Plot Code Rules: |
60 | | -- No functions, no classes |
61 | | -- No `if __name__ == '__main__':` |
62 | | -- No type hints or docstrings (in plot code) |
63 | | -- Just: imports → data → plot → save |
| 55 | +- No functions, no classes, no `if __name__` |
| 56 | +- No type hints or docstrings in plot code |
| 57 | +- Flow: imports → data → plot → save |
64 | 58 |
|
65 | 59 | ## Naming Conventions |
66 | | - |
67 | | -### Spec IDs |
68 | | -Format: `{plot-type}-{variant}-{modifier}` (lowercase, hyphens only) |
69 | | -- `scatter-basic` - Simple 2D scatter plot |
70 | | -- `bar-grouped-horizontal` - Horizontal grouped bars |
71 | | -- `heatmap-correlation` - Correlation matrix heatmap |
72 | | - |
73 | | -### Files |
74 | | -- Implementation files: `{library}.py` (e.g., `matplotlib.py`) |
75 | | -- Metadata files: `{library}.yaml` |
76 | | - |
77 | | -## General Rules |
78 | | -- Always write in English |
79 | | -- Testing coverage target: 90%+ |
80 | | -- Test naming: `test_{what_it_does}` |
| 60 | +- **Spec IDs**: `{plot-type}-{variant}-{modifier}` (lowercase, hyphens) |
| 61 | +- **Implementation files**: `{library}.py` |
| 62 | +- **Metadata files**: `{library}.yaml` |
| 63 | +- **Test naming**: `test_{what_it_does}` |
| 64 | +- **All output**: English only (comments, commits, docs, PRs) |
0 commit comments