# AGENTS.md — dotpromptz 代码仓库指南

> 本文件供 AI 编程代理在本仓库中工作时参考。

## 项目概览

`dotpromptz-py` 是一个 Python 库，用于解析和渲染 `.prompt` 格式的模板文件（基于 Jinja2 语法）。
源码位于 `src/dotpromptz/`，使用 `uv` 作为包管理器。
要求 Python >= 3.12。

## 总体要求

1. 请在最终使用中文总结改动的内容和结果
2. 可能存在多个agent同时工作的情况，当你发现代码被其他人修改，请不要管。只专注于你在做的事情和你修改的代码
3. 当你发现一些潜在的错误或者风险时，请在test中加入对应的测试。
4. 但你测试完之后如果发现问题，除非明显是你之前的错误引进的，否则不要直接修正。而是总结并询问
5. 文件命名采用单单词命名，不要下划线或者驼峰

## 构建与依赖

```bash
# 安装所有依赖（包括开发依赖）
uv sync

# 构建包
uv build
```

## 测试命令

```bash
# 运行所有测试
uv run pytest -xvvs --log-level=DEBUG .

# 运行单个测试文件
uv run pytest -xvvs tests/unit/dotprompt_test.py

# 运行单个测试类
uv run pytest -xvvs tests/unit/dotprompt_test.py::TestClassName

# 运行单个测试方法
uv run pytest -xvvs tests/unit/dotprompt_test.py::TestClassName::test_method_name

# 仅运行集成测试
uv run pytest -xvvs -m integration tests/integration/

# 运行除集成测试外的所有测试
uv run pytest -xvvs -m "not integration" .
```

### 测试约定

- 测试文件命名：统一使用 `*_test.py` 后缀（pyproject.toml 中配置 `python_files = ["**/*_test.py"]`）
- 测试目录结构：`tests/unit/`、`tests/integration/`、`tests/smoke/`、`tests/spec/`
- 使用 `pytest-asyncio`（strict 模式，function-scoped event loop）
- 集成测试用 `@pytest.mark.integration` 标记

## 代码格式化与 Lint

```bash
# 检查格式
uv run ruff format --check --preview .

# 自动格式化
uv run ruff format --preview .

# Lint 检查
uv run ruff check --select I .

# Lint 自动修复
uv run ruff check --fix .
```

### Ruff 配置摘要

| 配置项         | 值                                           |
| -------------- | -------------------------------------------- |
| 行长度         | 120                                          |
| 缩进           | 4 空格                                       |
| 目标版本       | py312                                        |
| 引号风格       | 单引号                                       |
| 行尾           | LF                                           |
| Docstring 格式 | Google 风格                                  |
| Lint 规则      | E, W, F, I (isort), UP, B, N, D (pydocstyle) |

- 测试文件豁免 docstring 规则（D）
- isort: `dotpromptz` 为 known-first-party，启用 `combine-as-imports`

## 代码风格指南

### 导入顺序

按以下顺序排列，组间空行分隔：

1. 标准库（`import os`、`from pathlib import Path`）
2. 第三方库（`import yaml`、`from pydantic import ...`）
3. 本地模块（`from dotpromptz.typing import ...`）

### 类型标注

- **所有** 函数/方法必须有完整的类型标注（参数 + 返回值）
- 使用现代 Python 语法：`str | None`（不用 `Optional[str]`），`dict[str, Any]`（不用 `Dict`）
- 支持 PEP 695 泛型语法：`def func[T](obj: T) -> T:`
- 链式方法使用 `Self` 作为返回类型

### 命名规范

| 类别            | 风格             | 示例                                    |
| --------------- | ---------------- | --------------------------------------- |
| 类              | PascalCase       | `DotPrompt`、`PromptMetadata`       |
| 函数 / 方法     | snake_case       | `render_messages`、`parse_document` |
| 私有函数 / 方法 | `_` 前缀       | `_remove_undefined_fields`            |
| 常量            | UPPER_SNAKE_CASE | `FRONT_MATTER_REGEX`、`VALID_ROLES` |
| 模块级编译正则  | UPPER_SNAKE_CASE | `SCALAR_TYPE_REGEX`                   |

### Docstring 风格

使用 Google 风格 docstring，包含 Args / Returns / Raises 等节：

```python
def parse_document(source: str) -> ParsedDocument:
    """解析 .prompt 文件的完整内容。

    Args:
        source: 原始 .prompt 文件内容。

    Returns:
        包含前置元数据和模板内容的 ParsedDocument 对象。

    Raises:
        ValueError: 当前置元数据格式无效时。
    """
```

模块级 docstring 可包含 Markdown 表格。

### 数据模型

- 使用 Pydantic V2：`ConfigDict`、`Field`、`model_validator`
- 不可变常量集合使用 `frozenset`

### 日志

- 使用标准库 `logging`，并优先通过 `dotpromptz.logging.get_logger()` 获取结构化 logger

### 错误处理

- 自定义异常类继承自 Python 内置异常（如 `ValueError`、`TypeError`）
- 不要使用空 `except` 或空 `catch` 块
- 不要使用 `# type: ignore`、`@ts-ignore` 等类型抑制注释

### 其他注意事项

- `Any` 在 schema/config 相关类型中可适当使用
- 测试中混合使用 `unittest.TestCase` 类和 pytest 风格的类/函数
- 模块级编译的正则表达式放在文件顶部常量区域
