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>
225 lines
8.3 KiB
Markdown
225 lines
8.3 KiB
Markdown
---
|
|
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"
|
|
---
|
|
|
|
<objective>
|
|
实现 WorkflowState 和 WorkflowStateManager,提供步骤级状态持久化、幂等执行检查和原子写入保障。
|
|
|
|
Purpose: 为工作流提供可靠的状态管理,支持断点续传和崩溃恢复
|
|
Output: kb_pipeline/state.py + 完整的单元测试
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/home/starmen1265/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
|
|
<interfaces>
|
|
<!-- Key types from 01-02 Schema Registry that this plan depends on -->
|
|
<!-- These will be created by 01-02 before this plan runs -->
|
|
|
|
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
|
|
</interfaces>
|
|
</context>
|
|
|
|
<feature>
|
|
<name>WorkflowStateManager</name>
|
|
<files>kb_pipeline/state.py, tests/test_pipeline/test_state.py</files>
|
|
<behavior>
|
|
- WorkflowState.is_step_completed(step_name) 返回 True 当且仅当步骤状态为 COMPLETED
|
|
- WorkflowState.mark_step_completed() 正确更新步骤状态和时间戳
|
|
- WorkflowStateManager.save() 使用原子写入,崩溃不损坏文件
|
|
- WorkflowStateManager.load() 主文件损坏时从备份恢复
|
|
- WorkflowStateManager.get_or_create() 返回现有状态或创建新状态
|
|
</behavior>
|
|
<implementation>
|
|
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 的原子写入模式
|
|
</implementation>
|
|
</feature>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 1: Write failing tests for WorkflowStateManager</name>
|
|
<files>tests/test_pipeline/test_state.py</files>
|
|
<behavior>
|
|
- 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
|
|
</behavior>
|
|
<action>
|
|
创建 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 的测试模式。
|
|
</action>
|
|
<verify>
|
|
<automated>pytest tests/test_pipeline/test_state.py -v --collect-only 2>/dev/null | grep "test_" | wc -l | xargs -I {} test {} -ge 10</automated>
|
|
</verify>
|
|
<done>测试文件包含至少 10 个测试用例,所有测试当前失败(RED 阶段)</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 2: Implement WorkflowStateManager</name>
|
|
<files>kb_pipeline/state.py</files>
|
|
<behavior>
|
|
- WorkflowStateManager.__init__ 正确设置 content_dir 和 state_path
|
|
- WorkflowStateManager.load() 返回 WorkflowState 或 None
|
|
- WorkflowStateManager.save() 使用原子写入模式
|
|
- WorkflowStateManager.get_or_create() 幂等创建状态
|
|
</behavior>
|
|
<action>
|
|
实现 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
|
|
```
|
|
</action>
|
|
<verify>
|
|
<automated>pytest tests/test_pipeline/test_state.py -v --tb=short</automated>
|
|
</verify>
|
|
<done>所有测试通过(GREEN 阶段)</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 3: Refactor and verify integration</name>
|
|
<files>kb_pipeline/state.py, tests/test_pipeline/test_state.py</files>
|
|
<behavior>
|
|
- 代码结构清晰,无重复
|
|
- 测试覆盖所有边界情况
|
|
- 与 schemas.py 正确集成
|
|
</behavior>
|
|
<action>
|
|
1. 检查代码质量: 移除重复代码,添加必要的类型注解
|
|
2. 添加文档字符串(如果缺失)
|
|
3. 确保与 kb_pipeline/schemas.py 的 WorkflowState 正确集成
|
|
4. 运行完整测试套件验证
|
|
</action>
|
|
<verify>
|
|
<automated>pytest tests/test_pipeline/test_state.py -v --tb=short -x</automated>
|
|
</verify>
|
|
<done>测试通过,代码结构清晰,与 schemas 模块正确集成</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
1. 运行 `pytest tests/test_pipeline/test_state.py -v` 全部通过
|
|
2. 验证原子写入: 创建状态文件后,确认存在 workflow_state.json
|
|
3. 验证备份轮转: 保存两次后,确认存在 .bak 文件
|
|
4. 验证幂等检查: is_step_completed 对已完成步骤返回 True
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- WorkflowStateManager 可以原子方式保存和加载状态
|
|
- 状态文件损坏时可从备份恢复
|
|
- is_step_completed 支持幂等执行检查
|
|
- 所有测试通过,覆盖率 > 80%
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/01-foundation/01-01-SUMMARY.md`
|
|
</output>
|