monoco-toolkit 0.3.9__py3-none-any.whl → 0.3.11__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.
- monoco/__main__.py +8 -0
- monoco/core/artifacts/__init__.py +16 -0
- monoco/core/artifacts/manager.py +575 -0
- monoco/core/artifacts/models.py +161 -0
- monoco/core/config.py +38 -4
- monoco/core/git.py +23 -0
- monoco/core/hooks/builtin/git_cleanup.py +1 -1
- monoco/core/ingestion/__init__.py +20 -0
- monoco/core/ingestion/discovery.py +248 -0
- monoco/core/ingestion/watcher.py +343 -0
- monoco/core/ingestion/worker.py +436 -0
- monoco/core/injection.py +63 -29
- monoco/core/integrations.py +2 -2
- monoco/core/loader.py +633 -0
- monoco/core/output.py +5 -5
- monoco/core/registry.py +34 -19
- monoco/core/resource/__init__.py +5 -0
- monoco/core/resource/finder.py +98 -0
- monoco/core/resource/manager.py +91 -0
- monoco/core/resource/models.py +35 -0
- monoco/core/skill_framework.py +292 -0
- monoco/core/skills.py +524 -385
- monoco/core/sync.py +73 -1
- monoco/core/workflow_converter.py +420 -0
- monoco/daemon/app.py +77 -1
- monoco/daemon/commands.py +10 -0
- monoco/daemon/mailroom_service.py +196 -0
- monoco/daemon/models.py +1 -0
- monoco/daemon/scheduler.py +236 -0
- monoco/daemon/services.py +185 -0
- monoco/daemon/triggers.py +55 -0
- monoco/features/agent/__init__.py +2 -2
- monoco/features/agent/adapter.py +41 -0
- monoco/features/agent/apoptosis.py +44 -0
- monoco/features/agent/cli.py +101 -144
- monoco/features/agent/config.py +35 -21
- monoco/features/agent/defaults.py +6 -49
- monoco/features/agent/engines.py +32 -6
- monoco/features/agent/manager.py +47 -6
- monoco/features/agent/models.py +2 -2
- monoco/features/agent/resources/atoms/atom-code-dev.yaml +61 -0
- monoco/features/agent/resources/atoms/atom-issue-lifecycle.yaml +73 -0
- monoco/features/agent/resources/atoms/atom-knowledge.yaml +55 -0
- monoco/features/agent/resources/atoms/atom-review.yaml +60 -0
- monoco/{core/resources/en → features/agent/resources/en/skills/monoco_atom_core}/SKILL.md +3 -1
- monoco/features/agent/resources/en/skills/monoco_workflow_agent_engineer/SKILL.md +94 -0
- monoco/features/agent/resources/en/skills/monoco_workflow_agent_manager/SKILL.md +93 -0
- monoco/features/agent/resources/en/skills/monoco_workflow_agent_planner/SKILL.md +85 -0
- monoco/features/agent/resources/en/skills/monoco_workflow_agent_reviewer/SKILL.md +114 -0
- monoco/features/agent/resources/workflows/workflow-dev.yaml +83 -0
- monoco/features/agent/resources/workflows/workflow-issue-create.yaml +72 -0
- monoco/features/agent/resources/workflows/workflow-review.yaml +94 -0
- monoco/features/agent/resources/zh/roles/monoco_role_engineer.yaml +49 -0
- monoco/features/agent/resources/zh/roles/monoco_role_manager.yaml +46 -0
- monoco/features/agent/resources/zh/roles/monoco_role_planner.yaml +46 -0
- monoco/features/agent/resources/zh/roles/monoco_role_reviewer.yaml +47 -0
- monoco/{core/resources/zh → features/agent/resources/zh/skills/monoco_atom_core}/SKILL.md +3 -1
- monoco/features/agent/resources/{skills/flow_engineer → zh/skills/monoco_workflow_agent_engineer}/SKILL.md +2 -2
- monoco/features/agent/resources/{skills/flow_manager → zh/skills/monoco_workflow_agent_manager}/SKILL.md +2 -2
- monoco/features/agent/resources/zh/skills/monoco_workflow_agent_planner/SKILL.md +259 -0
- monoco/features/agent/resources/zh/skills/monoco_workflow_agent_reviewer/SKILL.md +137 -0
- monoco/features/agent/session.py +59 -11
- monoco/features/agent/worker.py +38 -2
- monoco/features/artifact/__init__.py +0 -0
- monoco/features/artifact/adapter.py +33 -0
- monoco/features/artifact/resources/zh/AGENTS.md +14 -0
- monoco/features/artifact/resources/zh/skills/monoco_atom_artifact/SKILL.md +278 -0
- monoco/features/glossary/__init__.py +0 -0
- monoco/features/glossary/adapter.py +42 -0
- monoco/features/glossary/config.py +5 -0
- monoco/features/glossary/resources/en/AGENTS.md +29 -0
- monoco/features/glossary/resources/en/skills/monoco_atom_glossary/SKILL.md +35 -0
- monoco/features/glossary/resources/zh/AGENTS.md +29 -0
- monoco/features/glossary/resources/zh/skills/monoco_atom_glossary/SKILL.md +35 -0
- monoco/features/hooks/__init__.py +11 -0
- monoco/features/hooks/adapter.py +67 -0
- monoco/features/hooks/commands.py +309 -0
- monoco/features/hooks/core.py +441 -0
- monoco/features/hooks/resources/ADDING_HOOKS.md +234 -0
- monoco/features/i18n/adapter.py +18 -5
- monoco/features/i18n/core.py +482 -17
- monoco/features/i18n/resources/en/{SKILL.md → skills/monoco_atom_i18n/SKILL.md} +3 -1
- monoco/features/i18n/resources/en/skills/monoco_workflow_i18n_scan/SKILL.md +105 -0
- monoco/features/i18n/resources/zh/{SKILL.md → skills/monoco_atom_i18n/SKILL.md} +3 -1
- monoco/features/i18n/resources/{skills/i18n_scan_workflow → zh/skills/monoco_workflow_i18n_scan}/SKILL.md +2 -2
- monoco/features/issue/adapter.py +19 -6
- monoco/features/issue/commands.py +281 -7
- monoco/features/issue/core.py +272 -19
- monoco/features/issue/engine/machine.py +118 -5
- monoco/features/issue/linter.py +60 -5
- monoco/features/issue/models.py +3 -2
- monoco/features/issue/resources/en/AGENTS.md +109 -0
- monoco/features/issue/resources/en/{SKILL.md → skills/monoco_atom_issue/SKILL.md} +3 -1
- monoco/features/issue/resources/en/skills/monoco_workflow_issue_creation/SKILL.md +167 -0
- monoco/features/issue/resources/en/skills/monoco_workflow_issue_development/SKILL.md +224 -0
- monoco/features/issue/resources/en/skills/monoco_workflow_issue_management/SKILL.md +159 -0
- monoco/features/issue/resources/en/skills/monoco_workflow_issue_refinement/SKILL.md +203 -0
- monoco/features/issue/resources/hooks/post-checkout.sh +39 -0
- monoco/features/issue/resources/hooks/pre-commit.sh +41 -0
- monoco/features/issue/resources/hooks/pre-push.sh +35 -0
- monoco/features/issue/resources/zh/AGENTS.md +109 -0
- monoco/features/issue/resources/zh/{SKILL.md → skills/monoco_atom_issue_lifecycle/SKILL.md} +3 -1
- monoco/features/issue/resources/zh/skills/monoco_workflow_issue_creation/SKILL.md +167 -0
- monoco/features/issue/resources/zh/skills/monoco_workflow_issue_development/SKILL.md +224 -0
- monoco/features/issue/resources/{skills/issue_lifecycle_workflow → zh/skills/monoco_workflow_issue_management}/SKILL.md +2 -2
- monoco/features/issue/resources/zh/skills/monoco_workflow_issue_refinement/SKILL.md +203 -0
- monoco/features/issue/validator.py +101 -1
- monoco/features/memo/adapter.py +21 -8
- monoco/features/memo/cli.py +103 -10
- monoco/features/memo/core.py +178 -92
- monoco/features/memo/models.py +53 -0
- monoco/features/memo/resources/en/skills/monoco_atom_memo/SKILL.md +77 -0
- monoco/features/memo/resources/en/skills/monoco_workflow_note_processing/SKILL.md +140 -0
- monoco/features/memo/resources/zh/{SKILL.md → skills/monoco_atom_memo/SKILL.md} +3 -1
- monoco/features/memo/resources/{skills/note_processing_workflow → zh/skills/monoco_workflow_note_processing}/SKILL.md +2 -2
- monoco/features/spike/adapter.py +18 -5
- monoco/features/spike/resources/en/{SKILL.md → skills/monoco_atom_spike/SKILL.md} +3 -1
- monoco/features/spike/resources/en/skills/monoco_workflow_research/SKILL.md +121 -0
- monoco/features/spike/resources/zh/{SKILL.md → skills/monoco_atom_spike/SKILL.md} +3 -1
- monoco/features/spike/resources/{skills/research_workflow → zh/skills/monoco_workflow_research}/SKILL.md +2 -2
- monoco/main.py +38 -1
- monoco_toolkit-0.3.11.dist-info/METADATA +130 -0
- monoco_toolkit-0.3.11.dist-info/RECORD +181 -0
- monoco/features/agent/reliability.py +0 -106
- monoco/features/agent/resources/skills/flow_reviewer/SKILL.md +0 -114
- monoco_toolkit-0.3.9.dist-info/METADATA +0 -127
- monoco_toolkit-0.3.9.dist-info/RECORD +0 -115
- /monoco/{core → features/agent}/resources/en/AGENTS.md +0 -0
- /monoco/{core → features/agent}/resources/zh/AGENTS.md +0 -0
- {monoco_toolkit-0.3.9.dist-info → monoco_toolkit-0.3.11.dist-info}/WHEEL +0 -0
- {monoco_toolkit-0.3.9.dist-info → monoco_toolkit-0.3.11.dist-info}/entry_points.txt +0 -0
- {monoco_toolkit-0.3.9.dist-info → monoco_toolkit-0.3.11.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: monoco_workflow_agent_planner
|
|
3
|
+
description: Planner 角色的标准化工作流 (Flow Skill),负责分析、设计、规划和交接。
|
|
4
|
+
type: workflow
|
|
5
|
+
role: planner
|
|
6
|
+
version: 1.0.0
|
|
7
|
+
author: Monoco Toolkit
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# flow_planner
|
|
11
|
+
|
|
12
|
+
Planner 角色的标准化工作流 (Flow Skill),负责分析、设计、规划和交接。
|
|
13
|
+
|
|
14
|
+
## 工作流状态机
|
|
15
|
+
|
|
16
|
+
```mermaid
|
|
17
|
+
stateDiagram-v2
|
|
18
|
+
[*] --> Analyze: 接收输入
|
|
19
|
+
|
|
20
|
+
Analyze --> Design: 需求清晰
|
|
21
|
+
Analyze --> Analyze: 信息不足<br/>(收集更多)
|
|
22
|
+
|
|
23
|
+
Design --> Plan: 设计完成
|
|
24
|
+
Design --> Design: 方案冲突<br/>(重新设计)
|
|
25
|
+
|
|
26
|
+
Plan --> Handoff: 规划完成
|
|
27
|
+
Plan --> Plan: 依赖复杂<br/>(调整计划)
|
|
28
|
+
|
|
29
|
+
Handoff --> [*]: 交接成功
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 执行步骤
|
|
35
|
+
|
|
36
|
+
### 1. Analyze (分析)
|
|
37
|
+
|
|
38
|
+
**目标**: 充分理解需求和上下文
|
|
39
|
+
|
|
40
|
+
**入口条件**:
|
|
41
|
+
- 接收到 Memo 或 Issue 输入
|
|
42
|
+
- 或检测到需要细化的任务
|
|
43
|
+
|
|
44
|
+
**自动执行检查点**:
|
|
45
|
+
|
|
46
|
+
- [ ] **读取输入**: 读取 Memo 或 Issue 的完整内容
|
|
47
|
+
- [ ] **识别上下文**: 识别相关代码文件、模块和依赖
|
|
48
|
+
- [ ] **检查架构**: 检查现有架构和技术栈
|
|
49
|
+
- [ ] **评估范围**: 评估影响范围和复杂度
|
|
50
|
+
- [ ] **记录发现**: 将分析结果记录到 Issue 或创建新的研究 Issue
|
|
51
|
+
|
|
52
|
+
**退出条件**:
|
|
53
|
+
- 需求清晰明确 → 进入 Design
|
|
54
|
+
- 信息不足 → 返回 Analyze,收集更多信息
|
|
55
|
+
|
|
56
|
+
**命令参考**:
|
|
57
|
+
```bash
|
|
58
|
+
# 读取 Memo
|
|
59
|
+
monoco memo list
|
|
60
|
+
monoco memo open <id>
|
|
61
|
+
|
|
62
|
+
# 读取 Issue
|
|
63
|
+
cat Issues/<type>/<status>/<issue-file>.md
|
|
64
|
+
|
|
65
|
+
# 检查相关代码
|
|
66
|
+
grep -r "pattern" monoco/
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
### 2. Design (设计)
|
|
72
|
+
|
|
73
|
+
**目标**: 产出架构设计方案
|
|
74
|
+
|
|
75
|
+
**入口条件**:
|
|
76
|
+
- Analyze 阶段完成,需求清晰
|
|
77
|
+
|
|
78
|
+
**自动执行检查点**:
|
|
79
|
+
|
|
80
|
+
- [ ] **系统架构**: 设计系统架构和组件关系
|
|
81
|
+
- [ ] **继承性评估**: 评估与现有系统的兼容性
|
|
82
|
+
- [ ] **安全评估**: 识别安全风险和缓解措施
|
|
83
|
+
- [ ] **性能评估**: 评估性能影响和优化方案
|
|
84
|
+
- [ ] **可维护性**: 考虑可维护性和扩展性
|
|
85
|
+
- [ ] **设计文档**: 编写架构设计文档 (Architecture Decision Record)
|
|
86
|
+
|
|
87
|
+
**退出条件**:
|
|
88
|
+
- 设计完成且通过自评 → 进入 Plan
|
|
89
|
+
- 架构冲突 → 返回 Design,重新设计方案
|
|
90
|
+
|
|
91
|
+
**设计输出模板**:
|
|
92
|
+
```markdown
|
|
93
|
+
## Architecture Design
|
|
94
|
+
|
|
95
|
+
### 1. 系统架构
|
|
96
|
+
[架构图或描述]
|
|
97
|
+
|
|
98
|
+
### 2. 组件关系
|
|
99
|
+
- Component A → Component B
|
|
100
|
+
- 接口定义: ...
|
|
101
|
+
|
|
102
|
+
### 3. 技术选型
|
|
103
|
+
- 语言/框架: ...
|
|
104
|
+
- 依赖库: ...
|
|
105
|
+
|
|
106
|
+
### 4. 风险评估
|
|
107
|
+
| 风险 | 影响 | 缓解措施 |
|
|
108
|
+
|------|------|----------|
|
|
109
|
+
| ... | ... | ... |
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### 3. Plan (规划)
|
|
115
|
+
|
|
116
|
+
**目标**: 制定可执行的任务计划
|
|
117
|
+
|
|
118
|
+
**入口条件**:
|
|
119
|
+
- Design 阶段完成,架构方案确定
|
|
120
|
+
|
|
121
|
+
**自动执行检查点**:
|
|
122
|
+
|
|
123
|
+
- [ ] **任务分解**: 将工作分解为可执行的单元 (Issue/Feature)
|
|
124
|
+
- [ ] **依赖分析**: 识别任务间的依赖关系
|
|
125
|
+
- [ ] **工作量估算**: 估算每个任务的工作量和优先级
|
|
126
|
+
- [ ] **创建 Issue**: 使用 `monoco issue create` 创建子任务
|
|
127
|
+
- [ ] **更新父 Issue**: 更新原始 Issue 的任务列表和依赖
|
|
128
|
+
|
|
129
|
+
**退出条件**:
|
|
130
|
+
- 规划完成 → 进入 Handoff
|
|
131
|
+
- 依赖复杂 → 返回 Plan,调整任务分解
|
|
132
|
+
|
|
133
|
+
**命令参考**:
|
|
134
|
+
```bash
|
|
135
|
+
# 创建子任务
|
|
136
|
+
monoco issue create feature -t "子任务标题" --parent <parent-id>
|
|
137
|
+
|
|
138
|
+
# 更新 Issue
|
|
139
|
+
monoco issue edit <id> --add-task "任务描述"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### 4. Handoff (交接)
|
|
145
|
+
|
|
146
|
+
**目标**: 将任务交接给 Engineer
|
|
147
|
+
|
|
148
|
+
**入口条件**:
|
|
149
|
+
- Plan 阶段完成,任务已分解为可执行单元
|
|
150
|
+
|
|
151
|
+
**自动执行检查点**:
|
|
152
|
+
|
|
153
|
+
- [ ] **上下文摘要**: 生成完整的上下文摘要 (Context Summary)
|
|
154
|
+
- [ ] **更新 Issue**: 更新 Issue 描述,包含技术设计和执行步骤
|
|
155
|
+
- [ ] **标记状态**: 标记 Issue 为 `ready_for_dev`
|
|
156
|
+
- [ ] **通知 Engineer**: 如系统支持,通知 Engineer 有新任务
|
|
157
|
+
|
|
158
|
+
**交接文档模板**:
|
|
159
|
+
```markdown
|
|
160
|
+
## Handoff Document
|
|
161
|
+
|
|
162
|
+
### Context
|
|
163
|
+
[任务背景和目标的简要描述]
|
|
164
|
+
|
|
165
|
+
### Architecture
|
|
166
|
+
[架构设计的关键点]
|
|
167
|
+
|
|
168
|
+
### Implementation Guide
|
|
169
|
+
[实现步骤和注意事项]
|
|
170
|
+
|
|
171
|
+
### Acceptance Criteria
|
|
172
|
+
- [ ] 验收标准 1
|
|
173
|
+
- [ ] 验收标准 2
|
|
174
|
+
|
|
175
|
+
### Related Files
|
|
176
|
+
- `path/to/file1.py`
|
|
177
|
+
- `path/to/file2.py`
|
|
178
|
+
|
|
179
|
+
### Dependencies
|
|
180
|
+
- 依赖 Issue: #XXX
|
|
181
|
+
- 阻塞 Issue: #YYY
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**退出条件**:
|
|
185
|
+
- 交接成功 → 工作流结束
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 决策分支
|
|
190
|
+
|
|
191
|
+
| 条件 | 动作 | 说明 |
|
|
192
|
+
|------|------|------|
|
|
193
|
+
| 信息不足 | 返回 Analyze | 收集更多信息,可能创建 Spike Issue |
|
|
194
|
+
| 架构冲突 | 返回 Design | 重新设计方案,记录决策理由 |
|
|
195
|
+
| 依赖复杂 | 返回 Plan | 调整任务分解,简化依赖关系 |
|
|
196
|
+
| 规划完成 | 进入 Handoff | 交接给 Engineer |
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 与 Engineer 的协作
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
Planner (Analyze → Design → Plan)
|
|
204
|
+
↓
|
|
205
|
+
创建/细化 Issue
|
|
206
|
+
↓
|
|
207
|
+
Engineer (Investigate → Code → Test → Submit)
|
|
208
|
+
↓
|
|
209
|
+
Reviewer (Review → Approve/Reject)
|
|
210
|
+
↓
|
|
211
|
+
[如需要] → 返回 Planner 重新规划
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### 协作接口
|
|
215
|
+
|
|
216
|
+
**Planner → Engineer**:
|
|
217
|
+
- 输出: 细化的 Issue + 架构设计文档
|
|
218
|
+
- 格式: Issue 描述中包含 "## Implementation Guide" 章节
|
|
219
|
+
- 标记: Issue 标记为 `ready_for_dev`
|
|
220
|
+
|
|
221
|
+
**Engineer → Planner**:
|
|
222
|
+
- 触发: Engineer 发现需求不清或架构问题
|
|
223
|
+
- 动作: 标记 Issue 为 `needs_refine`,Planner 重新介入
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## 使用方式
|
|
228
|
+
|
|
229
|
+
### 手动触发
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
# 以 Planner 角色运行
|
|
233
|
+
monoco agent run --role Planner --input Issues/Features/open/FEAT-XXXX.md
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 自动触发
|
|
237
|
+
|
|
238
|
+
当满足以下条件时自动触发:
|
|
239
|
+
1. 新 Memo 创建且包含 `#plan` 标签
|
|
240
|
+
2. Issue 被标记为 `needs_refine`
|
|
241
|
+
3. Epic 创建后需要分解为 Features
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 最佳实践
|
|
246
|
+
|
|
247
|
+
1. **Evidence Based**: 所有架构决策必须有代码或文档证据支持
|
|
248
|
+
2. **Incremental Design**: 优先采用增量式设计,避免过度设计
|
|
249
|
+
3. **Clear Boundaries**: 明确模块边界和接口契约
|
|
250
|
+
4. **Document First**: 先写设计文档,再创建实现任务
|
|
251
|
+
5. **Review Loop**: 复杂设计应经过 Review 后再交接
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 相关资源
|
|
256
|
+
|
|
257
|
+
- Role 定义: `monoco/features/agent/resources/roles/planner.yaml`
|
|
258
|
+
- Engineer Flow: `.agent/skills/flow_engineer/SKILL.md`
|
|
259
|
+
- Reviewer Flow: `.agent/skills/flow_reviewer/SKILL.md`
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: monoco_workflow_agent_reviewer
|
|
3
|
+
description: Reviewer 角色的标准化工作流 (Flow Skill)。定义从代码检出、对抗性测试到评审完成的标准操作流程,确保代码质量和流程合规。
|
|
4
|
+
type: workflow
|
|
5
|
+
role: reviewer
|
|
6
|
+
version: 1.1.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Reviewer Flow
|
|
10
|
+
|
|
11
|
+
Reviewer 角色的标准化工作流,确保 "Checkout → Verify → Challenge → Review → Decide → Cleanup" 流程。核心理念是**双层防御体系**:Engineer 负责自证 (Verify),Reviewer 负责对抗 (Challenge)。
|
|
12
|
+
|
|
13
|
+
## 工作流状态机
|
|
14
|
+
|
|
15
|
+
```mermaid
|
|
16
|
+
stateDiagram-v2
|
|
17
|
+
[*] --> Checkout: 收到评审请求
|
|
18
|
+
|
|
19
|
+
Checkout --> Verify: 检出完成
|
|
20
|
+
Checkout --> Checkout: 检出失败<br/>(环境检查)
|
|
21
|
+
|
|
22
|
+
Verify --> Challenge: 现有测试通过
|
|
23
|
+
Verify --> Verify: 现有测试失败<br/>(记录问题)
|
|
24
|
+
|
|
25
|
+
Challenge --> Review: 对抗测试完成
|
|
26
|
+
Challenge --> Reject: 发现致命漏洞
|
|
27
|
+
|
|
28
|
+
Review --> Approve: 代码 & 架构 OK
|
|
29
|
+
Review --> Reject: 发现质量问题
|
|
30
|
+
|
|
31
|
+
Reject --> Checkout: 修复后重审
|
|
32
|
+
|
|
33
|
+
Approve --> Cleanup: 批准
|
|
34
|
+
|
|
35
|
+
Cleanup --> [*]: 清理完成
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 执行步骤
|
|
39
|
+
|
|
40
|
+
### 1. Checkout (检出)
|
|
41
|
+
|
|
42
|
+
- **目标**: 获取待评审的代码
|
|
43
|
+
- **检查点**:
|
|
44
|
+
- [ ] 检出 PR/Branch
|
|
45
|
+
- [ ] 确认与 Base 分支的差异
|
|
46
|
+
- [ ] 检查环境配置
|
|
47
|
+
|
|
48
|
+
### 2. Verify (验证)
|
|
49
|
+
|
|
50
|
+
- **目标**: 验证 Engineer 提交的功能正确性和测试覆盖 (White-box)
|
|
51
|
+
- **检查点**:
|
|
52
|
+
- [ ] 运行 **Engineer 编写的** 单元测试
|
|
53
|
+
- [ ] 运行集成测试 (如适用)
|
|
54
|
+
- [ ] 检查测试覆盖率报告
|
|
55
|
+
- [ ] **决策**: 如果现有测试失败,直接进入 `Reject` 流程。
|
|
56
|
+
|
|
57
|
+
### 3. Challenge (对抗测试)
|
|
58
|
+
|
|
59
|
+
- **目标**: 尝试破坏代码,寻找边界情况和安全漏洞 (Black-box / Edge Cases)
|
|
60
|
+
- **思维模式**: "Try to break it"
|
|
61
|
+
- **操作**:
|
|
62
|
+
1. 分析代码逻辑,寻找 Engineer 视角的盲区(并发、大/小数值、注入攻击等)。
|
|
63
|
+
2. 编写新的 **Challenge Test Cases**。
|
|
64
|
+
3. 运行这些新测试。
|
|
65
|
+
- **检查点**:
|
|
66
|
+
- [ ] **漏洞发现**: 如果新测试导致 Crash 或逻辑错误 -> **Reject** (并将测试用例作为反馈)。
|
|
67
|
+
- [ ] **鲁棒性验证**: 如果新测试通过 -> **保留测试用例** (提交到代码库) 并进入下一步。
|
|
68
|
+
|
|
69
|
+
### 4. Review (代码审查)
|
|
70
|
+
|
|
71
|
+
- **目标**: 检查代码质量、架构设计和可维护性
|
|
72
|
+
- **检查清单**:
|
|
73
|
+
- [ ] **功能**: 代码是否实现了需求?
|
|
74
|
+
- [ ] **设计**: 架构是否合理?是否遵循 KISS 原则?
|
|
75
|
+
- [ ] **可读性**: 命名和注释是否清晰?
|
|
76
|
+
- [ ] **文档**: 文档是否同步更新?
|
|
77
|
+
- [ ] **合规**: 是否遵循项目 Lint 规范?
|
|
78
|
+
|
|
79
|
+
### 5. Decide (决策)
|
|
80
|
+
|
|
81
|
+
- **目标**: 做出批准或拒绝的决定
|
|
82
|
+
- **选项**:
|
|
83
|
+
- **Approve**: 代码健壮且符合规范 (包含所有通过的 Challenge Tests)
|
|
84
|
+
- **Reject**: 需要修改,提供具体反馈 (附带失败的 Test Case 或 Log)
|
|
85
|
+
- **Request Changes**: 小问题,可快速修复
|
|
86
|
+
|
|
87
|
+
### 6. Cleanup (清理)
|
|
88
|
+
|
|
89
|
+
- **目标**: 完成评审后的环境清理
|
|
90
|
+
- **检查点**:
|
|
91
|
+
- [ ] 提交新增的测试用例 (如有)
|
|
92
|
+
- [ ] 删除本地临时分支
|
|
93
|
+
- [ ] 更新 Issue 状态
|
|
94
|
+
- [ ] 记录评审意见到 Review Comments
|
|
95
|
+
|
|
96
|
+
## 决策分支
|
|
97
|
+
|
|
98
|
+
| 条件 | 动作 |
|
|
99
|
+
| ------------------------- | --------------------------------------- |
|
|
100
|
+
| 现有测试 (Verify) 失败 | Reject,要求 Engineer 修复 |
|
|
101
|
+
| 对抗测试 (Challenge) 崩溃 | Reject,提交该测试用例证明漏洞 |
|
|
102
|
+
| 代码风格问题 | Request Changes 或提供建议 |
|
|
103
|
+
| 设计问题 | Reject,要求重新设计 |
|
|
104
|
+
| 一切正常 | Approve,并合并价值高的 Challenge Tests |
|
|
105
|
+
|
|
106
|
+
## 评审意见模板
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
## Review Comments
|
|
110
|
+
|
|
111
|
+
### 🛡️ Challenge Reports
|
|
112
|
+
|
|
113
|
+
- [Pass/Fail] Test Case: `test_concurrency_limit`
|
|
114
|
+
- [Pass/Fail] Test Case: `test_invalid_inputs`
|
|
115
|
+
|
|
116
|
+
### ✅ 优点
|
|
117
|
+
|
|
118
|
+
-
|
|
119
|
+
|
|
120
|
+
### ⚠️ 建议
|
|
121
|
+
|
|
122
|
+
-
|
|
123
|
+
|
|
124
|
+
### ❌ 必须修改
|
|
125
|
+
|
|
126
|
+
-
|
|
127
|
+
|
|
128
|
+
### 📝 其他
|
|
129
|
+
|
|
130
|
+
-
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## 合规要求
|
|
134
|
+
|
|
135
|
+
- **必须**: 先通过 Engineer 的测试 (Verify),再进行对抗测试 (Challenge)
|
|
136
|
+
- **必须**: 试图编写至少一个边界测试用例
|
|
137
|
+
- **禁止**: 未经测试直接 Approve
|
monoco/features/agent/session.py
CHANGED
|
@@ -25,6 +25,7 @@ class Session(BaseModel):
|
|
|
25
25
|
branch_name: str = Field(
|
|
26
26
|
..., description="Git branch name associated with this session"
|
|
27
27
|
)
|
|
28
|
+
pid: Optional[int] = Field(default=None, description="Process ID of the worker")
|
|
28
29
|
created_at: datetime = Field(default_factory=datetime.now)
|
|
29
30
|
updated_at: datetime = Field(default_factory=datetime.now)
|
|
30
31
|
# History could be a list of logs or pointers to git commits
|
|
@@ -37,22 +38,33 @@ class RuntimeSession:
|
|
|
37
38
|
"""
|
|
38
39
|
|
|
39
40
|
def __init__(
|
|
40
|
-
self,
|
|
41
|
-
session_model: Session,
|
|
42
|
-
worker: Worker,
|
|
41
|
+
self,
|
|
42
|
+
session_model: Session,
|
|
43
|
+
worker: Optional[Worker],
|
|
43
44
|
hook_registry: Optional[HookRegistry] = None,
|
|
44
45
|
project_root: Optional[Path] = None,
|
|
46
|
+
save_callback: Optional[callable] = None,
|
|
45
47
|
):
|
|
46
48
|
self.model = session_model
|
|
47
49
|
self.worker = worker
|
|
48
50
|
self.hook_registry = hook_registry or get_registry()
|
|
49
51
|
self.project_root = project_root or find_monoco_root()
|
|
52
|
+
self.save_callback = save_callback
|
|
53
|
+
|
|
54
|
+
def _save(self):
|
|
55
|
+
if self.save_callback:
|
|
56
|
+
self.save_callback(self.model)
|
|
50
57
|
|
|
51
58
|
def _create_hook_context(self) -> HookContext:
|
|
52
59
|
"""Create a HookContext from the current session state."""
|
|
53
60
|
return HookContext.from_runtime_session(self, self.project_root)
|
|
54
61
|
|
|
55
62
|
def start(self, context: Optional[dict] = None):
|
|
63
|
+
if not self.worker:
|
|
64
|
+
raise RuntimeError(
|
|
65
|
+
"Cannot start session in observer mode (no worker attached)"
|
|
66
|
+
)
|
|
67
|
+
|
|
56
68
|
print(
|
|
57
69
|
f"Session {self.model.id}: Starting worker on branch {self.model.branch_name}"
|
|
58
70
|
)
|
|
@@ -64,50 +76,83 @@ class RuntimeSession:
|
|
|
64
76
|
# Execute on_session_start hooks
|
|
65
77
|
hook_context = self._create_hook_context()
|
|
66
78
|
self.hook_registry.execute_on_session_start(hook_context)
|
|
67
|
-
|
|
79
|
+
|
|
68
80
|
self.worker.start(context)
|
|
69
81
|
# Async mode: we assume it started running.
|
|
70
82
|
# Use poll or refresh_status to check later.
|
|
71
83
|
self.model.status = "running"
|
|
84
|
+
self.model.pid = self.worker.process_id
|
|
72
85
|
except Exception:
|
|
73
86
|
self.model.status = "failed"
|
|
74
87
|
raise
|
|
75
88
|
finally:
|
|
76
89
|
self.model.updated_at = datetime.now()
|
|
90
|
+
self._save()
|
|
77
91
|
|
|
78
92
|
def refresh_status(self) -> str:
|
|
79
93
|
"""
|
|
80
94
|
Polls the worker and updates the session model status.
|
|
81
95
|
"""
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
if self.worker:
|
|
97
|
+
worker_status = self.worker.poll()
|
|
98
|
+
self.model.status = worker_status
|
|
99
|
+
else:
|
|
100
|
+
# Observer mode
|
|
101
|
+
if self.model.pid:
|
|
102
|
+
try:
|
|
103
|
+
import os
|
|
104
|
+
|
|
105
|
+
# Check if process exists.
|
|
106
|
+
# kill(pid, 0) does not send a signal but raises OSError if pid missing
|
|
107
|
+
os.kill(self.model.pid, 0)
|
|
108
|
+
# If we are here, process exists. We assume running if it was running.
|
|
109
|
+
# We can't detect "suspended" easily without psutil.
|
|
110
|
+
if self.model.status == "terminated":
|
|
111
|
+
# If we thought it was terminated but it's alive, maybe update?
|
|
112
|
+
# Or keep as terminated? Let's assume running if found.
|
|
113
|
+
pass
|
|
114
|
+
except OSError:
|
|
115
|
+
self.model.status = "terminated"
|
|
116
|
+
else:
|
|
117
|
+
self.model.status = "terminated"
|
|
118
|
+
|
|
84
119
|
self.model.updated_at = datetime.now()
|
|
85
|
-
|
|
120
|
+
self._save()
|
|
121
|
+
return self.model.status
|
|
86
122
|
|
|
87
123
|
def suspend(self):
|
|
124
|
+
if not self.worker:
|
|
125
|
+
raise RuntimeError("Cannot suspend session in observer mode")
|
|
126
|
+
|
|
88
127
|
print(f"Session {self.model.id}: Suspending worker")
|
|
89
128
|
self.worker.stop()
|
|
90
129
|
self.model.status = "suspended"
|
|
91
130
|
self.model.updated_at = datetime.now()
|
|
131
|
+
self._save()
|
|
92
132
|
# In real impl, ensure git commit of current state?
|
|
93
133
|
|
|
94
134
|
def resume(self):
|
|
135
|
+
if not self.worker:
|
|
136
|
+
raise RuntimeError("Cannot resume session in observer mode")
|
|
137
|
+
|
|
95
138
|
print(f"Session {self.model.id}: Resuming worker")
|
|
96
139
|
self.worker.start() # In real impl, might need to re-init process
|
|
97
140
|
|
|
98
141
|
# Async mode: assume running
|
|
99
142
|
self.model.status = "running"
|
|
143
|
+
self.model.pid = self.worker.process_id
|
|
100
144
|
self.model.updated_at = datetime.now()
|
|
145
|
+
self._save()
|
|
101
146
|
|
|
102
147
|
def terminate(self):
|
|
103
148
|
print(f"Session {self.model.id}: Terminating")
|
|
104
|
-
|
|
149
|
+
|
|
105
150
|
# Execute on_session_end hooks before stopping worker
|
|
106
151
|
# This allows hooks to perform cleanup while session context is still valid
|
|
107
152
|
try:
|
|
108
153
|
hook_context = self._create_hook_context()
|
|
109
154
|
results = self.hook_registry.execute_on_session_end(hook_context)
|
|
110
|
-
|
|
155
|
+
|
|
111
156
|
# Log hook results
|
|
112
157
|
for result in results:
|
|
113
158
|
if result.status == "failure":
|
|
@@ -115,7 +160,10 @@ class RuntimeSession:
|
|
|
115
160
|
except Exception as e:
|
|
116
161
|
# Don't let hook errors prevent session termination
|
|
117
162
|
print(f" Hook execution error: {e}")
|
|
118
|
-
|
|
119
|
-
self.worker
|
|
163
|
+
|
|
164
|
+
if self.worker:
|
|
165
|
+
self.worker.stop()
|
|
166
|
+
|
|
120
167
|
self.model.status = "terminated"
|
|
121
168
|
self.model.updated_at = datetime.now()
|
|
169
|
+
self._save()
|
monoco/features/agent/worker.py
CHANGED
|
@@ -8,12 +8,14 @@ class Worker:
|
|
|
8
8
|
Represents an active or pending agent session assigned to a specific role and issue.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
def __init__(self, role: RoleTemplate, issue_id: str):
|
|
11
|
+
def __init__(self, role: RoleTemplate, issue_id: str, timeout: Optional[int] = None):
|
|
12
12
|
self.role = role
|
|
13
13
|
self.issue_id = issue_id
|
|
14
|
+
self.timeout = timeout
|
|
14
15
|
self.status = "pending" # pending, running, suspended, terminated
|
|
15
16
|
self.process_id: Optional[int] = None
|
|
16
17
|
self._process = None
|
|
18
|
+
self.start_at: Optional[float] = None
|
|
17
19
|
|
|
18
20
|
def start(self, context: Optional[dict] = None):
|
|
19
21
|
"""
|
|
@@ -26,6 +28,8 @@ class Worker:
|
|
|
26
28
|
print(f"Starting worker {self.role.name} for issue {self.issue_id}")
|
|
27
29
|
|
|
28
30
|
try:
|
|
31
|
+
import time
|
|
32
|
+
self.start_at = time.time()
|
|
29
33
|
self._execute_work(context)
|
|
30
34
|
self.status = "running"
|
|
31
35
|
except Exception as e:
|
|
@@ -97,6 +101,23 @@ class Worker:
|
|
|
97
101
|
if not self._process:
|
|
98
102
|
return self.status
|
|
99
103
|
|
|
104
|
+
# Check timeout
|
|
105
|
+
if (
|
|
106
|
+
self.status == "running"
|
|
107
|
+
and self.timeout
|
|
108
|
+
and self.start_at
|
|
109
|
+
):
|
|
110
|
+
import time
|
|
111
|
+
|
|
112
|
+
elapsed = time.time() - self.start_at
|
|
113
|
+
if elapsed > self.timeout:
|
|
114
|
+
print(
|
|
115
|
+
f"\n[{self.role.name}] [bold red]Timeout exceeded[/bold red] ({self.timeout}s). Terminating process..."
|
|
116
|
+
)
|
|
117
|
+
self.stop()
|
|
118
|
+
self.status = "timeout"
|
|
119
|
+
return self.status
|
|
120
|
+
|
|
100
121
|
returncode = self._process.poll()
|
|
101
122
|
if returncode is None:
|
|
102
123
|
return "running"
|
|
@@ -118,14 +139,29 @@ class Worker:
|
|
|
118
139
|
|
|
119
140
|
def stop(self):
|
|
120
141
|
"""
|
|
121
|
-
Stop the worker session.
|
|
142
|
+
Stop the worker session and kill the process if running.
|
|
122
143
|
"""
|
|
123
144
|
if self.status == "terminated":
|
|
124
145
|
return
|
|
125
146
|
|
|
126
147
|
print(f"Stopping worker {self.role.name} for issue {self.issue_id}")
|
|
148
|
+
|
|
149
|
+
if self._process:
|
|
150
|
+
try:
|
|
151
|
+
# Try graceful termination
|
|
152
|
+
self._process.terminate()
|
|
153
|
+
# Wait a bit
|
|
154
|
+
try:
|
|
155
|
+
self._process.wait(timeout=2)
|
|
156
|
+
except Exception:
|
|
157
|
+
# Force kill if still running
|
|
158
|
+
self._process.kill()
|
|
159
|
+
except Exception as e:
|
|
160
|
+
print(f"Error stopping process: {e}")
|
|
161
|
+
|
|
127
162
|
self.status = "terminated"
|
|
128
163
|
self.process_id = None
|
|
164
|
+
self._process = None
|
|
129
165
|
|
|
130
166
|
def __repr__(self):
|
|
131
167
|
return (
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Dict
|
|
3
|
+
from monoco.core.loader import FeatureModule, FeatureMetadata
|
|
4
|
+
from monoco.core.feature import IntegrationData
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ArtifactFeature(FeatureModule):
|
|
8
|
+
"""Artifact management feature module."""
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def metadata(self) -> FeatureMetadata:
|
|
12
|
+
return FeatureMetadata(
|
|
13
|
+
name="artifact",
|
|
14
|
+
version="1.0.0",
|
|
15
|
+
description="Artifact management system for Monoco",
|
|
16
|
+
dependencies=["core"],
|
|
17
|
+
priority=20,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def integrate(self, root: Path, config: Dict) -> IntegrationData:
|
|
21
|
+
"""Provide integration data for agent environment."""
|
|
22
|
+
lang = config.get("i18n", {}).get("source_lang", "zh")
|
|
23
|
+
base_dir = Path(__file__).parent / "resources"
|
|
24
|
+
prompt_file = base_dir / lang / "AGENTS.md"
|
|
25
|
+
|
|
26
|
+
if not prompt_file.exists():
|
|
27
|
+
prompt_file = base_dir / "en" / "AGENTS.md"
|
|
28
|
+
|
|
29
|
+
content = ""
|
|
30
|
+
if prompt_file.exists():
|
|
31
|
+
content = prompt_file.read_text(encoding="utf-8").strip()
|
|
32
|
+
|
|
33
|
+
return IntegrationData(system_prompts={"Artifacts & Mailroom": content})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Artifacts & Mailroom
|
|
2
|
+
|
|
3
|
+
Monoco Artifacts 系统提供了多模态产物的生命周期管理能力,包括:
|
|
4
|
+
|
|
5
|
+
1. **内容寻址存储 (CAS)**: 所有产物存储在全局池 `~/.monoco/artifacts` 中,基于内容的 SHA256 哈希值进行寻址和去重。
|
|
6
|
+
2. **自动化摄取 (Mailroom)**: 通过监听 `.monoco/dropzone/` 目录,自动触发文档(Office, PDF 等)到 WebP 的转换流程。
|
|
7
|
+
3. **环境追踪**: 自动探测系统中的 `LibreOffice`, `PyMuPDF` 等工具链。
|
|
8
|
+
4. **元数据管理**: 项目本地维护 `manifest.jsonl`,记录所有产物的类型、哈希及创建时间。
|
|
9
|
+
|
|
10
|
+
### 常用操作建议
|
|
11
|
+
|
|
12
|
+
- **上传文档**: 建议将原始文档放入 `.monoco/dropzone/`,等待 Mailroom 自动完成转换并注册为 Artifact。
|
|
13
|
+
- **查看产物**: 检查 `.monoco/artifacts/manifest.jsonl` 获取当前可用的产物列表。
|
|
14
|
+
- **引用产物**: 在多模态分析时,可以使用产物的 ID 或本地软链接路径。
|