super-dev 2.0.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.
- super_dev/__init__.py +11 -0
- super_dev/analyzer/__init__.py +34 -0
- super_dev/analyzer/analyzer.py +440 -0
- super_dev/analyzer/detectors.py +511 -0
- super_dev/analyzer/models.py +285 -0
- super_dev/cli.py +3257 -0
- super_dev/config/__init__.py +11 -0
- super_dev/config/frontend.py +557 -0
- super_dev/config/manager.py +281 -0
- super_dev/creators/__init__.py +26 -0
- super_dev/creators/creator.py +134 -0
- super_dev/creators/document_generator.py +2473 -0
- super_dev/creators/frontend_builder.py +371 -0
- super_dev/creators/implementation_builder.py +789 -0
- super_dev/creators/prompt_generator.py +289 -0
- super_dev/creators/requirement_parser.py +354 -0
- super_dev/creators/spec_builder.py +195 -0
- super_dev/deployers/__init__.py +20 -0
- super_dev/deployers/cicd.py +1269 -0
- super_dev/deployers/delivery.py +229 -0
- super_dev/deployers/migration.py +1032 -0
- super_dev/design/__init__.py +74 -0
- super_dev/design/aesthetics.py +530 -0
- super_dev/design/charts.py +396 -0
- super_dev/design/codegen.py +379 -0
- super_dev/design/engine.py +528 -0
- super_dev/design/generator.py +395 -0
- super_dev/design/landing.py +422 -0
- super_dev/design/tech_stack.py +524 -0
- super_dev/design/tokens.py +269 -0
- super_dev/design/ux_guide.py +391 -0
- super_dev/exceptions.py +119 -0
- super_dev/experts/__init__.py +19 -0
- super_dev/experts/service.py +161 -0
- super_dev/integrations/__init__.py +7 -0
- super_dev/integrations/manager.py +264 -0
- super_dev/orchestrator/__init__.py +12 -0
- super_dev/orchestrator/engine.py +958 -0
- super_dev/orchestrator/experts.py +423 -0
- super_dev/orchestrator/knowledge.py +352 -0
- super_dev/orchestrator/quality.py +356 -0
- super_dev/reviewers/__init__.py +17 -0
- super_dev/reviewers/code_review.py +471 -0
- super_dev/reviewers/quality_gate.py +964 -0
- super_dev/reviewers/redteam.py +881 -0
- super_dev/skills/__init__.py +7 -0
- super_dev/skills/manager.py +307 -0
- super_dev/specs/__init__.py +44 -0
- super_dev/specs/generator.py +264 -0
- super_dev/specs/manager.py +428 -0
- super_dev/specs/models.py +348 -0
- super_dev/specs/validator.py +415 -0
- super_dev/utils/__init__.py +11 -0
- super_dev/utils/logger.py +133 -0
- super_dev/web/api.py +1402 -0
- super_dev-2.0.0.dist-info/METADATA +252 -0
- super_dev-2.0.0.dist-info/RECORD +61 -0
- super_dev-2.0.0.dist-info/WHEEL +5 -0
- super_dev-2.0.0.dist-info/entry_points.txt +2 -0
- super_dev-2.0.0.dist-info/licenses/LICENSE +21 -0
- super_dev-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"""
|
|
2
|
+
项目交付打包器
|
|
3
|
+
|
|
4
|
+
在流水线最后阶段收敛产物,输出交付清单、报告和压缩包。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from zipfile import ZIP_DEFLATED, ZipFile
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class ArtifactSpec:
|
|
18
|
+
"""交付物规则定义"""
|
|
19
|
+
|
|
20
|
+
path: Path
|
|
21
|
+
required: bool
|
|
22
|
+
reason: str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DeliveryPackager:
|
|
26
|
+
"""交付包生成器"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, project_dir: Path, name: str, version: str = "2.0.0"):
|
|
29
|
+
self.project_dir = Path(project_dir).resolve()
|
|
30
|
+
self.name = name
|
|
31
|
+
self.version = version
|
|
32
|
+
|
|
33
|
+
def package(self, cicd_platform: str = "all") -> dict[str, object]:
|
|
34
|
+
"""生成交付清单、报告和压缩包"""
|
|
35
|
+
output_dir = self.project_dir / "output" / "delivery"
|
|
36
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
|
|
38
|
+
specs = self._artifact_specs(cicd_platform=cicd_platform)
|
|
39
|
+
included_files: list[str] = []
|
|
40
|
+
missing_required: list[dict[str, str]] = []
|
|
41
|
+
|
|
42
|
+
for spec in specs:
|
|
43
|
+
if spec.path.exists():
|
|
44
|
+
included_files.append(self._relative(spec.path))
|
|
45
|
+
elif spec.required:
|
|
46
|
+
missing_required.append(
|
|
47
|
+
{
|
|
48
|
+
"path": self._relative(spec.path),
|
|
49
|
+
"reason": spec.reason,
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
migration_files = self._collect_migration_files()
|
|
54
|
+
if migration_files:
|
|
55
|
+
included_files.extend(self._relative(path) for path in migration_files)
|
|
56
|
+
else:
|
|
57
|
+
missing_required.append(
|
|
58
|
+
{
|
|
59
|
+
"path": "migrations/*",
|
|
60
|
+
"reason": "缺少数据库迁移脚本(至少应生成一种 ORM 迁移文件)",
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
included_files = sorted(set(included_files))
|
|
65
|
+
status = "ready" if not missing_required else "incomplete"
|
|
66
|
+
|
|
67
|
+
manifest: dict[str, object] = {
|
|
68
|
+
"project_name": self.name,
|
|
69
|
+
"version": self.version,
|
|
70
|
+
"generated_at": datetime.now().isoformat(timespec="seconds"),
|
|
71
|
+
"status": status,
|
|
72
|
+
"cicd_platform": cicd_platform,
|
|
73
|
+
"included_files": included_files,
|
|
74
|
+
"missing_required": missing_required,
|
|
75
|
+
"summary": {
|
|
76
|
+
"included_count": len(included_files),
|
|
77
|
+
"missing_required_count": len(missing_required),
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
manifest_file = output_dir / f"{self.name}-delivery-manifest.json"
|
|
82
|
+
manifest_file.write_text(
|
|
83
|
+
json.dumps(manifest, ensure_ascii=False, indent=2),
|
|
84
|
+
encoding="utf-8",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
report_file = output_dir / f"{self.name}-delivery-report.md"
|
|
88
|
+
report_file.write_text(self._to_markdown(manifest), encoding="utf-8")
|
|
89
|
+
|
|
90
|
+
archive_file = output_dir / f"{self.name}-delivery-v{self.version}.zip"
|
|
91
|
+
self._build_archive(
|
|
92
|
+
archive_path=archive_file,
|
|
93
|
+
included_files=included_files,
|
|
94
|
+
extra_files=[manifest_file, report_file],
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
"status": status,
|
|
99
|
+
"manifest_file": str(manifest_file),
|
|
100
|
+
"report_file": str(report_file),
|
|
101
|
+
"archive_file": str(archive_file),
|
|
102
|
+
"included_count": len(included_files),
|
|
103
|
+
"missing_required_count": len(missing_required),
|
|
104
|
+
"missing_required": missing_required,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
def _artifact_specs(self, cicd_platform: str) -> list[ArtifactSpec]:
|
|
108
|
+
output_dir = self.project_dir / "output"
|
|
109
|
+
specs = [
|
|
110
|
+
ArtifactSpec(output_dir / f"{self.name}-research.md", True, "缺少需求增强报告"),
|
|
111
|
+
ArtifactSpec(output_dir / f"{self.name}-prd.md", True, "缺少 PRD"),
|
|
112
|
+
ArtifactSpec(output_dir / f"{self.name}-architecture.md", True, "缺少架构文档"),
|
|
113
|
+
ArtifactSpec(output_dir / f"{self.name}-uiux.md", True, "缺少 UI/UX 文档"),
|
|
114
|
+
ArtifactSpec(output_dir / f"{self.name}-execution-plan.md", True, "缺少执行路线图"),
|
|
115
|
+
ArtifactSpec(output_dir / f"{self.name}-frontend-blueprint.md", True, "缺少前端蓝图"),
|
|
116
|
+
ArtifactSpec(output_dir / f"{self.name}-redteam.md", True, "缺少红队报告"),
|
|
117
|
+
ArtifactSpec(output_dir / f"{self.name}-quality-gate.md", True, "缺少质量门禁报告"),
|
|
118
|
+
ArtifactSpec(output_dir / f"{self.name}-code-review.md", True, "缺少代码审查指南"),
|
|
119
|
+
ArtifactSpec(output_dir / f"{self.name}-ai-prompt.md", True, "缺少 AI 提示词"),
|
|
120
|
+
ArtifactSpec(output_dir / "frontend" / "index.html", True, "缺少前端演示页面"),
|
|
121
|
+
ArtifactSpec(output_dir / "frontend" / "styles.css", True, "缺少前端演示样式"),
|
|
122
|
+
ArtifactSpec(output_dir / "frontend" / "app.js", True, "缺少前端演示脚本"),
|
|
123
|
+
ArtifactSpec(self.project_dir / "backend" / "API_CONTRACT.md", True, "缺少 API 契约"),
|
|
124
|
+
ArtifactSpec(self.project_dir / ".env.deploy.example", True, "缺少部署环境模板"),
|
|
125
|
+
ArtifactSpec(
|
|
126
|
+
self.project_dir / "output" / "deploy" / "all-secrets-checklist.md",
|
|
127
|
+
True,
|
|
128
|
+
"缺少部署 Secrets 检查清单",
|
|
129
|
+
),
|
|
130
|
+
]
|
|
131
|
+
specs.extend(self._cicd_specs(cicd_platform=cicd_platform))
|
|
132
|
+
return specs
|
|
133
|
+
|
|
134
|
+
def _cicd_specs(self, cicd_platform: str) -> list[ArtifactSpec]:
|
|
135
|
+
mapping: dict[str, list[str]] = {
|
|
136
|
+
"github": [".github/workflows/ci.yml", ".github/workflows/cd.yml"],
|
|
137
|
+
"gitlab": [".gitlab-ci.yml"],
|
|
138
|
+
"jenkins": ["Jenkinsfile"],
|
|
139
|
+
"azure": [".azure-pipelines.yml"],
|
|
140
|
+
"bitbucket": ["bitbucket-pipelines.yml"],
|
|
141
|
+
"all": [
|
|
142
|
+
".github/workflows/ci.yml",
|
|
143
|
+
".github/workflows/cd.yml",
|
|
144
|
+
".gitlab-ci.yml",
|
|
145
|
+
"Jenkinsfile",
|
|
146
|
+
".azure-pipelines.yml",
|
|
147
|
+
"bitbucket-pipelines.yml",
|
|
148
|
+
],
|
|
149
|
+
}
|
|
150
|
+
files = mapping.get(cicd_platform, mapping["github"])
|
|
151
|
+
return [
|
|
152
|
+
ArtifactSpec(self.project_dir / relative, True, f"缺少 CI/CD 文件: {relative}")
|
|
153
|
+
for relative in files
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
def _collect_migration_files(self) -> list[Path]:
|
|
157
|
+
patterns = [
|
|
158
|
+
"prisma/migrations/**/*.sql",
|
|
159
|
+
"alembic/versions/*.py",
|
|
160
|
+
"backend/migrations/**/*.sql",
|
|
161
|
+
"backend/migrations/**/*.py",
|
|
162
|
+
"migrations/**/*.sql",
|
|
163
|
+
"src/main/resources/db/migration/*.sql",
|
|
164
|
+
]
|
|
165
|
+
files: list[Path] = []
|
|
166
|
+
for pattern in patterns:
|
|
167
|
+
files.extend(self.project_dir.glob(pattern))
|
|
168
|
+
return sorted(path for path in files if path.is_file())
|
|
169
|
+
|
|
170
|
+
def _build_archive(
|
|
171
|
+
self,
|
|
172
|
+
archive_path: Path,
|
|
173
|
+
included_files: list[str],
|
|
174
|
+
extra_files: list[Path],
|
|
175
|
+
) -> None:
|
|
176
|
+
with ZipFile(archive_path, mode="w", compression=ZIP_DEFLATED) as archive:
|
|
177
|
+
for relative in included_files:
|
|
178
|
+
file_path = self.project_dir / relative
|
|
179
|
+
if file_path.exists():
|
|
180
|
+
archive.write(file_path, arcname=relative)
|
|
181
|
+
for file_path in extra_files:
|
|
182
|
+
if file_path.exists():
|
|
183
|
+
arcname = self._relative(file_path)
|
|
184
|
+
archive.write(file_path, arcname=arcname)
|
|
185
|
+
|
|
186
|
+
def _to_markdown(self, manifest: dict[str, object]) -> str:
|
|
187
|
+
status = str(manifest.get("status", "incomplete"))
|
|
188
|
+
status_text = "可交付" if status == "ready" else "未完成"
|
|
189
|
+
included = manifest.get("included_files", [])
|
|
190
|
+
missing = manifest.get("missing_required", [])
|
|
191
|
+
cicd_platform = manifest.get("cicd_platform", "all")
|
|
192
|
+
|
|
193
|
+
lines = [
|
|
194
|
+
"# 交付报告",
|
|
195
|
+
"",
|
|
196
|
+
f"- 项目: {manifest.get('project_name', self.name)}",
|
|
197
|
+
f"- 版本: {manifest.get('version', self.version)}",
|
|
198
|
+
f"- 状态: {status_text} ({status})",
|
|
199
|
+
f"- CI/CD 平台: {cicd_platform}",
|
|
200
|
+
f"- 生成时间: {manifest.get('generated_at', '')}",
|
|
201
|
+
"",
|
|
202
|
+
"## 已包含文件",
|
|
203
|
+
"",
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
if isinstance(included, list) and included:
|
|
207
|
+
for item in included:
|
|
208
|
+
lines.append(f"- {item}")
|
|
209
|
+
else:
|
|
210
|
+
lines.append("- (none)")
|
|
211
|
+
lines.append("")
|
|
212
|
+
|
|
213
|
+
lines.extend(["## 缺失必需项", ""])
|
|
214
|
+
if isinstance(missing, list) and missing:
|
|
215
|
+
for item in missing:
|
|
216
|
+
if isinstance(item, dict):
|
|
217
|
+
lines.append(
|
|
218
|
+
f"- {item.get('path', 'unknown')}: {item.get('reason', '')}"
|
|
219
|
+
)
|
|
220
|
+
else:
|
|
221
|
+
lines.append("- 无")
|
|
222
|
+
lines.append("")
|
|
223
|
+
return "\n".join(lines)
|
|
224
|
+
|
|
225
|
+
def _relative(self, path: Path) -> str:
|
|
226
|
+
try:
|
|
227
|
+
return str(path.relative_to(self.project_dir))
|
|
228
|
+
except ValueError:
|
|
229
|
+
return str(path)
|