opencode-collaboration 2.0.0__py3-none-any.whl → 2.1.0__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.
- {opencode_collaboration-2.0.0.dist-info → opencode_collaboration-2.1.0.dist-info}/METADATA +1 -1
- {opencode_collaboration-2.0.0.dist-info → opencode_collaboration-2.1.0.dist-info}/RECORD +14 -6
- src/core/config_reloader.py +257 -0
- src/core/design_review_notifier.py +303 -0
- src/core/error_templates.py +208 -0
- src/core/exception_handler.py +217 -2
- src/core/git_workflow_enforcer.py +352 -0
- src/core/iteration_status_manager.py +290 -0
- src/core/monitor.py +268 -0
- src/core/state_migrator.py +404 -0
- src/core/state_validator.py +564 -0
- {opencode_collaboration-2.0.0.dist-info → opencode_collaboration-2.1.0.dist-info}/WHEEL +0 -0
- {opencode_collaboration-2.0.0.dist-info → opencode_collaboration-2.1.0.dist-info}/entry_points.txt +0 -0
- {opencode_collaboration-2.0.0.dist-info → opencode_collaboration-2.1.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
"""State 结构验证器。
|
|
2
|
+
|
|
3
|
+
功能:
|
|
4
|
+
1. 验证 project_state.yaml 的结构是否符合 Schema
|
|
5
|
+
2. 检测 State 文件格式与代码期望是否兼容
|
|
6
|
+
3. 提供详细的验证错误信息
|
|
7
|
+
"""
|
|
8
|
+
from typing import Dict, List, Any, Optional, Union
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ValidationLevel(Enum):
|
|
18
|
+
"""验证级别。"""
|
|
19
|
+
ERROR = "error"
|
|
20
|
+
WARNING = "warning"
|
|
21
|
+
INFO = "info"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ValidationResult:
|
|
25
|
+
"""验证结果。"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
level: ValidationLevel,
|
|
30
|
+
field: str,
|
|
31
|
+
message: str,
|
|
32
|
+
suggestion: str = ""
|
|
33
|
+
):
|
|
34
|
+
self.level = level
|
|
35
|
+
self.field = field
|
|
36
|
+
self.message = message
|
|
37
|
+
self.suggestion = suggestion
|
|
38
|
+
|
|
39
|
+
def __str__(self):
|
|
40
|
+
result = f"[{self.level.value.upper()}] {self.field}: {self.message}"
|
|
41
|
+
if self.suggestion:
|
|
42
|
+
result += f"\n 💡 {self.suggestion}"
|
|
43
|
+
return result
|
|
44
|
+
|
|
45
|
+
def to_dict(self) -> Dict:
|
|
46
|
+
"""转换为字典。"""
|
|
47
|
+
return {
|
|
48
|
+
"level": self.level.value,
|
|
49
|
+
"field": self.field,
|
|
50
|
+
"message": self.message,
|
|
51
|
+
"suggestion": self.suggestion
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class StateValidator:
|
|
56
|
+
"""State 结构验证器。"""
|
|
57
|
+
|
|
58
|
+
# Schema 定义
|
|
59
|
+
SCHEMA = {
|
|
60
|
+
"version": {
|
|
61
|
+
"type": str,
|
|
62
|
+
"required": True,
|
|
63
|
+
"pattern": r"^\d+\.\d+\.\d+$",
|
|
64
|
+
"error_message": "version 格式不正确,期望格式: X.Y.Z"
|
|
65
|
+
},
|
|
66
|
+
"project": {
|
|
67
|
+
"type": dict,
|
|
68
|
+
"required": True,
|
|
69
|
+
"fields": {
|
|
70
|
+
"name": {
|
|
71
|
+
"type": str,
|
|
72
|
+
"required": True,
|
|
73
|
+
"error_message": "project.name 缺失"
|
|
74
|
+
},
|
|
75
|
+
"type": {
|
|
76
|
+
"type": str,
|
|
77
|
+
"required": True,
|
|
78
|
+
"error_message": "project.type 缺失"
|
|
79
|
+
},
|
|
80
|
+
"phase": {
|
|
81
|
+
"type": str,
|
|
82
|
+
"required": True,
|
|
83
|
+
"enum": ["unknown", "requirements", "design",
|
|
84
|
+
"development", "testing", "deployment",
|
|
85
|
+
"completed"],
|
|
86
|
+
"error_message": "project.phase 值无效"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"requirements": {
|
|
91
|
+
"type": [dict, list],
|
|
92
|
+
"required": True,
|
|
93
|
+
"error_message": "requirements 字段格式不正确"
|
|
94
|
+
},
|
|
95
|
+
"design": {
|
|
96
|
+
"type": [dict, list],
|
|
97
|
+
"required": True,
|
|
98
|
+
"error_message": "design 字段格式不正确"
|
|
99
|
+
},
|
|
100
|
+
"test": {
|
|
101
|
+
"type": dict,
|
|
102
|
+
"required": True,
|
|
103
|
+
"fields": {
|
|
104
|
+
"status": {
|
|
105
|
+
"type": str,
|
|
106
|
+
"enum": ["pending", "in_progress", "passed", "failed"],
|
|
107
|
+
"error_message": "test.status 值无效"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"development": {
|
|
112
|
+
"type": dict,
|
|
113
|
+
"required": True,
|
|
114
|
+
"fields": {
|
|
115
|
+
"status": {
|
|
116
|
+
"type": str,
|
|
117
|
+
"enum": ["pending", "in_progress", "completed"],
|
|
118
|
+
"error_message": "development.status 值无效"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"deployment": {
|
|
123
|
+
"type": dict,
|
|
124
|
+
"required": True,
|
|
125
|
+
"fields": {
|
|
126
|
+
"status": {
|
|
127
|
+
"type": str,
|
|
128
|
+
"enum": ["pending", "in_progress", "released"],
|
|
129
|
+
"error_message": "deployment.status 值无效"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
"iteration": {
|
|
134
|
+
"type": dict,
|
|
135
|
+
"required": False,
|
|
136
|
+
"fields": {
|
|
137
|
+
"current": {"type": str, "required": False},
|
|
138
|
+
"status": {"type": str, "required": False}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"iterations": {
|
|
142
|
+
"type": dict,
|
|
143
|
+
"required": False,
|
|
144
|
+
"error_message": "iterations 应该是字典格式"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
def __init__(self, strict_mode: bool = False):
|
|
149
|
+
"""初始化验证器。
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
strict_mode: 严格模式,更多验证
|
|
153
|
+
"""
|
|
154
|
+
self.strict_mode = strict_mode
|
|
155
|
+
self.results: List[ValidationResult] = []
|
|
156
|
+
self._validated = False
|
|
157
|
+
|
|
158
|
+
def validate(self, state: Dict[str, Any]) -> List[ValidationResult]:
|
|
159
|
+
"""验证 State 结构。
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
state: State 字典
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
验证结果列表
|
|
166
|
+
"""
|
|
167
|
+
self.results = []
|
|
168
|
+
self._validated = True
|
|
169
|
+
|
|
170
|
+
if not isinstance(state, dict):
|
|
171
|
+
self.results.append(ValidationResult(
|
|
172
|
+
level=ValidationLevel.ERROR,
|
|
173
|
+
field="root",
|
|
174
|
+
message="State 应该是字典格式",
|
|
175
|
+
suggestion="检查 project_state.yaml 文件格式是否正确"
|
|
176
|
+
))
|
|
177
|
+
return self.results
|
|
178
|
+
|
|
179
|
+
# 验证 version
|
|
180
|
+
self._validate_version(state)
|
|
181
|
+
|
|
182
|
+
# 验证 project
|
|
183
|
+
self._validate_project(state)
|
|
184
|
+
|
|
185
|
+
# 验证 requirements
|
|
186
|
+
self._validate_field("requirements", state)
|
|
187
|
+
|
|
188
|
+
# 验证 design
|
|
189
|
+
self._validate_design(state)
|
|
190
|
+
|
|
191
|
+
# 验证 test
|
|
192
|
+
self._validate_test(state)
|
|
193
|
+
|
|
194
|
+
# 验证 development
|
|
195
|
+
self._validate_development(state)
|
|
196
|
+
|
|
197
|
+
# 验证 deployment
|
|
198
|
+
self._validate_deployment(state)
|
|
199
|
+
|
|
200
|
+
# 验证 iteration
|
|
201
|
+
if "iteration" in state:
|
|
202
|
+
self._validate_iteration(state)
|
|
203
|
+
|
|
204
|
+
return self.results
|
|
205
|
+
|
|
206
|
+
def _validate_version(self, state: Dict[str, Any]):
|
|
207
|
+
"""验证 version 字段。"""
|
|
208
|
+
if "version" not in state:
|
|
209
|
+
self.results.append(ValidationResult(
|
|
210
|
+
level=ValidationLevel.ERROR,
|
|
211
|
+
field="version",
|
|
212
|
+
message="version 字段缺失",
|
|
213
|
+
suggestion="在 state 文件开头添加 version: X.Y.Z"
|
|
214
|
+
))
|
|
215
|
+
return
|
|
216
|
+
|
|
217
|
+
version = state["version"]
|
|
218
|
+
|
|
219
|
+
if not isinstance(version, str):
|
|
220
|
+
self.results.append(ValidationResult(
|
|
221
|
+
level=ValidationLevel.ERROR,
|
|
222
|
+
field="version",
|
|
223
|
+
message=f"version 应该是字符串,实际: {type(version)}"
|
|
224
|
+
))
|
|
225
|
+
return
|
|
226
|
+
|
|
227
|
+
import re
|
|
228
|
+
if not re.match(r"^\d+\.\d+\.\d+$", version):
|
|
229
|
+
self.results.append(ValidationResult(
|
|
230
|
+
level=ValidationLevel.ERROR,
|
|
231
|
+
field="version",
|
|
232
|
+
message=f"version 格式不正确: {version}",
|
|
233
|
+
suggestion="期望格式: X.Y.Z (例如: 2.0.0 或 2.1.0)"
|
|
234
|
+
))
|
|
235
|
+
|
|
236
|
+
def _validate_project(self, state: Dict[str, Any]):
|
|
237
|
+
"""验证 project 字段。"""
|
|
238
|
+
if "project" not in state:
|
|
239
|
+
self.results.append(ValidationResult(
|
|
240
|
+
level=ValidationLevel.ERROR,
|
|
241
|
+
field="project",
|
|
242
|
+
message="project 字段缺失",
|
|
243
|
+
suggestion="添加 project 字段,包含 name、type、phase"
|
|
244
|
+
))
|
|
245
|
+
return
|
|
246
|
+
|
|
247
|
+
project = state["project"]
|
|
248
|
+
|
|
249
|
+
if not isinstance(project, dict):
|
|
250
|
+
self.results.append(ValidationResult(
|
|
251
|
+
level=ValidationLevel.ERROR,
|
|
252
|
+
field="project",
|
|
253
|
+
message=f"project 应该是字典格式,实际: {type(project)}"
|
|
254
|
+
))
|
|
255
|
+
return
|
|
256
|
+
|
|
257
|
+
# 验证 project.name
|
|
258
|
+
if "name" not in project:
|
|
259
|
+
self.results.append(ValidationResult(
|
|
260
|
+
level=ValidationLevel.WARNING,
|
|
261
|
+
field="project.name",
|
|
262
|
+
message="project.name 缺失",
|
|
263
|
+
suggestion="添加项目名称"
|
|
264
|
+
))
|
|
265
|
+
|
|
266
|
+
# 验证 project.phase
|
|
267
|
+
if "phase" not in project:
|
|
268
|
+
# 检查是否在根级
|
|
269
|
+
if "phase" in state:
|
|
270
|
+
self.results.append(ValidationResult(
|
|
271
|
+
level=ValidationLevel.WARNING,
|
|
272
|
+
field="project.phase",
|
|
273
|
+
message="phase 在根级而非 project.phase",
|
|
274
|
+
suggestion="考虑迁移 phase 到 project.phase"
|
|
275
|
+
))
|
|
276
|
+
else:
|
|
277
|
+
self.results.append(ValidationResult(
|
|
278
|
+
level=ValidationLevel.ERROR,
|
|
279
|
+
field="project.phase",
|
|
280
|
+
message="project.phase 缺失"
|
|
281
|
+
))
|
|
282
|
+
else:
|
|
283
|
+
valid_phases = ["unknown", "requirements", "design",
|
|
284
|
+
"development", "testing", "deployment", "completed"]
|
|
285
|
+
if project["phase"] not in valid_phases:
|
|
286
|
+
self.results.append(ValidationResult(
|
|
287
|
+
level=ValidationLevel.ERROR,
|
|
288
|
+
field="project.phase",
|
|
289
|
+
message=f"无效的 phase 值: {project['phase']}",
|
|
290
|
+
suggestion=f"有效值: {valid_phases}"
|
|
291
|
+
))
|
|
292
|
+
|
|
293
|
+
def _validate_field(self, field_name: str, state: Dict[str, Any]):
|
|
294
|
+
"""验证通用字段。"""
|
|
295
|
+
schema = self.SCHEMA.get(field_name, {})
|
|
296
|
+
|
|
297
|
+
if field_name not in state:
|
|
298
|
+
if schema.get("required", False):
|
|
299
|
+
self.results.append(ValidationResult(
|
|
300
|
+
level=ValidationLevel.ERROR,
|
|
301
|
+
field=field_name,
|
|
302
|
+
message=f"{field_name} 字段缺失"
|
|
303
|
+
))
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
value = state[field_name]
|
|
307
|
+
expected_types = schema.get("type", dict)
|
|
308
|
+
|
|
309
|
+
if isinstance(expected_types, list):
|
|
310
|
+
if not any(isinstance(value, t) for t in expected_types):
|
|
311
|
+
self.results.append(ValidationResult(
|
|
312
|
+
level=ValidationLevel.ERROR,
|
|
313
|
+
field=field_name,
|
|
314
|
+
message=f"{field_name} 类型错误,期望: {expected_types},实际: {type(value)}"
|
|
315
|
+
))
|
|
316
|
+
elif not isinstance(value, expected_types):
|
|
317
|
+
self.results.append(ValidationResult(
|
|
318
|
+
level=ValidationLevel.ERROR,
|
|
319
|
+
field=field_name,
|
|
320
|
+
message=f"{field_name} 类型错误,期望: {expected_types},实际: {type(value)}"
|
|
321
|
+
))
|
|
322
|
+
|
|
323
|
+
def _validate_design(self, state: Dict[str, Any]):
|
|
324
|
+
"""验证 design 字段(处理列表和字典两种格式)。"""
|
|
325
|
+
if "design" not in state:
|
|
326
|
+
self.results.append(ValidationResult(
|
|
327
|
+
level=ValidationLevel.ERROR,
|
|
328
|
+
field="design",
|
|
329
|
+
message="design 字段缺失"
|
|
330
|
+
))
|
|
331
|
+
return
|
|
332
|
+
|
|
333
|
+
design = state["design"]
|
|
334
|
+
|
|
335
|
+
# 列表格式
|
|
336
|
+
if isinstance(design, list):
|
|
337
|
+
for i, item in enumerate(design):
|
|
338
|
+
if isinstance(item, dict):
|
|
339
|
+
if not item.get("version"):
|
|
340
|
+
self.results.append(ValidationResult(
|
|
341
|
+
level=ValidationLevel.WARNING,
|
|
342
|
+
field=f"design[{i}].version",
|
|
343
|
+
message="设计文档缺少 version 字段"
|
|
344
|
+
))
|
|
345
|
+
# 字典格式
|
|
346
|
+
elif isinstance(design, dict):
|
|
347
|
+
self.results.append(ValidationResult(
|
|
348
|
+
level=ValidationLevel.WARNING,
|
|
349
|
+
field="design",
|
|
350
|
+
message="design 字段是字典格式,建议迁移到列表格式",
|
|
351
|
+
suggestion="使用 StateMigrator 迁移到列表格式"
|
|
352
|
+
))
|
|
353
|
+
|
|
354
|
+
def _validate_test(self, state: Dict[str, Any]):
|
|
355
|
+
"""验证 test 字段。"""
|
|
356
|
+
if "test" not in state:
|
|
357
|
+
self.results.append(ValidationResult(
|
|
358
|
+
level=ValidationLevel.ERROR,
|
|
359
|
+
field="test",
|
|
360
|
+
message="test 字段缺失"
|
|
361
|
+
))
|
|
362
|
+
return
|
|
363
|
+
|
|
364
|
+
test = state["test"]
|
|
365
|
+
|
|
366
|
+
if not isinstance(test, dict):
|
|
367
|
+
self.results.append(ValidationResult(
|
|
368
|
+
level=ValidationLevel.ERROR,
|
|
369
|
+
field="test",
|
|
370
|
+
message=f"test 应该是字典格式,实际: {type(test)}"
|
|
371
|
+
))
|
|
372
|
+
return
|
|
373
|
+
|
|
374
|
+
# 验证 status
|
|
375
|
+
if "status" in test:
|
|
376
|
+
valid_statuses = ["pending", "in_progress", "passed", "failed"]
|
|
377
|
+
if test["status"] not in valid_statuses:
|
|
378
|
+
self.results.append(ValidationResult(
|
|
379
|
+
level=ValidationLevel.ERROR,
|
|
380
|
+
field="test.status",
|
|
381
|
+
message=f"无效的 test.status: {test['status']}",
|
|
382
|
+
suggestion=f"有效值: {valid_statuses}"
|
|
383
|
+
))
|
|
384
|
+
|
|
385
|
+
def _validate_development(self, state: Dict[str, Any]):
|
|
386
|
+
"""验证 development 字段。"""
|
|
387
|
+
if "development" not in state:
|
|
388
|
+
self.results.append(ValidationResult(
|
|
389
|
+
level=ValidationLevel.ERROR,
|
|
390
|
+
field="development",
|
|
391
|
+
message="development 字段缺失"
|
|
392
|
+
))
|
|
393
|
+
return
|
|
394
|
+
|
|
395
|
+
dev = state["development"]
|
|
396
|
+
|
|
397
|
+
if not isinstance(dev, dict):
|
|
398
|
+
self.results.append(ValidationResult(
|
|
399
|
+
level=ValidationLevel.ERROR,
|
|
400
|
+
field="development",
|
|
401
|
+
message=f"development 应该是字典格式,实际: {type(dev)}"
|
|
402
|
+
))
|
|
403
|
+
return
|
|
404
|
+
|
|
405
|
+
def _validate_deployment(self, state: Dict[str, Any]):
|
|
406
|
+
"""验证 deployment 字段。"""
|
|
407
|
+
if "deployment" not in state:
|
|
408
|
+
self.results.append(ValidationResult(
|
|
409
|
+
level=ValidationLevel.ERROR,
|
|
410
|
+
field="deployment",
|
|
411
|
+
message="deployment 字段缺失"
|
|
412
|
+
))
|
|
413
|
+
return
|
|
414
|
+
|
|
415
|
+
deploy = state["deployment"]
|
|
416
|
+
|
|
417
|
+
if not isinstance(deploy, dict):
|
|
418
|
+
self.results.append(ValidationResult(
|
|
419
|
+
level=ValidationLevel.ERROR,
|
|
420
|
+
field="deployment",
|
|
421
|
+
message=f"deployment 应该是字典格式,实际: {type(deploy)}"
|
|
422
|
+
))
|
|
423
|
+
return
|
|
424
|
+
|
|
425
|
+
def _validate_iteration(self, state: Dict[str, Any]):
|
|
426
|
+
"""验证 iteration 字段。"""
|
|
427
|
+
iteration = state["iteration"]
|
|
428
|
+
|
|
429
|
+
if not isinstance(iteration, dict):
|
|
430
|
+
self.results.append(ValidationResult(
|
|
431
|
+
level=ValidationLevel.ERROR,
|
|
432
|
+
field="iteration",
|
|
433
|
+
message=f"iteration 应该是字典格式,实际: {type(iteration)}"
|
|
434
|
+
))
|
|
435
|
+
return
|
|
436
|
+
|
|
437
|
+
if "current" not in iteration:
|
|
438
|
+
self.results.append(ValidationResult(
|
|
439
|
+
level=ValidationLevel.WARNING,
|
|
440
|
+
field="iteration.current",
|
|
441
|
+
message="iteration.current 缺失"
|
|
442
|
+
))
|
|
443
|
+
|
|
444
|
+
def check_compatibility(self, state: Dict[str, Any]) -> List[ValidationResult]:
|
|
445
|
+
"""检测 State 文件格式与代码期望是否兼容。
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
state: State 字典
|
|
449
|
+
|
|
450
|
+
Returns:
|
|
451
|
+
兼容性问题列表
|
|
452
|
+
"""
|
|
453
|
+
issues = []
|
|
454
|
+
|
|
455
|
+
# 检测 design 字段类型
|
|
456
|
+
if "design" in state:
|
|
457
|
+
design = state["design"]
|
|
458
|
+
if isinstance(design, list):
|
|
459
|
+
issues.append(ValidationResult(
|
|
460
|
+
level=ValidationLevel.INFO,
|
|
461
|
+
field="design",
|
|
462
|
+
message="design 字段是列表格式",
|
|
463
|
+
suggestion="代码已兼容列表格式,无需修改"
|
|
464
|
+
))
|
|
465
|
+
elif isinstance(design, dict):
|
|
466
|
+
issues.append(ValidationResult(
|
|
467
|
+
level=ValidationLevel.WARNING,
|
|
468
|
+
field="design",
|
|
469
|
+
message="design 字段是字典格式,建议迁移到列表格式",
|
|
470
|
+
suggestion="使用 StateMigrator.migrate_v1_to_v2() 迁移"
|
|
471
|
+
))
|
|
472
|
+
|
|
473
|
+
# 检测 phase 位置
|
|
474
|
+
if "phase" in state:
|
|
475
|
+
issues.append(ValidationResult(
|
|
476
|
+
level=ValidationLevel.WARNING,
|
|
477
|
+
field="phase",
|
|
478
|
+
message="phase 在根级,建议迁移到 project.phase",
|
|
479
|
+
suggestion="使用 StateMigrator.migrate_v1_to_v2() 迁移"
|
|
480
|
+
))
|
|
481
|
+
|
|
482
|
+
return issues
|
|
483
|
+
|
|
484
|
+
def is_valid(self) -> bool:
|
|
485
|
+
"""检查是否有错误级别的验证结果。"""
|
|
486
|
+
if not self._validated:
|
|
487
|
+
return False
|
|
488
|
+
return not any(r.level == ValidationLevel.ERROR for r in self.results)
|
|
489
|
+
|
|
490
|
+
def get_errors(self) -> List[ValidationResult]:
|
|
491
|
+
"""获取所有错误级别的验证结果。"""
|
|
492
|
+
return [r for r in self.results if r.level == ValidationLevel.ERROR]
|
|
493
|
+
|
|
494
|
+
def get_warnings(self) -> List[ValidationResult]:
|
|
495
|
+
"""获取所有警告级别的验证结果。"""
|
|
496
|
+
return [r for r in self.results if r.level == ValidationLevel.WARNING]
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def validate_state_file(state_path: str) -> bool:
|
|
500
|
+
"""验证 State 文件。
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
state_path: State 文件路径
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
验证是否通过
|
|
507
|
+
"""
|
|
508
|
+
import yaml
|
|
509
|
+
|
|
510
|
+
with open(state_path, 'r') as f:
|
|
511
|
+
state = yaml.safe_load(f)
|
|
512
|
+
|
|
513
|
+
validator = StateValidator()
|
|
514
|
+
results = validator.validate(state)
|
|
515
|
+
|
|
516
|
+
# 输出验证结果
|
|
517
|
+
print("\n" + "=" * 50)
|
|
518
|
+
print("🔍 State 结构验证结果")
|
|
519
|
+
print("=" * 50)
|
|
520
|
+
|
|
521
|
+
if results:
|
|
522
|
+
for result in results:
|
|
523
|
+
print(f"\n{result}")
|
|
524
|
+
|
|
525
|
+
print("\n" + "-" * 50)
|
|
526
|
+
if validator.is_valid():
|
|
527
|
+
print("✅ 验证通过")
|
|
528
|
+
else:
|
|
529
|
+
print(f"❌ 验证失败,发现 {len(validator.get_errors())} 个错误")
|
|
530
|
+
else:
|
|
531
|
+
print("✅ State 结构有效")
|
|
532
|
+
|
|
533
|
+
print("=" * 50 + "\n")
|
|
534
|
+
|
|
535
|
+
return validator.is_valid()
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
if __name__ == "__main__":
|
|
539
|
+
import sys
|
|
540
|
+
|
|
541
|
+
if len(sys.argv) > 1:
|
|
542
|
+
validate_state_file(sys.argv[1])
|
|
543
|
+
else:
|
|
544
|
+
# 测试验证器
|
|
545
|
+
test_state = {
|
|
546
|
+
"version": "2.0.0",
|
|
547
|
+
"project": {
|
|
548
|
+
"name": "Test Project",
|
|
549
|
+
"type": "PYTHON",
|
|
550
|
+
"phase": "development"
|
|
551
|
+
},
|
|
552
|
+
"design": [{"version": "v1", "status": "completed"}],
|
|
553
|
+
"test": {"status": "pending"},
|
|
554
|
+
"development": {"status": "in_progress"},
|
|
555
|
+
"deployment": {"status": "pending"}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
validator = StateValidator()
|
|
559
|
+
results = validator.validate(test_state)
|
|
560
|
+
|
|
561
|
+
print("测试 State 验证:")
|
|
562
|
+
for r in results:
|
|
563
|
+
print(f" {r}")
|
|
564
|
+
print(f"\n是否有效: {validator.is_valid()}")
|
|
File without changes
|
{opencode_collaboration-2.0.0.dist-info → opencode_collaboration-2.1.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{opencode_collaboration-2.0.0.dist-info → opencode_collaboration-2.1.0.dist-info}/top_level.txt
RENAMED
|
File without changes
|