monoco-toolkit 0.3.5__py3-none-any.whl → 0.3.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. monoco/cli/workspace.py +1 -1
  2. monoco/core/config.py +51 -0
  3. monoco/core/hooks/__init__.py +19 -0
  4. monoco/core/hooks/base.py +104 -0
  5. monoco/core/hooks/builtin/__init__.py +11 -0
  6. monoco/core/hooks/builtin/git_cleanup.py +266 -0
  7. monoco/core/hooks/builtin/logging_hook.py +78 -0
  8. monoco/core/hooks/context.py +131 -0
  9. monoco/core/hooks/registry.py +222 -0
  10. monoco/core/integrations.py +6 -0
  11. monoco/core/registry.py +2 -0
  12. monoco/core/setup.py +1 -1
  13. monoco/core/skills.py +226 -42
  14. monoco/features/{scheduler → agent}/__init__.py +4 -2
  15. monoco/features/{scheduler → agent}/cli.py +134 -80
  16. monoco/features/{scheduler → agent}/config.py +17 -3
  17. monoco/features/agent/defaults.py +55 -0
  18. monoco/features/agent/flow_skills.py +281 -0
  19. monoco/features/{scheduler → agent}/manager.py +39 -2
  20. monoco/features/{scheduler → agent}/models.py +6 -3
  21. monoco/features/{scheduler → agent}/reliability.py +1 -1
  22. monoco/features/agent/resources/skills/flow_engineer/SKILL.md +94 -0
  23. monoco/features/agent/resources/skills/flow_manager/SKILL.md +88 -0
  24. monoco/features/agent/resources/skills/flow_reviewer/SKILL.md +114 -0
  25. monoco/features/{scheduler → agent}/session.py +39 -5
  26. monoco/features/{scheduler → agent}/worker.py +2 -2
  27. monoco/features/i18n/resources/skills/i18n_scan_workflow/SKILL.md +105 -0
  28. monoco/features/issue/commands.py +427 -21
  29. monoco/features/issue/core.py +104 -0
  30. monoco/features/issue/criticality.py +553 -0
  31. monoco/features/issue/domain/models.py +28 -2
  32. monoco/features/issue/engine/machine.py +65 -37
  33. monoco/features/issue/git_service.py +185 -0
  34. monoco/features/issue/linter.py +291 -62
  35. monoco/features/issue/models.py +91 -14
  36. monoco/features/issue/resources/en/SKILL.md +48 -0
  37. monoco/features/issue/resources/skills/issue_lifecycle_workflow/SKILL.md +159 -0
  38. monoco/features/issue/resources/zh/SKILL.md +50 -0
  39. monoco/features/issue/test_priority_integration.py +1 -0
  40. monoco/features/issue/validator.py +185 -65
  41. monoco/features/memo/__init__.py +4 -0
  42. monoco/features/memo/adapter.py +32 -0
  43. monoco/features/memo/cli.py +112 -0
  44. monoco/features/memo/core.py +146 -0
  45. monoco/features/memo/resources/skills/note_processing_workflow/SKILL.md +140 -0
  46. monoco/features/memo/resources/zh/AGENTS.md +8 -0
  47. monoco/features/memo/resources/zh/SKILL.md +75 -0
  48. monoco/features/spike/resources/skills/research_workflow/SKILL.md +121 -0
  49. monoco/main.py +6 -3
  50. {monoco_toolkit-0.3.5.dist-info → monoco_toolkit-0.3.9.dist-info}/METADATA +1 -1
  51. {monoco_toolkit-0.3.5.dist-info → monoco_toolkit-0.3.9.dist-info}/RECORD +56 -35
  52. monoco/features/scheduler/defaults.py +0 -54
  53. monoco/features/skills/__init__.py +0 -0
  54. monoco/features/skills/core.py +0 -102
  55. /monoco/core/{hooks.py → githooks.py} +0 -0
  56. /monoco/features/{scheduler → agent}/engines.py +0 -0
  57. {monoco_toolkit-0.3.5.dist-info → monoco_toolkit-0.3.9.dist-info}/WHEEL +0 -0
  58. {monoco_toolkit-0.3.5.dist-info → monoco_toolkit-0.3.9.dist-info}/entry_points.txt +0 -0
  59. {monoco_toolkit-0.3.5.dist-info → monoco_toolkit-0.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,281 @@
1
+ """
2
+ Flow Skills Manager for Monoco Scheduler.
3
+
4
+ This module provides management and injection of standard Agent workflow skills
5
+ (Flow Skills) following the Kimi CLI Flow Skill format.
6
+
7
+ Note: This module is now a thin wrapper around SkillManager for backward compatibility.
8
+ New code should use SkillManager directly for multi-skill architecture support.
9
+
10
+ Key Responsibilities:
11
+ 1. Discover flow skills from resources/skills/ directory
12
+ 2. Inject flow skills to target agent framework directories
13
+ 3. Handle .gitignore updates for injected skills
14
+ """
15
+
16
+ import shutil
17
+ from pathlib import Path
18
+ from typing import List, Set
19
+ from rich.console import Console
20
+
21
+ console = Console()
22
+
23
+ # Prefix for injected flow skills to avoid conflicts
24
+ FLOW_SKILL_PREFIX = "monoco_flow_"
25
+
26
+ # Gitignore pattern for flow skills
27
+ GITIGNORE_PATTERN = f"{FLOW_SKILL_PREFIX}*/"
28
+
29
+
30
+ def discover_flow_skills(resources_dir: Path) -> List[Path]:
31
+ """
32
+ Discover all flow skill directories in the resources/skills/ directory.
33
+
34
+ Flow skills are identified by either:
35
+ 1. Directory name starting with "flow_" (legacy pattern)
36
+ 2. SKILL.md containing "type: flow" in front matter (new pattern)
37
+
38
+ Args:
39
+ resources_dir: Path to the resources directory (e.g., monoco/features/scheduler/resources/)
40
+
41
+ Returns:
42
+ List of paths to flow skill directories
43
+ """
44
+ skills_dir = resources_dir / "skills"
45
+ if not skills_dir.exists():
46
+ return []
47
+
48
+ flow_skills = []
49
+ for item in skills_dir.iterdir():
50
+ if not item.is_dir():
51
+ continue
52
+
53
+ skill_file = item / "SKILL.md"
54
+ if not skill_file.exists():
55
+ continue
56
+
57
+ # Check legacy pattern: directory starts with "flow_"
58
+ if item.name.startswith("flow_"):
59
+ flow_skills.append(item)
60
+ continue
61
+
62
+ # Check new pattern: SKILL.md contains "type: flow" in front matter
63
+ try:
64
+ content = skill_file.read_text(encoding="utf-8")
65
+ # Look for type: flow in front matter (between --- markers)
66
+ if content.startswith("---"):
67
+ front_matter_end = content.find("---", 3)
68
+ if front_matter_end != -1:
69
+ front_matter = content[3:front_matter_end]
70
+ if "type: flow" in front_matter:
71
+ flow_skills.append(item)
72
+ except Exception:
73
+ pass # Skip files that can't be read
74
+
75
+ return sorted(flow_skills)
76
+
77
+
78
+ def inject_flow_skill(
79
+ skill_dir: Path, target_dir: Path, prefix: str = FLOW_SKILL_PREFIX
80
+ ) -> bool:
81
+ """
82
+ Inject a single flow skill to the target directory.
83
+
84
+ Args:
85
+ skill_dir: Source flow skill directory (e.g., .../flow_engineer/)
86
+ target_dir: Target directory for skill injection (e.g., .agent/skills/)
87
+ prefix: Prefix to add to the skill directory name
88
+
89
+ Returns:
90
+ True if injection successful, False otherwise
91
+ """
92
+ try:
93
+ # Calculate target skill name with prefix
94
+ # e.g., flow_engineer -> monoco_flow_engineer
95
+ target_skill_name = f"{prefix}{skill_dir.name}"
96
+ target_skill_dir = target_dir / target_skill_name
97
+
98
+ # Remove existing skill directory if present
99
+ if target_skill_dir.exists():
100
+ shutil.rmtree(target_skill_dir)
101
+
102
+ # Copy skill directory
103
+ shutil.copytree(skill_dir, target_skill_dir)
104
+
105
+ console.print(f"[green] ✓ Injected {target_skill_name}/[/green]")
106
+ return True
107
+
108
+ except Exception as e:
109
+ console.print(f"[red] ✗ Failed to inject {skill_dir.name}: {e}[/red]")
110
+ return False
111
+
112
+
113
+ def sync_flow_skills(
114
+ resources_dir: Path,
115
+ target_dir: Path,
116
+ prefix: str = FLOW_SKILL_PREFIX,
117
+ force: bool = False,
118
+ ) -> dict:
119
+ """
120
+ Synchronize all flow skills from resources to target directory.
121
+
122
+ This function:
123
+ 1. Discovers all flow skills in resources/skills/
124
+ 2. Injects them to target_dir with the specified prefix
125
+ 3. Optionally removes skills that no longer exist in source
126
+
127
+ Args:
128
+ resources_dir: Path to the resources directory
129
+ target_dir: Target directory for skill injection (e.g., .agent/skills/)
130
+ prefix: Prefix to add to skill directory names
131
+ force: Force re-injection even if skills already exist
132
+
133
+ Returns:
134
+ Dictionary with 'injected', 'failed', 'removed' counts
135
+ """
136
+ results = {"injected": 0, "failed": 0, "removed": 0}
137
+
138
+ # Ensure target directory exists
139
+ target_dir.mkdir(parents=True, exist_ok=True)
140
+
141
+ # Discover flow skills
142
+ flow_skills = discover_flow_skills(resources_dir)
143
+
144
+ if not flow_skills:
145
+ console.print("[yellow]No flow skills found in resources[/yellow]")
146
+ return results
147
+
148
+ console.print(f"[dim]Found {len(flow_skills)} flow skill(s)[/dim]")
149
+
150
+ # Track expected skill names
151
+ expected_skills: Set[str] = set()
152
+
153
+ # Inject each flow skill
154
+ for skill_dir in flow_skills:
155
+ target_skill_name = f"{prefix}{skill_dir.name}"
156
+ expected_skills.add(target_skill_name)
157
+
158
+ # Check if already exists and not force
159
+ target_skill_dir = target_dir / target_skill_name
160
+ if target_skill_dir.exists() and not force:
161
+ # Check if source is newer
162
+ source_mtime = (skill_dir / "SKILL.md").stat().st_mtime
163
+ target_mtime = (target_skill_dir / "SKILL.md").stat().st_mtime
164
+
165
+ if source_mtime <= target_mtime:
166
+ console.print(f"[dim] = {target_skill_name}/ is up to date[/dim]")
167
+ continue
168
+
169
+ if inject_flow_skill(skill_dir, target_dir, prefix):
170
+ results["injected"] += 1
171
+ else:
172
+ results["failed"] += 1
173
+
174
+ # Clean up orphaned skills (optional, when force=True)
175
+ if force:
176
+ for item in target_dir.iterdir():
177
+ if item.is_dir() and item.name.startswith(prefix):
178
+ if item.name not in expected_skills:
179
+ shutil.rmtree(item)
180
+ console.print(f"[dim] - Removed orphaned {item.name}/[/dim]")
181
+ results["removed"] += 1
182
+
183
+ return results
184
+
185
+
186
+ def update_gitignore(project_root: Path, pattern: str = GITIGNORE_PATTERN) -> bool:
187
+ """
188
+ Add flow skill pattern to .gitignore if not present.
189
+
190
+ Args:
191
+ project_root: Project root directory
192
+ pattern: Gitignore pattern to add
193
+
194
+ Returns:
195
+ True if .gitignore was updated or already contains pattern
196
+ """
197
+ gitignore_path = project_root / ".gitignore"
198
+
199
+ try:
200
+ # Read existing content
201
+ if gitignore_path.exists():
202
+ content = gitignore_path.read_text(encoding="utf-8")
203
+ lines = content.splitlines()
204
+ else:
205
+ lines = []
206
+
207
+ # Check if pattern already exists
208
+ for line in lines:
209
+ if line.strip() == pattern or line.strip() == f"/{pattern}":
210
+ return True
211
+
212
+ # Add pattern with comment
213
+ comment = "# Monoco Flow Skills (auto-generated)"
214
+ new_lines = [comment, pattern, ""]
215
+
216
+ # Append to file
217
+ with open(gitignore_path, "a", encoding="utf-8") as f:
218
+ # Add newline if file doesn't end with one
219
+ if lines and not content.endswith("\n"):
220
+ f.write("\n")
221
+ f.write("\n".join(new_lines))
222
+
223
+ console.print(f"[green] ✓ Updated .gitignore with {pattern}[/green]")
224
+ return True
225
+
226
+ except Exception as e:
227
+ console.print(f"[red] ✗ Failed to update .gitignore: {e}[/red]")
228
+ return False
229
+
230
+
231
+ def remove_flow_skills(target_dir: Path, prefix: str = FLOW_SKILL_PREFIX) -> int:
232
+ """
233
+ Remove all injected flow skills from target directory.
234
+
235
+ Args:
236
+ target_dir: Target directory (e.g., .agent/skills/)
237
+ prefix: Prefix used for flow skill directories
238
+
239
+ Returns:
240
+ Number of skills removed
241
+ """
242
+ if not target_dir.exists():
243
+ return 0
244
+
245
+ removed_count = 0
246
+ for item in target_dir.iterdir():
247
+ if item.is_dir() and item.name.startswith(prefix):
248
+ shutil.rmtree(item)
249
+ console.print(f"[green] ✓ Removed {item.name}/[/green]")
250
+ removed_count += 1
251
+
252
+ return removed_count
253
+
254
+
255
+ def get_flow_skill_commands(target_dir: Path, prefix: str = FLOW_SKILL_PREFIX) -> List[str]:
256
+ """
257
+ Get list of available flow skill commands.
258
+
259
+ In Kimi CLI, flow skills are invoked via /flow:<role> command.
260
+ This function extracts the role names from injected flow skills.
261
+
262
+ Args:
263
+ target_dir: Target directory (e.g., .agent/skills/)
264
+ prefix: Prefix used for flow skill directories
265
+
266
+ Returns:
267
+ List of available /flow:<role> commands
268
+ """
269
+ if not target_dir.exists():
270
+ return []
271
+
272
+ commands = []
273
+ for item in target_dir.iterdir():
274
+ if item.is_dir() and item.name.startswith(prefix):
275
+ # Extract role from directory name
276
+ # e.g., monoco_flow_engineer -> engineer
277
+ role = item.name[len(prefix) + 5:] # Remove prefix + "flow_"
278
+ if role:
279
+ commands.append(f"/flow:{role}")
280
+
281
+ return sorted(commands)
@@ -1,8 +1,12 @@
1
1
  from typing import Dict, List, Optional
2
2
  import uuid
3
+ from pathlib import Path
4
+
3
5
  from .models import RoleTemplate
4
6
  from .worker import Worker
5
7
  from .session import Session, RuntimeSession
8
+ from monoco.core.hooks import HookRegistry, get_registry
9
+ from monoco.core.config import find_monoco_root, MonocoConfig
6
10
 
7
11
 
8
12
  class SessionManager:
@@ -11,9 +15,37 @@ class SessionManager:
11
15
  Responsible for creating, tracking, and retrieving sessions.
12
16
  """
13
17
 
14
- def __init__(self):
18
+ def __init__(
19
+ self,
20
+ project_root: Optional[Path] = None,
21
+ hook_registry: Optional[HookRegistry] = None,
22
+ config: Optional[MonocoConfig] = None,
23
+ ):
15
24
  # In-memory storage for now. In prod, this might be a DB or file-backed.
16
25
  self._sessions: Dict[str, RuntimeSession] = {}
26
+ self.project_root = project_root or find_monoco_root()
27
+ self.config = config
28
+
29
+ # Initialize hook registry
30
+ self.hook_registry = hook_registry or get_registry()
31
+
32
+ # Load hooks from config if available
33
+ self._load_hooks_from_config()
34
+
35
+ def _load_hooks_from_config(self) -> None:
36
+ """Load and register hooks from configuration."""
37
+ if self.config is None:
38
+ try:
39
+ from monoco.core.config import get_config
40
+ self.config = get_config(str(self.project_root))
41
+ except Exception:
42
+ return
43
+
44
+ # Load hooks from config
45
+ if self.config and hasattr(self.config, "session_hooks"):
46
+ hooks_config = self.config.session_hooks
47
+ if hooks_config:
48
+ self.hook_registry.load_from_config(hooks_config, self.project_root)
17
49
 
18
50
  def create_session(self, issue_id: str, role: RoleTemplate) -> RuntimeSession:
19
51
  session_id = str(uuid.uuid4())
@@ -29,7 +61,12 @@ class SessionManager:
29
61
  )
30
62
 
31
63
  worker = Worker(role, issue_id)
32
- runtime = RuntimeSession(session_model, worker)
64
+ runtime = RuntimeSession(
65
+ session_model,
66
+ worker,
67
+ hook_registry=self.hook_registry,
68
+ project_root=self.project_root,
69
+ )
33
70
  self._sessions[session_id] = runtime
34
71
  return runtime
35
72
 
@@ -4,14 +4,13 @@ from pydantic import BaseModel, Field
4
4
 
5
5
  class RoleTemplate(BaseModel):
6
6
  name: str = Field(
7
- ..., description="Unique identifier for the role (e.g., 'crafter')"
7
+ ..., description="Unique identifier for the role (e.g., 'Planner')"
8
8
  )
9
9
  description: str = Field(..., description="Human-readable description of the role")
10
10
  trigger: str = Field(
11
11
  ..., description="Event that triggers this agent (e.g., 'issue.created')"
12
12
  )
13
13
  goal: str = Field(..., description="The primary goal/output of this agent")
14
- tools: List[str] = Field(default_factory=list, description="List of allowed tools")
15
14
  system_prompt: str = Field(
16
15
  ..., description="The system prompt template for this agent"
17
16
  )
@@ -20,5 +19,9 @@ class RoleTemplate(BaseModel):
20
19
  )
21
20
 
22
21
 
23
- class SchedulerConfig(BaseModel):
22
+ class AgentConfig(BaseModel):
24
23
  roles: List[RoleTemplate] = Field(default_factory=list)
24
+
25
+
26
+ # Backward compatibility alias
27
+ SchedulerConfig = AgentConfig
@@ -20,7 +20,7 @@ class ApoptosisManager:
20
20
  roles = load_scheduler_config(project_root)
21
21
 
22
22
  # Find coroner role
23
- self.coroner_role = roles.get("coroner")
23
+ self.coroner_role = roles.get("Coroner")
24
24
 
25
25
  if not self.coroner_role:
26
26
  raise ValueError("Coroner role not defined!")
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: flow-engineer
3
+ description: Engineer 角色的标准化工作流 (Flow Skill)。定义从需求调研到代码提交的标准操作流程,确保测试覆盖和代码质量。
4
+ type: flow
5
+ role: engineer
6
+ version: 1.0.0
7
+ ---
8
+
9
+ # Engineer Flow
10
+
11
+ Engineer 角色的标准化工作流,确保代码开发遵循 "Investigate → Code → Test → Report → Submit" 流程。
12
+
13
+ ## 工作流状态机
14
+
15
+ ```mermaid
16
+ stateDiagram-v2
17
+ [*] --> Investigate: 接收任务
18
+
19
+ Investigate --> Code: 需求清晰
20
+ Investigate --> Investigate: 需求模糊<br/>(请求澄清)
21
+
22
+ Code --> Test: 编码完成
23
+
24
+ Test --> Test: 测试失败<br/>(修复代码)
25
+ Test --> Report: 测试通过
26
+
27
+ Report --> Submit: 报告完成
28
+
29
+ Submit --> [*]: 提交成功
30
+ ```
31
+
32
+ ## 执行步骤
33
+
34
+ ### 1. Investigate (调研)
35
+
36
+ - **目标**: 充分理解需求,识别技术风险和依赖
37
+ - **输入**: Issue 描述、相关代码、依赖 Issue
38
+ - **输出**: 技术方案草稿、风险清单
39
+ - **检查点**:
40
+ - [ ] 阅读并理解 Issue 描述
41
+ - [ ] 识别相关代码文件
42
+ - [ ] 检查依赖 Issue 状态
43
+ - [ ] 评估技术可行性
44
+
45
+ ### 2. Code (编码)
46
+
47
+ - **目标**: 实现功能或修复缺陷
48
+ - **前置条件**: 需求已清晰,分支已创建 (`monoco issue start <ID> --branch`)
49
+ - **检查点**:
50
+ - [ ] 遵循项目代码规范
51
+ - [ ] 编写/更新必要的文档
52
+ - [ ] 处理边界情况
53
+
54
+ ### 3. Test (测试)
55
+
56
+ - **目标**: 确保代码质量和功能正确性
57
+ - **策略**: 循环测试直到通过
58
+ - **检查点**:
59
+ - [ ] 编写/更新单元测试
60
+ - [ ] 运行测试套件 (`pytest`, `cargo test`, etc.)
61
+ - [ ] 修复失败的测试
62
+ - [ ] 检查测试覆盖率
63
+
64
+ ### 4. Report (报告)
65
+
66
+ - **目标**: 记录变更内容,更新 Issue 状态
67
+ - **检查点**:
68
+ - [ ] 更新 Issue 文件追踪 (`monoco issue sync-files`)
69
+ - [ ] 编写变更摘要
70
+ - [ ] 更新任务清单 (Checkboxes)
71
+
72
+ ### 5. Submit (提交)
73
+
74
+ - **目标**: 完成代码提交,进入评审流程
75
+ - **检查点**:
76
+ - [ ] 运行 `monoco issue lint` 检查合规性
77
+ - [ ] 运行 `monoco issue submit <ID>`
78
+ - [ ] 等待评审结果
79
+
80
+ ## 决策分支
81
+
82
+ | 条件 | 动作 |
83
+ |------|------|
84
+ | 需求不清晰 | 返回 Investigate,请求澄清 |
85
+ | 测试失败 | 返回 Code,修复问题 |
86
+ | Lint 失败 | 修复合规性问题,重新 Submit |
87
+ | 评审拒绝 | 返回 Code,按反馈修改 |
88
+
89
+ ## 合规要求
90
+
91
+ - **禁止**: 跳过测试直接提交
92
+ - **禁止**: 在 main/master 分支直接修改代码
93
+ - **必须**: 使用 `monoco issue start --branch` 创建功能分支
94
+ - **必须**: 所有单元测试通过后才能 Submit
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: flow-manager
3
+ description: Manager 角色的标准化工作流 (Flow Skill)。定义从 Inbox 整理到任务指派的标准操作流程,确保需求清晰和任务合理拆解。
4
+ type: flow
5
+ role: manager
6
+ version: 1.0.0
7
+ ---
8
+
9
+ # Manager Flow
10
+
11
+ Manager 角色的标准化工作流,确保 "Inbox → Clarify → Decompose → Assign" 流程。
12
+
13
+ ## 工作流状态机
14
+
15
+ ```mermaid
16
+ stateDiagram-v2
17
+ [*] --> Inbox: 新需求/想法
18
+
19
+ Inbox --> Clarify: 开始处理
20
+ Inbox --> Inbox: 暂存<br/>(低优先级)
21
+
22
+ Clarify --> Decompose: 需求清晰
23
+ Clarify --> Clarify: 需更多信息<br/>(等待反馈)
24
+
25
+ Decompose --> Assign: 拆解完成
26
+ Decompose --> Decompose: 过于复杂<br/>(拆分为 Epic)
27
+
28
+ Assign --> [*]: 指派完成
29
+ ```
30
+
31
+ ## 执行步骤
32
+
33
+ ### 1. Inbox (收件箱)
34
+
35
+ - **目标**: 收集和暂存所有 incoming 需求、想法和任务
36
+ - **输入**: Memo、用户反馈、系统告警、技术债务
37
+ - **检查点**:
38
+ - [ ] 记录需求来源和背景
39
+ - [ ] 初步分类 (Feature/Chore/Fix)
40
+ - [ ] 评估紧急程度
41
+
42
+ ### 2. Clarify (需求澄清)
43
+
44
+ - **目标**: 将模糊的需求转化为清晰的描述
45
+ - **策略**: 5W2H 分析法
46
+ - **检查点**:
47
+ - [ ] **What**: 要解决什么问题?
48
+ - [ ] **Why**: 为什么重要?
49
+ - [ ] **Who**: 谁是利益相关者?
50
+ - [ ] **When**: 期望的完成时间?
51
+ - [ ] **Where**: 影响范围?
52
+ - [ ] **How**: 建议的实现方式?
53
+ - [ ] **How Much**: 工作量预估?
54
+
55
+ ### 3. Decompose (任务拆解)
56
+
57
+ - **目标**: 将大任务拆分为可独立交付的子任务
58
+ - **策略**: 垂直切片 (Vertical Slicing)
59
+ - **检查点**:
60
+ - [ ] 识别核心价值和依赖关系
61
+ - [ ] 拆分为可独立交付的 Feature/Chore/Fix
62
+ - [ ] 设置合理的优先级
63
+ - [ ] 为复杂任务创建 Epic
64
+
65
+ ### 4. Assign (任务指派)
66
+
67
+ - **目标**: 将任务分配给合适的执行者
68
+ - **检查点**:
69
+ - [ ] 评估团队能力和负载
70
+ - [ ] 明确验收标准 (Acceptance Criteria)
71
+ - [ ] 设置合理的截止日期
72
+ - [ ] 通知相关成员
73
+
74
+ ## 决策分支
75
+
76
+ | 条件 | 动作 |
77
+ |------|------|
78
+ | 需求过于模糊 | 返回 Inbox,等待更多信息 |
79
+ | 任务过于复杂 | 创建 Epic,拆分为多个 Feature |
80
+ | 依赖其他任务 | 设置依赖关系,调整优先级 |
81
+ | 资源不足 | 调整范围或延期 |
82
+
83
+ ## 合规要求
84
+
85
+ - **必须**: 每个任务都有清晰的验收标准
86
+ - **必须**: 复杂任务必须拆分为 Epic + Features
87
+ - **禁止**: 指派没有澄清需求给 Engineer
88
+ - **建议**: 使用 `monoco memo` 管理临时想法
@@ -0,0 +1,114 @@
1
+ ---
2
+ name: flow-reviewer
3
+ description: Reviewer 角色的标准化工作流 (Flow Skill)。定义从代码检出到评审完成的标准操作流程,确保代码质量和流程合规。
4
+ type: flow
5
+ role: reviewer
6
+ version: 1.0.0
7
+ ---
8
+
9
+ # Reviewer Flow
10
+
11
+ Reviewer 角色的标准化工作流,确保 "Checkout → Test → Review → Decide → Cleanup" 流程。
12
+
13
+ ## 工作流状态机
14
+
15
+ ```mermaid
16
+ stateDiagram-v2
17
+ [*] --> Checkout: 收到评审请求
18
+
19
+ Checkout --> Test: 检出完成
20
+ Checkout --> Checkout: 检出失败<br/>(环境检查)
21
+
22
+ Test --> Review: 测试通过
23
+ Test --> Test: 测试失败<br/>(记录问题)
24
+
25
+ Review --> Approve: 代码 OK
26
+ Review --> Reject: 发现问题
27
+
28
+ Reject --> Checkout: 修复后重审
29
+
30
+ Approve --> Cleanup: 批准
31
+
32
+ Cleanup --> [*]: 清理完成
33
+ ```
34
+
35
+ ## 执行步骤
36
+
37
+ ### 1. Checkout (检出)
38
+
39
+ - **目标**: 获取待评审的代码
40
+ - **检查点**:
41
+ - [ ] 检出 PR/Branch
42
+ - [ ] 确认与 Base 分支的差异
43
+ - [ ] 检查环境配置
44
+
45
+ ### 2. Test (测试)
46
+
47
+ - **目标**: 验证功能正确性和测试覆盖
48
+ - **检查点**:
49
+ - [ ] 运行单元测试
50
+ - [ ] 运行集成测试 (如适用)
51
+ - [ ] 验证手动测试场景
52
+ - [ ] 检查测试覆盖率报告
53
+
54
+ ### 3. Review (代码审查)
55
+
56
+ - **目标**: 检查代码质量和设计合理性
57
+ - **检查清单**:
58
+ - [ ] **功能**: 代码是否实现了需求?
59
+ - [ ] **设计**: 架构是否合理?
60
+ - [ ] **可读性**: 代码是否易于理解?
61
+ - [ ] **测试**: 测试是否充分?
62
+ - [ ] **文档**: 文档是否同步更新?
63
+ - [ ] **合规**: 是否遵循项目规范?
64
+
65
+ ### 4. Decide (决策)
66
+
67
+ - **目标**: 做出批准或拒绝的决定
68
+ - **选项**:
69
+ - **Approve**: 代码可以合并
70
+ - **Reject**: 需要修改,提供具体反馈
71
+ - **Request Changes**: 小问题,可快速修复
72
+
73
+ ### 5. Cleanup (清理)
74
+
75
+ - **目标**: 完成评审后的环境清理
76
+ - **检查点**:
77
+ - [ ] 删除本地分支 (如适用)
78
+ - [ ] 更新 Issue 状态
79
+ - [ ] 记录评审意见到 Review Comments
80
+
81
+ ## 决策分支
82
+
83
+ | 条件 | 动作 |
84
+ |------|------|
85
+ | 测试失败 | Reject,要求修复测试 |
86
+ | 代码风格问题 | Request Changes 或提供建议 |
87
+ | 设计问题 | Reject,要求重新设计 |
88
+ | 文档缺失 | Request Changes,要求补充 |
89
+ | 修复后重审 | 返回 Checkout,重新执行流程 |
90
+
91
+ ## 评审意见模板
92
+
93
+ ```markdown
94
+ ## Review Comments
95
+
96
+ ### ✅ 优点
97
+ -
98
+
99
+ ### ⚠️ 建议
100
+ -
101
+
102
+ ### ❌ 必须修改
103
+ -
104
+
105
+ ### 📝 其他
106
+ -
107
+ ```
108
+
109
+ ## 合规要求
110
+
111
+ - **必须**: 所有测试通过才能 Approve
112
+ - **必须**: 拒绝时必须提供具体反馈
113
+ - **禁止**: 未经测试直接 Approve
114
+ - **建议**: 使用 `monoco issue close --prune` 合并后清理