|
1 | | -# Contributor Quickstart Guide |
| 1 | +# AI Agent Guide for Fromager |
2 | 2 |
|
3 | | -## Commit Message Guidelines |
| 3 | +> **Note**: This file is also available as `CLAUDE.md` (symlink) for Claude Code CLI users. |
| 4 | +> |
| 5 | +> **IMPORTANT**: Before making any code changes, you MUST read [CONTRIBUTING.md](CONTRIBUTING.md) for comprehensive coding standards and design patterns. This file provides essential quick reference only. |
4 | 6 |
|
5 | | -### Objectives |
| 7 | +## When to Read CONTRIBUTING.md |
6 | 8 |
|
7 | | -- Help the user craft commit messages that follow best practices |
8 | | -- Use [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/) format unless otherwise specified |
9 | | -- Clarify unclear or incomplete input with targeted questions |
10 | | -- Ensure messages are concise, informative, and use imperative mood |
| 9 | +**Always read CONTRIBUTING.md before:** |
11 | 10 |
|
12 | | -### Style Guidelines |
| 11 | +- Writing new functions (for type annotation standards) |
| 12 | +- Adding imports (for import organization rules) |
| 13 | +- Creating tests (for testing patterns) |
| 14 | +- Making commits (for commit message format) |
| 15 | +- Adding error handling or logging |
13 | 16 |
|
14 | | -- Use the format: `<type>(<scope>): <short summary>` for the subject line |
15 | | -- Keep the subject line ≤ 72 characters |
16 | | -- Use a blank line before the body |
17 | | -- The body explains what and why (not how) |
18 | | -- Use a footer for metadata (e.g., `Closes: #123`, `BREAKING CHANGE:`) |
| 17 | +## Essential Rules (MUST FOLLOW) |
19 | 18 |
|
20 | | -### Commit Types |
| 19 | +### Do |
21 | 20 |
|
22 | | -- **feat**: a new feature |
23 | | -- **fix**: a bug fix |
24 | | -- **docs**: documentation only changes |
25 | | -- **style**: formatting, missing semi colons, etc |
26 | | -- **refactor**: code change that neither fixes a bug nor adds a feature |
27 | | -- **perf**: performance improvements |
28 | | -- **test**: adding missing tests |
29 | | -- **chore**: changes to the build process or auxiliary tools |
| 21 | +- **Type annotations REQUIRED** on ALL functions including tests. Use syntax compatible with Python 3.11+ |
| 22 | +- Use `X | None` not `Optional[X]` |
| 23 | +- Add docstrings on all public functions and classes |
| 24 | +- Use file-scoped commands for fast feedback (see below) |
| 25 | +- Follow existing patterns - search codebase for similar code |
| 26 | +- Chain exceptions: `raise ValueError(...) from err` |
| 27 | +- Use `req_ctxvar_context()` for per-requirement logging |
| 28 | +- Run `hatch run lint:fix` to format code (handles line length, whitespace, etc.) |
30 | 29 |
|
31 | | -### Examples |
| 30 | +### Don't |
32 | 31 |
|
33 | | -#### Good commit messages |
| 32 | +- Don't use `Optional[X]` syntax (use `X | None`) |
| 33 | +- Don't omit type annotations or return types |
| 34 | +- Don't run full test suite for small changes (use file-scoped) |
| 35 | +- Don't create temporary helper scripts or workarounds |
| 36 | +- Don't commit without running quality checks |
| 37 | +- Don't make large speculative changes without asking |
| 38 | +- Don't update git config or force push to main |
| 39 | +- Don't use bare `except:` - always specify exception types |
34 | 40 |
|
35 | | -```text |
36 | | -feat(api): add user authentication endpoint |
| 41 | +## Commands (IMPORTANT: Use File-Scoped First) |
37 | 42 |
|
38 | | -Add JWT-based authentication system for secure API access. |
39 | | -Includes token generation, validation, and refresh functionality. |
| 43 | +### File-Scoped Commands (PREFER THESE) |
40 | 44 |
|
41 | | -Closes: #123 |
42 | | -``` |
| 45 | +```bash |
| 46 | +# Type check single file |
| 47 | +hatch run mypy:check <filepath> |
43 | 48 |
|
44 | | -```text |
45 | | -fix(parser): handle empty input gracefully |
| 49 | +# Format single file |
| 50 | +hatch run lint:fix <filepath> |
| 51 | + |
| 52 | +# Test specific file |
| 53 | +hatch run test:test tests/test_<module>.py |
46 | 54 |
|
47 | | -Previously, empty input would cause a null pointer exception. |
48 | | -Now returns an appropriate error message. |
| 55 | +# Test specific function |
| 56 | +hatch run test:test tests/test_<module>.py::test_function_name |
| 57 | + |
| 58 | +# Debug test with verbose output |
| 59 | +hatch run test:test <filepath> --log-level DEBUG |
49 | 60 | ``` |
50 | 61 |
|
51 | | -```text |
52 | | -docs: update installation instructions |
| 62 | +### Project-Wide Commands (ASK BEFORE RUNNING) |
53 | 63 |
|
54 | | -Add missing dependency requirements and clarify setup steps |
55 | | -for new contributors. |
| 64 | +```bash |
| 65 | +hatch run lint:fix # Format all code |
| 66 | +hatch run test:test # Full test suite (slow!) |
| 67 | +hatch run mypy:check # Type check everything |
| 68 | +hatch run lint:check # Final lint check |
56 | 69 | ``` |
57 | 70 |
|
58 | | -#### Poor commit messages to avoid |
| 71 | +## Safety and Permissions |
59 | 72 |
|
60 | | -- `fix bug` (too vague) |
61 | | -- `updated files` (not descriptive) |
62 | | -- `WIP` (not informative) |
63 | | -- `fixed the thing that was broken` (not professional) |
| 73 | +### Allowed Without Asking |
64 | 74 |
|
65 | | -### Best Practices |
| 75 | +- Read files, search codebase |
| 76 | +- Run file-scoped linting, type checking, tests |
| 77 | +- Edit existing files following established patterns |
| 78 | +- Create test files |
66 | 79 |
|
67 | | -- Write in imperative mood (e.g., "add feature" not "added feature") |
68 | | -- Don't end the subject line with a period |
69 | | -- Use the body to explain the motivation for the change |
70 | | -- Reference issues and pull requests where relevant |
71 | | -- Use `BREAKING CHANGE:` in footer for breaking changes |
| 80 | +### Ask First |
72 | 81 |
|
73 | | -## Code Quality Guidelines |
| 82 | +- Installing/updating packages in pyproject.toml |
| 83 | +- Git commit or push operations |
| 84 | +- Deleting files or entire modules |
| 85 | +- Running full test suite |
| 86 | +- Creating new modules or major refactors |
| 87 | +- Making breaking changes |
74 | 88 |
|
75 | | -### Formatting Standards |
| 89 | +## Project Structure |
76 | 90 |
|
77 | | -- **No trailing whitespace**: Ensure no extra spaces at the end of lines |
78 | | -- **No whitespace on blank lines**: Empty lines should contain no spaces or tabs |
79 | | -- **End files with a single newline**: Each file should end with a single newline character (`\n`). This is a widely adopted convention recommended by PEP 8, Python's style guide. Many Unix-style text editors and tools expect files to end with a newline character and may not handle files without one properly. |
80 | | -- Follow the project's existing code style and indentation patterns |
81 | | -- Use consistent line endings (LF for this project) |
| 91 | +- `src/fromager/` - Main package code |
| 92 | +- `tests/` - Unit tests (mirror `src/` structure) |
| 93 | +- `e2e/` - End-to-end integration tests |
| 94 | +- `docs/` - Sphinx documentation |
82 | 95 |
|
83 | | -### Type Annotations |
| 96 | +### Reference Files for Patterns |
84 | 97 |
|
85 | | -- **Always add type annotations to all functions**: All functions must include type annotations for parameters and return values |
86 | | -- This applies to regular functions, test functions, class methods, and async functions |
87 | | -- Existing code will be updated gradually; new code must be fully typed |
88 | | -- Follow the existing pattern in the codebase for consistency |
89 | | -- Examples: |
| 98 | +**Before writing code, look at these examples:** |
90 | 99 |
|
91 | | - ```python |
92 | | - def calculate_total(items: list[int]) -> int: |
93 | | - """Calculate sum of items.""" |
94 | | - return sum(items) |
| 100 | +- Type annotations: `src/fromager/context.py` |
| 101 | +- Pydantic models: `src/fromager/packagesettings.py` |
| 102 | +- Logging with context: `src/fromager/resolver.py` |
| 103 | +- Error handling: `src/fromager/commands.py` |
| 104 | +- Testing patterns: `tests/test_context.py` |
95 | 105 |
|
96 | | - def test_my_feature() -> None: |
97 | | - """Test that my feature works correctly.""" |
98 | | - assert my_feature() == expected_result |
99 | | - ``` |
| 106 | +## Code Patterns |
100 | 107 |
|
101 | | -### Code Comments |
| 108 | +**Import Guidelines:** |
102 | 109 |
|
103 | | -- **Avoid unnecessary comments**: Write self-documenting code with clear variable names, function names, and structure |
104 | | -- **Only add comments when absolutely necessary**: Comments should be reserved for must-have cases such as: |
105 | | - - Explaining complex algorithms or non-obvious logic |
106 | | - - Documenting "why" decisions were made (not "what" the code does) |
107 | | - - Warning about edge cases or subtle bugs |
108 | | - - Explaining workarounds for external library issues |
109 | | -- **Do not add comments that simply restate what the code does**: The code itself should be clear enough |
110 | | -- **Prefer docstrings over comments**: Use docstrings for functions, classes, and modules to document their purpose and usage |
| 110 | +- **PEP 8: imports should be at the top**: All import statements must be placed at the top of the file, after module docstrings and before other code |
| 111 | +- **No local imports**: Do not place import statements inside functions, methods, or conditional blocks |
111 | 112 |
|
112 | | -### Testing After Code Changes |
| 113 | +### Testing Pattern |
113 | 114 |
|
114 | | -After making code changes, run the following tests within a Python virtual environment to ensure code quality: |
| 115 | +```python |
| 116 | +def test_behavior(tmp_path: pathlib.Path) -> None: |
| 117 | + """Verify expected behavior.""" |
| 118 | + # Arrange |
| 119 | + config = tmp_path / "config.txt" |
| 120 | + config.write_text("key=value\n") |
| 121 | + # Act |
| 122 | + result = load_config(config) |
| 123 | + # Assert |
| 124 | + assert result["key"] == "value" |
| 125 | +``` |
115 | 126 |
|
116 | | -#### Run all unit tests |
| 127 | +## Commit Message Format (REQUIRED) |
117 | 128 |
|
118 | | -```bash |
119 | | -hatch run test:test |
| 129 | +Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format: |
| 130 | + |
| 131 | +```text |
| 132 | +<type>(<scope>): <short summary> |
| 133 | +
|
| 134 | +<body explaining what + why> |
| 135 | +
|
| 136 | +<footer: Closes: #123> |
120 | 137 | ``` |
121 | 138 |
|
122 | | -#### Run lint checks |
| 139 | +### Types |
123 | 140 |
|
124 | | -```bash |
125 | | -hatch run lint:check |
| 141 | +- **feat**: new functionality |
| 142 | +- **fix**: bug fix |
| 143 | +- **docs**: documentation only |
| 144 | +- **test**: tests only |
| 145 | +- **refactor**: behavioral no-op refactor |
| 146 | +- **perf**: performance improvement |
| 147 | +- **chore**: tooling or dependency change |
| 148 | + |
| 149 | +### Good Examples |
| 150 | + |
| 151 | +```text |
| 152 | +feat(resolver): add exponential backoff for HTTP retries |
| 153 | +
|
| 154 | +Improves resilience when PyPI is under load by adding jittered backoff. |
| 155 | +
|
| 156 | +Closes: #123 |
126 | 157 | ``` |
127 | 158 |
|
128 | | -#### Run mypy type checking |
| 159 | +```text |
| 160 | +fix(constraints): handle missing constraint file gracefully |
| 161 | +
|
| 162 | +Validate file existence and emit helpful message instead of crashing. |
| 163 | +``` |
129 | 164 |
|
130 | | -```bash |
131 | | -hatch run mypy:check |
| 165 | +### AI Agent Attribution |
| 166 | + |
| 167 | +When AI agents create or significantly modify code, add attribution using `Co-Authored-By`: |
| 168 | + |
| 169 | +```text |
| 170 | +feat(resolver): add exponential backoff for HTTP retries |
| 171 | +
|
| 172 | +Improves resilience when PyPI is under load by adding jittered backoff. |
| 173 | +
|
| 174 | +Co-Authored-By: Claude <claude@anthropic.com> |
| 175 | +Closes: #123 |
132 | 176 | ``` |
133 | 177 |
|
134 | | -### Before Committing |
| 178 | +### Bad Examples (NEVER DO THIS) |
| 179 | + |
| 180 | +- `fix bug` (too vague) |
| 181 | +- `updated files` (not descriptive) |
| 182 | +- `WIP` (not informative) |
| 183 | +- `fixed the thing that was broken` (not professional) |
| 184 | + |
| 185 | +## Workflow for Complex Tasks |
| 186 | + |
| 187 | +1. **Search codebase** for similar patterns first |
| 188 | +2. **Create a checklist** in a markdown file for tracking |
| 189 | +3. **Work through items systematically** one at a time |
| 190 | +4. **Run file-scoped tests** after each change |
| 191 | +5. **Check off completed items** before moving to next |
| 192 | +6. **Run full quality checks** only at the end |
| 193 | + |
| 194 | +## When Uncertain |
| 195 | + |
| 196 | +- Ask clarifying questions rather than making assumptions |
| 197 | +- Search the codebase for similar patterns before inventing new ones |
| 198 | +- Propose a specific plan before making large changes |
| 199 | +- Reference [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidance |
| 200 | +- **DO NOT** make large speculative changes without confirmation |
| 201 | + |
| 202 | +## Quality Checklist Before Finishing |
| 203 | + |
| 204 | +- [ ] Read CONTRIBUTING.md for relevant standards |
| 205 | +- [ ] Type annotations on all functions |
| 206 | +- [ ] Docstrings on public APIs |
| 207 | +- [ ] Tests cover the change |
| 208 | +- [ ] File-scoped tests pass |
| 209 | +- [ ] No trailing whitespace |
| 210 | +- [ ] File ends with single newline |
| 211 | +- [ ] Conventional Commit format used |
| 212 | +- [ ] Full quality checks pass: `hatch run lint:fix && hatch run test:test && hatch run mypy:check && hatch run lint:check` |
| 213 | + |
| 214 | +--- |
135 | 215 |
|
136 | | -- Review your changes for trailing whitespace: `git diff | grep -E "^\+.*[[:space:]]$"` |
137 | | -- Run tests to ensure all changes work correctly |
138 | | -- Check for linting errors if the project uses linters |
| 216 | +**See [CONTRIBUTING.md](CONTRIBUTING.md) for comprehensive standards, detailed examples, and design patterns used in Fromager.** |
0 commit comments