# AGENTS

This file is the single source of truth for coding-agent guidance in this repo.
Follow these rules and patterns when making changes.

## Rules

### Using Numpy-Style Docstrings

Any new public methods and classes in this repository should follow the
Numpy-style docstring format. This ensures consistency and compatibility with
mkdocstrings for automated documentation generation.

Example:

```python
class Cas:
    """
    Represents a CAS entity.

    Attributes
    ----------
    number : str
        The CAS number.
    name : str, optional
        The name of the CAS.
    """

    def from_string(cls, *, number: str) -> "Cas":
        """
        Creates a Cas object from a string.

        Parameters
        ----------
        number : str
            The CAS number.

        Returns
        -------
        Cas
            The Cas object created from the string.
        """
        return cls(number=number)
```

When contributing new classes or methods, ensure all public members have
properly formatted Numpy-style docstrings.

## Design Principles

1. **Keep it simple** - Avoid over-engineering. Make minimal changes. Don't create massive file diffs or edit unnecessary files. Validate at boundaries, trust internal code based on type hints.

2. **Follow existing code patterns** - Check similar code in the codebase before writing new code. Match existing patterns rather than creating new ones.

3. **YAGNI** - Only edit files absolutely necessary for the task. Don't add extra configuration unless explicitly needed. Prefer sensible defaults over configurable complexity.

4. **Verify by running code** - When guessing about how something works, run the code and verify rather than assuming.

5. Verify you haven't over-engineered the solution

## Project Basics

- Python: >=3.10 (type hints use modern syntax like list[str]).
- Formatting and linting: Ruff (line length 99). CI and pre-commit enforce this.
- Commit style: Conventional Commits (type(scope): summary), enforced by hooks.

Useful commands:

```bash
./setup.sh
uv run ruff format .
uv run ruff check . --fix
uv run pytest
```

## Repo Layout

- src/albert/collections: API-facing collection classes that call endpoints.
- src/albert/resources: Pydantic models representing API resources.
- src/albert/core: Session, pagination, shared enums, and base classes.
- src/albert/utils: Reusable helper utilities used by collections/resources.
- docs/: mkdocs content (autogenerated from docstrings via mkdocstrings).
- tests/: pytest suites, fixtures, and seed helpers.

## API and Modeling Conventions

- Collections inherit from BaseCollection and accept an AlbertSession.
- Public collection methods should use @validate_call for runtime validation.
- Resources use BaseAlbertModel/BaseResource with Pydantic Fields and aliases.
- Keep API payloads in the wire format (camelCase) via Field(alias=...) and
  model_dump(by_alias=True, mode="json", exclude_none=True).
- Prefer narrow, explicit payload construction instead of dumping entire models.

## Pagination

Many list/search methods use AlbertPaginator (src/albert/core/pagination.py).
Two modes exist:

- Offset pagination (PaginationMode.OFFSET)
  - Uses the offset query parameter.
  - Defaults to limit=1000.
  - Continues until Items is empty.

- Key pagination (PaginationMode.KEY)
  - Uses startKey and expects lastKey in the response.
  - Page size defaults to backend behavior.

Guidelines:

- Expose a max_items parameter on public list/search methods where appropriate.
  It is used to stop iteration early regardless of mode.
- If a method returns an iterator, ensure the paginator is used consistently and
  that the last_key can be inspected for resuming.
- Use clear docstrings about offset/startKey behavior and max_items semantics.

## Testing

- Tests use pytest (see tests/).
- Integration-style tests require environment variables:
  - ALBERT_CLIENT_ID_SDK
  - ALBERT_CLIENT_SECRET_SDK
  - ALBERT_BASE_URL
- Only add integration-style tests. Do not add unit tests that use FakeAlbertSession.
- Seed helpers live in tests/seeding.py and are reused across fixtures.
- Test docstrings should be crisp, start with "Test ...", and avoid implementation details.

## Documentation

- Docs are built with mkdocs + mkdocstrings.
- When adding a new resource/collection, add a docs page in docs/ and link it in
  mkdocs.yml (alphabetical in nav).
- Prefer docstrings for API reference content and keep them Numpy-style.

## Release and Versioning

- Version is defined in src/albert/**init**.py and read dynamically by Hatch.
- Releases are created by tagging a version and drafting a GitHub release.

## Do/Don’t Summary

Do:

- Keep docstrings Numpy-style for public APIs.
- Use ruff for formatting/linting and respect line length 99.
- Follow existing collection/resource patterns and naming.
- Split diffs into meaningful commits, using Conventional Commits.
- When squashing multiple logical changes into one commit, add sub-commits as
  Conventional Commits in the footer so release-please can pick them up.

Don’t:

- Add new public APIs without docstrings and tests.
- Bypass Conventional Commits in commit messages.
- Introduce new dependencies without strong justification.

## Commit Guidance

- Prefer multiple meaningful commits over one large commit.
- Use Conventional Commits for each commit message.
- If multiple logical changes must be included in a single commit, add sub-commits
  as footers at the bottom of the commit message so release-please can parse them.

Example:

feat: adds v4 UUID to crypto

This adds support for v4 UUIDs to the library.

fix(utils): unicode no longer throws exception
  PiperOrigin-RevId: 345559154
  BREAKING-CHANGE: encode method no longer throws.
  Source-Link: googleapis/googleapis@5e0dcb2

feat(utils): update encode to support unicode
  PiperOrigin-RevId: 345559182
  Source-Link: googleapis/googleapis@e5eef86

The above commit message will contain:

- an entry for the "adds v4 UUID to crypto" feature.
- an entry for the fix "unicode no longer throws exception", along with a note that it's a breaking change.
- an entry for the feature "update encode to support unicode".

Important: Additional messages must be added to the bottom of the commit.

## General Guidelines

**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.

### 1. Think Before Coding

**Don't assume. Don't hide confusion. Surface tradeoffs.**

Before implementing:

- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.

### 2. Simplicity First

**Minimum code that solves the problem. Nothing speculative.**

- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

### 3. Surgical Changes

**Touch only what you must. Clean up only your own mess.**

When editing existing code:

- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:

- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.

The test: Every changed line should trace directly to the user's request.

### 4. Goal-Driven Execution

**Define success criteria. Loop until verified.**

Transform tasks into verifiable goals:

- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:

```
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
```
