bd40f4965b
Change depends_on from [01-02] to ["02"] for consistency with plan frontmatter format. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8.3 KiB
8.3 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, user_setup, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | user_setup | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-foundation | 01 | tdd | 2 |
|
|
true |
|
|
Purpose: 为工作流提供可靠的状态管理,支持断点续传和崩溃恢复 Output: kb_pipeline/state.py + 完整的单元测试
<execution_context> @/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md @/home/starmen1265/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.mdFrom kb_pipeline/schemas.py (created by 01-02):
from pydantic import BaseModel, Field
from typing import Optional, Dict, Literal
from datetime import datetime
from enum import Enum
class StepStatus(str, Enum):
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
SKIPPED = "skipped"
class StepRecord(BaseModel):
"""单个步骤的执行记录"""
step_name: str
status: StepStatus
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
error_message: Optional[str] = None
output_summary: Optional[str] = None
class WorkflowState(BaseModel):
"""工作流状态 - 存储在 workflow_state.json"""
schema_version: str = Field(default="1.0")
content_id: str = Field(..., description="内容唯一标识")
platform: str = Field(..., description="平台名称")
source_url: str = Field(..., description="原始链接")
created_at: datetime = Field(default_factory=datetime.now)
updated_at: datetime = Field(default_factory=datetime.now)
steps: Dict[str, StepRecord] = Field(default_factory=dict)
Reference implementation from gsd-openclaw:
- Atomic write pattern: write-to-temp + os.replace
- Backup rotation: state.json -> state.json.bak
- Load fallback: main file corrupted -> try backup
参考 gsd-openclaw/tests/test_state_manager.py 的测试模式。
pytest tests/test_pipeline/test_state.py -v --collect-only 2>/dev/null | grep "test_" | wc -l | xargs -I {} test {} -ge 10
测试文件包含至少 10 个测试用例,所有测试当前失败(RED 阶段)
Task 2: Implement WorkflowStateManager
kb_pipeline/state.py
- WorkflowStateManager.__init__ 正确设置 content_dir 和 state_path
- WorkflowStateManager.load() 返回 WorkflowState 或 None
- WorkflowStateManager.save() 使用原子写入模式
- WorkflowStateManager.get_or_create() 幂等创建状态
实现 kb_pipeline/state.py:
1. 导入必要的模块 (json, os, tempfile, Path)
2. 从 kb_pipeline.schemas 导入 WorkflowState
3. 实现 WorkflowStateManager 类:
- STATE_FILENAME = "workflow_state.json"
- load(): 尝试加载主文件,失败时尝试 .bak 文件
- save(state): 原子写入 - 创建父目录 -> 轮转备份 -> 写临时文件 -> os.replace
- get_or_create(content_id, platform, source_url): 加载现有或创建新状态
原子写入模式 (参考 gsd-openclaw):
```python
fd, temp_path = tempfile.mkstemp(dir=self.content_dir, suffix='.tmp')
try:
with os.fdopen(fd, 'w', encoding='utf-8') as f:
f.write(state.model_dump_json(indent=2))
os.replace(temp_path, self.state_path)
except Exception:
if os.path.exists(temp_path):
os.unlink(temp_path)
raise
```
pytest tests/test_pipeline/test_state.py -v --tb=short
所有测试通过(GREEN 阶段)
Task 3: Refactor and verify integration
kb_pipeline/state.py, tests/test_pipeline/test_state.py
- 代码结构清晰,无重复
- 测试覆盖所有边界情况
- 与 schemas.py 正确集成
1. 检查代码质量: 移除重复代码,添加必要的类型注解
2. 添加文档字符串(如果缺失)
3. 确保与 kb_pipeline/schemas.py 的 WorkflowState 正确集成
4. 运行完整测试套件验证
pytest tests/test_pipeline/test_state.py -v --tb=short -x
测试通过,代码结构清晰,与 schemas 模块正确集成
1. 运行 `pytest tests/test_pipeline/test_state.py -v` 全部通过
2. 验证原子写入: 创建状态文件后,确认存在 workflow_state.json
3. 验证备份轮转: 保存两次后,确认存在 .bak 文件
4. 验证幂等检查: is_step_completed 对已完成步骤返回 True
<success_criteria>
- WorkflowStateManager 可以原子方式保存和加载状态
- 状态文件损坏时可从备份恢复
- is_step_completed 支持幂等执行检查
- 所有测试通过,覆盖率 > 80% </success_criteria>