📃 docs: 部分完成
This commit is contained in:
698
aide-program/docs/05-配置文件规范.md
Normal file
698
aide-program/docs/05-配置文件规范.md
Normal file
@@ -0,0 +1,698 @@
|
||||
# 配置文件规范
|
||||
|
||||
## 一、概述
|
||||
|
||||
### 1.1 配置文件定位
|
||||
|
||||
- **文件路径**:`.aide/config.toml`
|
||||
- **格式**:TOML(Tom's Obvious, Minimal Language)
|
||||
- **特点**:自文档化,包含详细注释
|
||||
- **创建时机**:`aide init` 命令执行时
|
||||
|
||||
### 1.2 设计原则
|
||||
|
||||
1. **自文档化**:每个配置项都有注释说明
|
||||
2. **合理默认值**:开箱即用,无需修改
|
||||
3. **类型安全**:明确的数据类型
|
||||
4. **向后兼容**:新版本保持旧配置可用
|
||||
|
||||
---
|
||||
|
||||
## 二、配置文件结构
|
||||
|
||||
### 2.1 完整示例
|
||||
|
||||
```toml
|
||||
# Aide 项目配置文件
|
||||
# 由 aide init 自动生成
|
||||
# 版本: 1.0
|
||||
|
||||
[task]
|
||||
# 任务原文档路径(prep 阶段使用)
|
||||
source = "task-now.md"
|
||||
|
||||
# 任务细则文档路径(exec 阶段使用)
|
||||
spec = "task-spec.md"
|
||||
|
||||
[env]
|
||||
# 环境配置
|
||||
|
||||
[env.python]
|
||||
# Python 版本要求(语义化版本)
|
||||
version = ">=3.10"
|
||||
|
||||
# 虚拟环境路径(相对于项目根目录)
|
||||
venv = ".venv"
|
||||
|
||||
[env.tools]
|
||||
# 可选工具配置
|
||||
|
||||
# 是否需要 uv(Python 包管理器)
|
||||
uv = false
|
||||
|
||||
# 是否需要 git
|
||||
git = true
|
||||
|
||||
[flow]
|
||||
# 流程追踪配置(后续实现)
|
||||
|
||||
# 环节列表
|
||||
phases = ["flow-design", "impl", "verify", "docs", "finish"]
|
||||
|
||||
# PlantUML 流程图目录
|
||||
flowchart_dir = "program_flowchart"
|
||||
|
||||
[decide]
|
||||
# 待定项确认配置(后续实现)
|
||||
|
||||
# Web 服务端口
|
||||
port = 3721
|
||||
|
||||
# 决策记录保存目录
|
||||
decisions_dir = ".aide/decisions"
|
||||
|
||||
[output]
|
||||
# 输出配置
|
||||
|
||||
# 是否启用颜色输出
|
||||
color = true
|
||||
|
||||
# 输出语言(当前仅支持 zh-CN)
|
||||
language = "zh-CN"
|
||||
```
|
||||
|
||||
### 2.2 配置项说明
|
||||
|
||||
#### 2.2.1 [task] 任务配置
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| `source` | string | `"task-now.md"` | 任务原文档路径 |
|
||||
| `spec` | string | `"task-spec.md"` | 任务细则文档路径 |
|
||||
|
||||
**使用场景**:
|
||||
- `prep` 命令未传入参数时,使用 `task.source`
|
||||
- `exec` 命令未传入参数时,使用 `task.spec`
|
||||
|
||||
#### 2.2.2 [env.python] Python 环境配置
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| `version` | string | `">=3.10"` | Python 版本要求 |
|
||||
| `venv` | string | `".venv"` | 虚拟环境路径 |
|
||||
|
||||
**版本格式**:
|
||||
- `">=3.10"` - 大于等于 3.10
|
||||
- `">=3.10,<4.0"` - 3.10 到 4.0 之间
|
||||
- `"3.12"` - 精确匹配 3.12
|
||||
|
||||
#### 2.2.3 [env.tools] 工具配置
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| `uv` | boolean | `false` | 是否需要 uv |
|
||||
| `git` | boolean | `true` | 是否需要 git |
|
||||
|
||||
#### 2.2.4 [flow] 流程配置(后续实现)
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| `phases` | array | `["flow-design", "impl", "verify", "docs", "finish"]` | 环节列表 |
|
||||
| `flowchart_dir` | string | `"program_flowchart"` | 流程图目录 |
|
||||
|
||||
#### 2.2.5 [decide] 待定项配置(后续实现)
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| `port` | integer | `3721` | Web 服务端口 |
|
||||
| `decisions_dir` | string | `".aide/decisions"` | 决策记录目录 |
|
||||
|
||||
#### 2.2.6 [output] 输出配置
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| `color` | boolean | `true` | 是否启用颜色 |
|
||||
| `language` | string | `"zh-CN"` | 输出语言 |
|
||||
|
||||
---
|
||||
|
||||
## 三、配置文件操作
|
||||
|
||||
### 3.1 读取配置
|
||||
|
||||
**Python 实现示例**:
|
||||
|
||||
```python
|
||||
import tomllib # Python 3.11+
|
||||
# 或
|
||||
import tomli # Python 3.10
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
def load_config(project_root: Path) -> dict:
|
||||
"""加载配置文件
|
||||
|
||||
Args:
|
||||
project_root: 项目根目录
|
||||
|
||||
Returns:
|
||||
配置字典
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: 配置文件不存在
|
||||
tomllib.TOMLDecodeError: 配置文件格式错误
|
||||
"""
|
||||
config_path = project_root / ".aide" / "config.toml"
|
||||
|
||||
if not config_path.exists():
|
||||
raise FileNotFoundError(f"配置文件不存在: {config_path}")
|
||||
|
||||
with open(config_path, "rb") as f:
|
||||
return tomllib.load(f)
|
||||
|
||||
def get_config_value(config: dict, key: str, default=None):
|
||||
"""获取配置值(支持点号分隔的键)
|
||||
|
||||
Args:
|
||||
config: 配置字典
|
||||
key: 配置键(如 "task.source")
|
||||
default: 默认值
|
||||
|
||||
Returns:
|
||||
配置值
|
||||
|
||||
Example:
|
||||
>>> config = {"task": {"source": "task-now.md"}}
|
||||
>>> get_config_value(config, "task.source")
|
||||
'task-now.md'
|
||||
"""
|
||||
keys = key.split(".")
|
||||
value = config
|
||||
|
||||
for k in keys:
|
||||
if isinstance(value, dict) and k in value:
|
||||
value = value[k]
|
||||
else:
|
||||
return default
|
||||
|
||||
return value
|
||||
```
|
||||
|
||||
### 3.2 写入配置
|
||||
|
||||
**Python 实现示例**:
|
||||
|
||||
```python
|
||||
import tomli_w
|
||||
from pathlib import Path
|
||||
|
||||
def save_config(project_root: Path, config: dict) -> None:
|
||||
"""保存配置文件
|
||||
|
||||
Args:
|
||||
project_root: 项目根目录
|
||||
config: 配置字典
|
||||
"""
|
||||
config_path = project_root / ".aide" / "config.toml"
|
||||
|
||||
with open(config_path, "wb") as f:
|
||||
tomli_w.dump(config, f)
|
||||
|
||||
def set_config_value(config: dict, key: str, value) -> dict:
|
||||
"""设置配置值(支持点号分隔的键)
|
||||
|
||||
Args:
|
||||
config: 配置字典
|
||||
key: 配置键(如 "task.source")
|
||||
value: 配置值
|
||||
|
||||
Returns:
|
||||
更新后的配置字典
|
||||
|
||||
Example:
|
||||
>>> config = {"task": {"source": "task-now.md"}}
|
||||
>>> set_config_value(config, "task.source", "new-task.md")
|
||||
{'task': {'source': 'new-task.md'}}
|
||||
"""
|
||||
keys = key.split(".")
|
||||
current = config
|
||||
|
||||
# 导航到倒数第二层
|
||||
for k in keys[:-1]:
|
||||
if k not in current:
|
||||
current[k] = {}
|
||||
current = current[k]
|
||||
|
||||
# 设置最后一层的值
|
||||
current[keys[-1]] = value
|
||||
|
||||
return config
|
||||
```
|
||||
|
||||
### 3.3 验证配置
|
||||
|
||||
**验证规则**:
|
||||
|
||||
```python
|
||||
from typing import Any
|
||||
|
||||
def validate_config(config: dict) -> list[str]:
|
||||
"""验证配置文件
|
||||
|
||||
Args:
|
||||
config: 配置字典
|
||||
|
||||
Returns:
|
||||
错误列表(空列表表示无错误)
|
||||
"""
|
||||
errors = []
|
||||
|
||||
# 验证必需的顶层键
|
||||
required_sections = ["task", "env", "output"]
|
||||
for section in required_sections:
|
||||
if section not in config:
|
||||
errors.append(f"缺少必需的配置节: [{section}]")
|
||||
|
||||
# 验证 task 配置
|
||||
if "task" in config:
|
||||
if "source" not in config["task"]:
|
||||
errors.append("缺少配置项: task.source")
|
||||
if "spec" not in config["task"]:
|
||||
errors.append("缺少配置项: task.spec")
|
||||
|
||||
# 验证 env.python 配置
|
||||
if "env" in config and "python" in config["env"]:
|
||||
python_config = config["env"]["python"]
|
||||
if "version" not in python_config:
|
||||
errors.append("缺少配置项: env.python.version")
|
||||
else:
|
||||
# 验证版本格式
|
||||
version = python_config["version"]
|
||||
if not is_valid_version_spec(version):
|
||||
errors.append(f"无效的版本格式: {version}")
|
||||
|
||||
# 验证 output 配置
|
||||
if "output" in config:
|
||||
output_config = config["output"]
|
||||
if "language" in output_config:
|
||||
lang = output_config["language"]
|
||||
if lang not in ["zh-CN", "en-US"]:
|
||||
errors.append(f"不支持的语言: {lang}")
|
||||
|
||||
return errors
|
||||
|
||||
def is_valid_version_spec(spec: str) -> bool:
|
||||
"""验证版本规格字符串
|
||||
|
||||
Args:
|
||||
spec: 版本规格(如 ">=3.10")
|
||||
|
||||
Returns:
|
||||
是否有效
|
||||
"""
|
||||
import re
|
||||
# 简化的版本规格验证
|
||||
pattern = r'^(>=|<=|>|<|==)?\d+\.\d+(\.\d+)?$'
|
||||
return bool(re.match(pattern, spec))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、默认配置生成
|
||||
|
||||
### 4.1 生成逻辑
|
||||
|
||||
`aide init` 命令应该生成包含注释的默认配置:
|
||||
|
||||
```python
|
||||
def generate_default_config() -> str:
|
||||
"""生成默认配置文件内容(带注释)
|
||||
|
||||
Returns:
|
||||
TOML 格式的配置文件内容
|
||||
"""
|
||||
return '''# Aide 项目配置文件
|
||||
# 由 aide init 自动生成
|
||||
# 文档: https://github.com/your-org/aide
|
||||
|
||||
[task]
|
||||
# 任务原文档路径(prep 阶段使用)
|
||||
# 可通过 /aide:prep [路径] 覆盖
|
||||
source = "task-now.md"
|
||||
|
||||
# 任务细则文档路径(exec 阶段使用)
|
||||
# 可通过 /aide:exec [路径] 覆盖
|
||||
spec = "task-spec.md"
|
||||
|
||||
[env]
|
||||
# 环境配置
|
||||
|
||||
[env.python]
|
||||
# Python 版本要求(语义化版本)
|
||||
# 格式: ">=3.10" 或 ">=3.10,<4.0"
|
||||
version = ">=3.10"
|
||||
|
||||
# 虚拟环境路径(相对于项目根目录)
|
||||
venv = ".venv"
|
||||
|
||||
[env.tools]
|
||||
# 可选工具配置
|
||||
|
||||
# 是否需要 uv(Python 包管理器)
|
||||
uv = false
|
||||
|
||||
# 是否需要 git
|
||||
git = true
|
||||
|
||||
[flow]
|
||||
# 流程追踪配置(aide flow 命令使用)
|
||||
|
||||
# 环节列表(不建议修改)
|
||||
phases = ["flow-design", "impl", "verify", "docs", "finish"]
|
||||
|
||||
# PlantUML 流程图目录
|
||||
flowchart_dir = "program_flowchart"
|
||||
|
||||
[decide]
|
||||
# 待定项确认配置(aide decide 命令使用)
|
||||
|
||||
# Web 服务端口
|
||||
port = 3721
|
||||
|
||||
# 决策记录保存目录
|
||||
decisions_dir = ".aide/decisions"
|
||||
|
||||
[output]
|
||||
# 输出配置
|
||||
|
||||
# 是否启用颜色输出
|
||||
# 可通过环境变量 NO_COLOR 禁用
|
||||
color = true
|
||||
|
||||
# 输出语言(当前仅支持 zh-CN)
|
||||
language = "zh-CN"
|
||||
'''
|
||||
```
|
||||
|
||||
### 4.2 配置文件创建流程
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
|
||||
def create_config_file(project_root: Path) -> bool:
|
||||
"""创建配置文件
|
||||
|
||||
Args:
|
||||
project_root: 项目根目录
|
||||
|
||||
Returns:
|
||||
是否创建成功(False 表示文件已存在)
|
||||
"""
|
||||
aide_dir = project_root / ".aide"
|
||||
config_path = aide_dir / "config.toml"
|
||||
|
||||
# 检查是否已存在
|
||||
if config_path.exists():
|
||||
return False
|
||||
|
||||
# 确保 .aide 目录存在
|
||||
aide_dir.mkdir(exist_ok=True)
|
||||
|
||||
# 写入默认配置
|
||||
config_content = generate_default_config()
|
||||
config_path.write_text(config_content, encoding="utf-8")
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、配置访问接口
|
||||
|
||||
### 5.1 Config 类设计
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
class Config:
|
||||
"""配置管理类"""
|
||||
|
||||
def __init__(self, project_root: Path):
|
||||
"""初始化配置
|
||||
|
||||
Args:
|
||||
project_root: 项目根目录
|
||||
"""
|
||||
self.project_root = project_root
|
||||
self.config_path = project_root / ".aide" / "config.toml"
|
||||
self._config: Optional[dict] = None
|
||||
|
||||
def load(self) -> None:
|
||||
"""加载配置文件"""
|
||||
if not self.config_path.exists():
|
||||
raise FileNotFoundError(f"配置文件不存在: {self.config_path}")
|
||||
|
||||
with open(self.config_path, "rb") as f:
|
||||
self._config = tomllib.load(f)
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""获取配置值
|
||||
|
||||
Args:
|
||||
key: 配置键(支持点号分隔)
|
||||
default: 默认值
|
||||
|
||||
Returns:
|
||||
配置值
|
||||
"""
|
||||
if self._config is None:
|
||||
self.load()
|
||||
|
||||
return get_config_value(self._config, key, default)
|
||||
|
||||
def set(self, key: str, value: Any) -> None:
|
||||
"""设置配置值
|
||||
|
||||
Args:
|
||||
key: 配置键(支持点号分隔)
|
||||
value: 配置值
|
||||
"""
|
||||
if self._config is None:
|
||||
self.load()
|
||||
|
||||
set_config_value(self._config, key, value)
|
||||
self.save()
|
||||
|
||||
def save(self) -> None:
|
||||
"""保存配置文件"""
|
||||
if self._config is None:
|
||||
return
|
||||
|
||||
with open(self.config_path, "wb") as f:
|
||||
tomli_w.dump(self._config, f)
|
||||
|
||||
def validate(self) -> list[str]:
|
||||
"""验证配置
|
||||
|
||||
Returns:
|
||||
错误列表
|
||||
"""
|
||||
if self._config is None:
|
||||
self.load()
|
||||
|
||||
return validate_config(self._config)
|
||||
```
|
||||
|
||||
### 5.2 使用示例
|
||||
|
||||
```python
|
||||
# 初始化配置
|
||||
config = Config(Path.cwd())
|
||||
|
||||
# 获取配置值
|
||||
task_source = config.get("task.source", "task-now.md")
|
||||
python_version = config.get("env.python.version", ">=3.10")
|
||||
|
||||
# 设置配置值
|
||||
config.set("task.source", "new-task.md")
|
||||
config.set("env.python.version", ">=3.11")
|
||||
|
||||
# 验证配置
|
||||
errors = config.validate()
|
||||
if errors:
|
||||
for error in errors:
|
||||
print(f"✗ 配置错误: {error}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、配置迁移
|
||||
|
||||
### 6.1 版本兼容性
|
||||
|
||||
当配置文件格式升级时,需要提供迁移机制:
|
||||
|
||||
```python
|
||||
def migrate_config(config: dict, from_version: str, to_version: str) -> dict:
|
||||
"""迁移配置文件
|
||||
|
||||
Args:
|
||||
config: 旧配置
|
||||
from_version: 源版本
|
||||
to_version: 目标版本
|
||||
|
||||
Returns:
|
||||
新配置
|
||||
"""
|
||||
if from_version == "1.0" and to_version == "1.1":
|
||||
# 示例:添加新的配置项
|
||||
if "output" not in config:
|
||||
config["output"] = {
|
||||
"color": True,
|
||||
"language": "zh-CN"
|
||||
}
|
||||
|
||||
return config
|
||||
```
|
||||
|
||||
### 6.2 配置备份
|
||||
|
||||
修改配置前应该备份:
|
||||
|
||||
```python
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
|
||||
def backup_config(config_path: Path) -> Path:
|
||||
"""备份配置文件
|
||||
|
||||
Args:
|
||||
config_path: 配置文件路径
|
||||
|
||||
Returns:
|
||||
备份文件路径
|
||||
"""
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
backup_path = config_path.with_suffix(f".toml.backup.{timestamp}")
|
||||
shutil.copy2(config_path, backup_path)
|
||||
return backup_path
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、错误处理
|
||||
|
||||
### 7.1 常见错误
|
||||
|
||||
| 错误类型 | 处理方式 |
|
||||
|---------|---------|
|
||||
| 配置文件不存在 | 提示使用 `aide init` 创建 |
|
||||
| 配置文件格式错误 | 显示具体错误位置和原因 |
|
||||
| 配置项缺失 | 使用默认值并警告 |
|
||||
| 配置值类型错误 | 显示期望类型和实际类型 |
|
||||
|
||||
### 7.2 错误信息示例
|
||||
|
||||
```python
|
||||
def handle_config_error(error: Exception, config_path: Path) -> None:
|
||||
"""处理配置错误
|
||||
|
||||
Args:
|
||||
error: 异常对象
|
||||
config_path: 配置文件路径
|
||||
"""
|
||||
if isinstance(error, FileNotFoundError):
|
||||
err(
|
||||
"配置文件不存在",
|
||||
[
|
||||
f"位置: {config_path}",
|
||||
"建议: 运行 'aide init' 创建配置文件"
|
||||
]
|
||||
)
|
||||
elif isinstance(error, tomllib.TOMLDecodeError):
|
||||
err(
|
||||
f"配置文件格式错误 (第{error.lineno}行)",
|
||||
[
|
||||
f"位置: {config_path}:{error.lineno}",
|
||||
f"原因: {error.msg}",
|
||||
"建议: 检查 TOML 语法,确保格式正确"
|
||||
]
|
||||
)
|
||||
else:
|
||||
err(
|
||||
"配置文件读取失败",
|
||||
[
|
||||
f"位置: {config_path}",
|
||||
f"原因: {str(error)}"
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、测试要求
|
||||
|
||||
### 8.1 测试用例
|
||||
|
||||
```python
|
||||
def test_load_config():
|
||||
"""测试加载配置"""
|
||||
# 创建测试配置
|
||||
# 加载配置
|
||||
# 验证配置内容
|
||||
|
||||
def test_get_config_value():
|
||||
"""测试获取配置值"""
|
||||
# 测试简单键
|
||||
# 测试嵌套键
|
||||
# 测试不存在的键
|
||||
# 测试默认值
|
||||
|
||||
def test_set_config_value():
|
||||
"""测试设置配置值"""
|
||||
# 测试设置简单键
|
||||
# 测试设置嵌套键
|
||||
# 测试创建新键
|
||||
|
||||
def test_validate_config():
|
||||
"""测试配置验证"""
|
||||
# 测试有效配置
|
||||
# 测试缺少必需项
|
||||
# 测试无效值类型
|
||||
# 测试无效版本格式
|
||||
|
||||
def test_config_migration():
|
||||
"""测试配置迁移"""
|
||||
# 测试版本升级
|
||||
# 测试向后兼容
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、总结
|
||||
|
||||
### 9.1 核心要点
|
||||
|
||||
1. 使用 TOML 格式,自文档化
|
||||
2. 提供合理的默认值
|
||||
3. 支持点号分隔的键访问
|
||||
4. 完善的错误处理和验证
|
||||
5. 配置迁移和备份机制
|
||||
|
||||
### 9.2 实现检查清单
|
||||
|
||||
- [ ] 实现配置文件读取(load_config)
|
||||
- [ ] 实现配置文件写入(save_config)
|
||||
- [ ] 实现配置值获取(get_config_value)
|
||||
- [ ] 实现配置值设置(set_config_value)
|
||||
- [ ] 实现配置验证(validate_config)
|
||||
- [ ] 实现默认配置生成(generate_default_config)
|
||||
- [ ] 实现 Config 类
|
||||
- [ ] 编写配置测试用例
|
||||
- [ ] 验证 TOML 格式正确性
|
||||
|
||||
---
|
||||
|
||||
**版本**:v1.0
|
||||
**更新日期**:2025-12-13
|
||||
Reference in New Issue
Block a user