-
Notifications
You must be signed in to change notification settings - Fork 1
Copier update: more AGENTS.md #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,13 +1,22 @@ | ||||||
| # Project Structure | ||||||
|
|
||||||
| This project is a Python library. | ||||||
|
|
||||||
| # Code Guidelines | ||||||
|
|
||||||
| ## Code Style | ||||||
|
|
||||||
| - Comments should be used very rarely. Code should generally express its intent. | ||||||
| - Never write a one-line docstring — either the name is sufficient or the behavior warrants a full explanation. | ||||||
| - Don't sort or remove imports manually — pre-commit handles it. | ||||||
| - Always include type hints for pyright in Python | ||||||
| - Respect the pyright rule reportUnusedCallResult; assign unneeded return values to `_` | ||||||
| - Prefer keyword-only parameters (unless a very clear single-argument function): use `*` in Python signatures and destructured options objects in TypeScript. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tighten wording by removing the weak intensifier. Consider replacing “a very clear single-argument function” with “a clear single-argument function” for more direct style. ✏️ Suggested edit-- Prefer keyword-only parameters (unless a very clear single-argument function): use `*` in Python signatures and destructured options objects in TypeScript.
+- Prefer keyword-only parameters (unless a clear single-argument function): use `*` in Python signatures and destructured options objects in TypeScript.📝 Committable suggestion
Suggested change
🧰 Tools🪛 LanguageTool[style] ~14-~14: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase. (EN_WEAK_ADJECTIVE) 🤖 Prompt for AI Agents |
||||||
| - When disabling a linting rule with an inline directive, provide a comment at the end of the line (or on the line above for tools that don't allow extra text after an inline directive) describing the reasoning for disabling the rule. | ||||||
| - Avoid telling the type checker what a type is rather than letting it prove it. This includes type assertions (`as SomeType` in TypeScript, `cast()` in Python) and variable annotations that override inference. Prefer approaches that let the type checker verify the type itself: `isinstance`/`instanceof` narrowing, restructuring code so the correct type flows naturally, or using discriminated unions. When there is genuinely no alternative, add a comment explaining why the workaround is necessary and why it is safe. | ||||||
|
|
||||||
| ## Testing | ||||||
|
|
||||||
| - Always run tests with an explicit path (e.g. uv run pytest tests/unit) — test runners discover all types by default. | ||||||
| - Test coverage requirements are usually at 100%, so when running a subset of tests, always disable test coverage to avoid the test run failing for insufficient coverage. | ||||||
| - Avoid magic values in comparisons in tests in all languages (like ruff rule PLR2004 specifies) | ||||||
|
|
@@ -16,22 +25,33 @@ | |||||
| - Key `data-testid` selectors off unique IDs (e.g. UUIDs), not human-readable names which may collide or change. | ||||||
|
|
||||||
| ### Python Testing | ||||||
|
|
||||||
| - When using `mocker.spy` on a class-level method (including inherited ones), the spy records the unbound call, so assertions need `ANY` as the first argument to match self: `spy.assert_called_once_with(ANY, expected_arg)` | ||||||
| - Before writing new mock/spy helpers, check the `tests/unit/` folder for pre-built helpers in files like `fixtures.py` or `*mocks.py` | ||||||
| - When a test needs a fixture only for its side effects (not its return value), use `@pytest.mark.usefixtures(fixture_name.__name__)` instead of adding an unused parameter with a noqa comment | ||||||
| - Use `__name__` instead of string literals when referencing functions/methods (e.g., `mocker.patch.object(MyClass, MyClass.method.__name__)`, `pytest.mark.usefixtures(my_fixture.__name__)`). This enables IDE refactoring tools to catch renames. | ||||||
| - When using the faker library, prefer the pytest fixture (provided by the faker library) over instantiating instances of Faker. | ||||||
| - **Never hand-write VCR cassette YAML files.** Cassettes must be recorded from real HTTP interactions by running the test once with `--record-mode=once` against a live external service: `uv run pytest --record-mode=once <test path> --no-cov`. The default mode is `none` — a missing cassette will cause an error, which is expected until recorded. | ||||||
| - **Never hand-edit syrupy snapshot files.** Snapshots are auto-generated — to create or update them, run `uv run pytest --snapshot-update <test path> --no-cov`. A missing snapshot causes the test to fail, which is expected until you run with `--snapshot-update`. When a snapshot mismatch occurs, fix the code if the change was unintentional; run `--snapshot-update` if it was intentional. | ||||||
| - **Never hand-write or hand-edit pytest-reserial `.jsonl` recording files.** Recordings must be captured from real serial port traffic by running the test with `--record` while the device is connected: `uv run pytest --record <test path> --no-cov`. The default mode replays recordings — a missing recording causes an error, which is expected until recorded against a live device. | ||||||
|
|
||||||
| # Agent Implementations & Configurations | ||||||
|
|
||||||
| ## Memory and Rules | ||||||
|
|
||||||
| - Before saving any memory or adding any rule, explicitly ask the user whether the concept should be: (1) added to AGENTS.md as a general rule applicable across all projects, (2) added to AGENTS.md as a rule specific to this project, or (3) stored as a temporary local memory only relevant to the current active work. The devcontainer environment is ephemeral, so local memory files are rarely the right choice. | ||||||
|
|
||||||
| ## Tooling | ||||||
|
|
||||||
| - Always use `uv run python` instead of `python3` or `python` when running Python commands. | ||||||
| - Prefer dedicated shell tools over `python3`/`python` for simple one-off tasks: use `jq` for JSON parsing, standard shell builtins for string manipulation, etc. Only reach for `python3` when no simpler tool covers the need. | ||||||
| - Check .devcontainer/devcontainer.json for tooling versions (Python, Node, etc.) when reasoning about version-specific stdlib or tooling behavior. | ||||||
| - For frontend work, run commands via `pnpm` scripts from `frontend/package.json` — never invoke tools directly (not pnpm exec <tool>, npx <tool>, etc.). ✅ pnpm test-unit ❌ pnpm vitest ... or npx vitest ... | ||||||
| - For frontend tests, run commands via `pnpm` scripts from `frontend/package.json` — never invoke tools directly (not pnpm exec <tool>, npx <tool>, etc.). ✅ pnpm test-unit ❌ pnpm vitest ... or npx vitest ... | ||||||
| - For linting and type-checking, prefer `pre-commit run <hook-id>` over invoking tools directly — this matches the permission allow-list and mirrors what CI runs. Key hook IDs: `typescript-check`, `eslint`, `pyright`, `ruff`, `ruff-format`. | ||||||
| - Never rely on IDE diagnostics for ruff warnings — the IDE may not respect the project's ruff.toml config. Run `pre-commit run ruff -a` to get accurate results. | ||||||
| - When running terminal commands, execute exactly one command per tool call. Do not chain commands with &&, ||, ;, or & — this prohibition has no exceptions, even for `cd && ...` patterns. Use absolute paths instead of `cd` to avoid needing to chain. Pipes (|) are allowed for output transformation (e.g., head, tail, grep). If two sequential commands are needed, run them in separate tool calls. Chained commands break the permission allow-list matcher and cause unnecessary permission prompts | ||||||
| - Never use backslash line continuations in shell commands — always write the full command on a single line. Backslashes break the permission allow-list matcher. | ||||||
| - **Never manually edit files in any `generated/` folder.** These files are produced by codegen tooling (typically Kiota) and any manual changes will be overwritten. If a generated file needs to change, update the source (e.g. the OpenAPI schema) and re-run the generator. | ||||||
|
|
||||||
| <!-- BEGIN BEADS INTEGRATION --> | ||||||
| ## Issue Tracking with bd (beads) | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apply the same wording cleanup here for consistency.
Replace “a very clear single-argument function” with “a clear single-argument function.”
✏️ Suggested edit
📝 Committable suggestion
🧰 Tools
🪛 LanguageTool
[style] ~14-~14: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ... Prefer keyword-only parameters (unless a very clear single-argument function): use
*in P...(EN_WEAK_ADJECTIVE)
🤖 Prompt for AI Agents