--- phase: 01-foundation plan: 01 type: tdd wave: 2 depends_on: ["02"] files_modified: [kb_pipeline/state.py, tests/test_pipeline/test_state.py] autonomous: true requirements: [PIPE-02, REL-01, REL-03] user_setup: [] must_haves: truths: - "执行任意步骤后,workflow_state.json 正确记录该步骤的完成状态" - "中断后重新执行,已完成的步骤被跳过,从中断点继续" - "状态文件崩溃后可从备份恢复" artifacts: - path: "kb_pipeline/state.py" provides: "WorkflowState 和 WorkflowStateManager" min_lines: 80 exports: ["WorkflowState", "StepRecord", "StepStatus", "WorkflowStateManager"] - path: "tests/test_pipeline/test_state.py" provides: "状态管理单元测试" min_lines: 100 key_links: - from: "WorkflowStateManager.save()" to: "workflow_state.json" via: "原子写入 + 备份轮转" pattern: "tempfile.mkstemp.*os.replace" - from: "WorkflowState.is_step_completed()" to: "幂等执行检查" via: "步骤状态查询" pattern: "status == StepStatus.COMPLETED" --- 实现 WorkflowState 和 WorkflowStateManager,提供步骤级状态持久化、幂等执行检查和原子写入保障。 Purpose: 为工作流提供可靠的状态管理,支持断点续传和崩溃恢复 Output: kb_pipeline/state.py + 完整的单元测试 @/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md @/home/starmen1265/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md From kb_pipeline/schemas.py (created by 01-02): ```python 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 WorkflowStateManager kb_pipeline/state.py, tests/test_pipeline/test_state.py - WorkflowState.is_step_completed(step_name) 返回 True 当且仅当步骤状态为 COMPLETED - WorkflowState.mark_step_completed() 正确更新步骤状态和时间戳 - WorkflowStateManager.save() 使用原子写入,崩溃不损坏文件 - WorkflowStateManager.load() 主文件损坏时从备份恢复 - WorkflowStateManager.get_or_create() 返回现有状态或创建新状态 1. 在 state.py 中导入 schemas 模块的 WorkflowState, StepRecord, StepStatus 2. 实现 WorkflowStateManager 类: - __init__(content_dir: Path): 初始化内容目录和状态文件路径 - load() -> Optional[WorkflowState]: 加载状态,失败时尝试备份 - save(state: WorkflowState): 原子保存,备份轮转 - get_or_create(content_id, platform, source_url): 获取或创建状态 3. 参考 gsd-openclaw/state_manager.py 的原子写入模式 Task 1: Write failing tests for WorkflowStateManager tests/test_pipeline/test_state.py - Test is_step_completed returns True for completed step - Test is_step_completed returns False for pending/running/failed step - Test mark_step_completed updates status and timestamp - Test save creates file atomically with backup rotation - Test load falls back to backup on corruption - Test get_or_create returns existing or creates new 创建 tests/test_pipeline/test_state.py 测试文件,包含以下测试类: - TestWorkflowStateIsStepCompleted: 测试 is_step_completed 方法 - TestWorkflowStateMarkStep: 测试 mark_step_started/completed/failed 方法 - TestAtomicWrite: 测试原子写入和备份轮转 - TestBackupFallback: 测试主文件损坏时的备份恢复 - TestStateManagerGetOrCreate: 测试 get_or_create 方法 参考 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 - WorkflowStateManager 可以原子方式保存和加载状态 - 状态文件损坏时可从备份恢复 - is_step_completed 支持幂等执行检查 - 所有测试通过,覆盖率 > 80% After completion, create `.planning/phases/01-foundation/01-01-SUMMARY.md`