pdd-skills 3.0.0

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 (261) hide show
  1. package/README.md +1478 -0
  2. package/bin/pdd.js +354 -0
  3. package/config/bpmn-rules.yaml +166 -0
  4. package/config/checkstyle.xml +105 -0
  5. package/config/eslint.config.js +48 -0
  6. package/config/pmd.xml +91 -0
  7. package/config/prd-rules.yaml +113 -0
  8. package/config/ruff.toml +45 -0
  9. package/config/sqlfluff.cfg +82 -0
  10. package/hooks/hook-executor.js +332 -0
  11. package/index.js +43 -0
  12. package/lib/api-routes.js +750 -0
  13. package/lib/api-server.js +408 -0
  14. package/lib/cache/cache-config.js +209 -0
  15. package/lib/cache/system-cache.js +852 -0
  16. package/lib/config-manager.js +373 -0
  17. package/lib/generate.js +528 -0
  18. package/lib/grpc/grpc-routes.js +1134 -0
  19. package/lib/grpc/grpc-server.js +912 -0
  20. package/lib/grpc/proto-definitions.js +1033 -0
  21. package/lib/init.js +172 -0
  22. package/lib/iteration/auto-fixer.js +1025 -0
  23. package/lib/iteration/auto-reviewer.js +923 -0
  24. package/lib/iteration/controller.js +577 -0
  25. package/lib/list.js +130 -0
  26. package/lib/mcp-server.js +548 -0
  27. package/lib/openclaw/api-integration.js +535 -0
  28. package/lib/openclaw/cli-integration.js +567 -0
  29. package/lib/openclaw/data-sync.js +845 -0
  30. package/lib/openclaw/openclaw-adapter.js +783 -0
  31. package/lib/plugin/example-plugins/code-stats/index.js +332 -0
  32. package/lib/plugin/example-plugins/code-stats/plugin.json +1 -0
  33. package/lib/plugin/example-plugins/custom-linter/index.js +472 -0
  34. package/lib/plugin/example-plugins/custom-linter/plugin.json +1 -0
  35. package/lib/plugin/example-plugins/hello-world/index.js +86 -0
  36. package/lib/plugin/example-plugins/hello-world/plugin.json +1 -0
  37. package/lib/plugin/plugin-manager.js +655 -0
  38. package/lib/plugin/plugin-sdk.js +565 -0
  39. package/lib/plugin/sandbox.js +627 -0
  40. package/lib/quality/rules/maintainability.js +418 -0
  41. package/lib/quality/rules/performance.js +498 -0
  42. package/lib/quality/rules/readability.js +441 -0
  43. package/lib/quality/rules/robustness.js +504 -0
  44. package/lib/quality/rules/security.js +444 -0
  45. package/lib/quality/scorer.js +576 -0
  46. package/lib/report.js +669 -0
  47. package/lib/sdk-base.js +301 -0
  48. package/lib/sdk-js.js +446 -0
  49. package/lib/sdk-python/README.md +546 -0
  50. package/lib/sdk-python/examples/basic_usage.py +450 -0
  51. package/lib/sdk-python/pdd_sdk/__init__.py +180 -0
  52. package/lib/sdk-python/pdd_sdk/client.py +1170 -0
  53. package/lib/sdk-python/pdd_sdk/events.py +423 -0
  54. package/lib/sdk-python/pdd_sdk/exceptions.py +158 -0
  55. package/lib/sdk-python/pdd_sdk/models.py +518 -0
  56. package/lib/sdk-python/pdd_sdk/utils.py +759 -0
  57. package/lib/token/budget-alert.js +367 -0
  58. package/lib/token/budget-manager.js +485 -0
  59. package/lib/update.js +54 -0
  60. package/lib/utils/logger.js +88 -0
  61. package/lib/verify.js +741 -0
  62. package/lib/version.js +52 -0
  63. package/lib/vm/README.md +102 -0
  64. package/lib/vm/dashboard/api-routes.js +669 -0
  65. package/lib/vm/dashboard/server.js +391 -0
  66. package/lib/vm/dashboard/sse.js +358 -0
  67. package/lib/vm/dashboard/static/css/dashboard.css +1378 -0
  68. package/lib/vm/dashboard/static/index.html +118 -0
  69. package/lib/vm/dashboard/static/js/app.js +949 -0
  70. package/lib/vm/dashboard/static/js/charts.js +913 -0
  71. package/lib/vm/dashboard/static/js/kanban-view.js +1053 -0
  72. package/lib/vm/dashboard/static/js/pipeline-view.js +463 -0
  73. package/lib/vm/dashboard/static/js/quality-view.js +598 -0
  74. package/lib/vm/dashboard/static/js/system-view.js +1021 -0
  75. package/lib/vm/data-provider.js +1191 -0
  76. package/lib/vm/event-bus.js +402 -0
  77. package/lib/vm/hooks/extract-hook.js +307 -0
  78. package/lib/vm/hooks/generate-hook.js +374 -0
  79. package/lib/vm/hooks/hook-interface.js +458 -0
  80. package/lib/vm/hooks/report-hook.js +331 -0
  81. package/lib/vm/hooks/verify-hook.js +454 -0
  82. package/lib/vm/models.js +1003 -0
  83. package/lib/vm/reconciler.js +855 -0
  84. package/lib/vm/scanner.js +988 -0
  85. package/lib/vm/state-schema.js +955 -0
  86. package/lib/vm/state-store.js +733 -0
  87. package/lib/vm/tui/components/card.js +339 -0
  88. package/lib/vm/tui/components/progress-bar.js +368 -0
  89. package/lib/vm/tui/components/sparkline.js +327 -0
  90. package/lib/vm/tui/components/status-light.js +294 -0
  91. package/lib/vm/tui/components/table.js +370 -0
  92. package/lib/vm/tui/input.js +335 -0
  93. package/lib/vm/tui/renderer.js +548 -0
  94. package/lib/vm/tui/screens/kanban-screen.js +397 -0
  95. package/lib/vm/tui/screens/overview-screen.js +357 -0
  96. package/lib/vm/tui/screens/quality-screen.js +336 -0
  97. package/lib/vm/tui/screens/system-screen.js +379 -0
  98. package/lib/vm/tui/tui.js +805 -0
  99. package/package.json +1 -0
  100. package/scripts/cso-analyzer.js +198 -0
  101. package/scripts/eval-runner.js +359 -0
  102. package/scripts/i18n-checker.js +109 -0
  103. package/scripts/linter/activiti-linter.js +272 -0
  104. package/scripts/linter/prd-linter.js +162 -0
  105. package/scripts/linter/report-generator.js +207 -0
  106. package/scripts/linter/run-linters.js +285 -0
  107. package/scripts/linter/sql-linter.js +166 -0
  108. package/scripts/token-analyzer.js +162 -0
  109. package/scripts/vm-test.js +180 -0
  110. package/skills/core/official-doc-writer/LICENSE +21 -0
  111. package/skills/core/official-doc-writer/README.md +232 -0
  112. package/skills/core/official-doc-writer/SKILL.md +475 -0
  113. package/skills/core/official-doc-writer/_meta.json +1 -0
  114. package/skills/core/official-doc-writer/document_generator.py +580 -0
  115. package/skills/core/official-doc-writer/evals/default-evals.json +1 -0
  116. package/skills/core/official-doc-writer/examples.md +150 -0
  117. package/skills/core/official-doc-writer/fonts/FONTS_LIST.md +45 -0
  118. package/skills/core/official-doc-writer/fonts/README.md +141 -0
  119. package/skills/core/official-doc-writer/fonts/SIMFANG.TTF +0 -0
  120. package/skills/core/official-doc-writer/fonts/SIMHEI.TTF +0 -0
  121. package/skills/core/official-doc-writer/fonts/SIMKAI.TTF +0 -0
  122. package/skills/core/official-doc-writer/fonts/SIMSUN.TTC +0 -0
  123. package/skills/core/official-doc-writer/fonts//346/226/271/346/255/243/345/260/217/346/240/207/345/256/213GBK.TTF +0 -0
  124. package/skills/core/official-doc-writer/references/GBT_9704-2012_/345/205/232/346/224/277/346/234/272/345/205/263/345/205/254/346/226/207/346/240/274/345/274/217.md +422 -0
  125. package/skills/core/official-doc-writer/scripts/__pycache__/generate_official_doc.cpython-313.pyc +0 -0
  126. package/skills/core/official-doc-writer/scripts/dialog_manager.py +564 -0
  127. package/skills/core/official-doc-writer/scripts/generate_official_doc.py +252 -0
  128. package/skills/core/official-doc-writer/scripts/install_fonts.py +390 -0
  129. package/skills/core/official-doc-writer/scripts/smart_prompts.py +363 -0
  130. package/skills/core/pdd-ba/SKILL.md +305 -0
  131. package/skills/core/pdd-ba/_meta.json +1 -0
  132. package/skills/core/pdd-ba/evals/default-evals.json +1 -0
  133. package/skills/core/pdd-code-reviewer/SKILL.md +378 -0
  134. package/skills/core/pdd-code-reviewer/_meta.json +1 -0
  135. package/skills/core/pdd-code-reviewer/evals/default-evals.json +1 -0
  136. package/skills/core/pdd-doc-change/SKILL.md +350 -0
  137. package/skills/core/pdd-doc-change/_meta.json +1 -0
  138. package/skills/core/pdd-doc-change/evals/default-evals.json +1 -0
  139. package/skills/core/pdd-doc-gardener/SKILL.md +248 -0
  140. package/skills/core/pdd-doc-gardener/_meta.json +1 -0
  141. package/skills/core/pdd-doc-gardener/evals/default-evals.json +1 -0
  142. package/skills/core/pdd-entropy-reduction/SKILL.md +360 -0
  143. package/skills/core/pdd-entropy-reduction/_meta.json +1 -0
  144. package/skills/core/pdd-entropy-reduction/evals/default-evals.json +1 -0
  145. package/skills/core/pdd-entropy-reduction/references/entropy-report-template.md +287 -0
  146. package/skills/core/pdd-entropy-reduction/references/golden-principles.md +573 -0
  147. package/skills/core/pdd-entropy-reduction/scripts/entropy_scan.py +712 -0
  148. package/skills/core/pdd-extract-features/SKILL.md +320 -0
  149. package/skills/core/pdd-extract-features/_meta.json +1 -0
  150. package/skills/core/pdd-extract-features/evals/default-evals.json +1 -0
  151. package/skills/core/pdd-generate-spec/SKILL.md +418 -0
  152. package/skills/core/pdd-generate-spec/_meta.json +1 -0
  153. package/skills/core/pdd-generate-spec/evals/default-evals.json +1 -0
  154. package/skills/core/pdd-implement-feature/SKILL.md +332 -0
  155. package/skills/core/pdd-implement-feature/_meta.json +1 -0
  156. package/skills/core/pdd-implement-feature/evals/default-evals.json +1 -0
  157. package/skills/core/pdd-main/SKILL.md +540 -0
  158. package/skills/core/pdd-main/_meta.json +1 -0
  159. package/skills/core/pdd-main/evals/default-evals.json +1 -0
  160. package/skills/core/pdd-main/evals/evals.json +215 -0
  161. package/skills/core/pdd-verify-feature/SKILL.md +474 -0
  162. package/skills/core/pdd-verify-feature/_meta.json +1 -0
  163. package/skills/core/pdd-verify-feature/evals/default-evals.json +1 -0
  164. package/skills/core/pdd-vm/evals/default-evals.json +1 -0
  165. package/skills/core/traffic-accident-assessor/LICENSE +29 -0
  166. package/skills/core/traffic-accident-assessor/SKILL.md +439 -0
  167. package/skills/core/traffic-accident-assessor/evals/evals.json +1 -0
  168. package/skills/core/traffic-accident-assessor/references/accident-types.md +369 -0
  169. package/skills/core/traffic-accident-assessor/references/liability-rules.md +287 -0
  170. package/skills/core/traffic-accident-assessor/references/traffic-laws.md +226 -0
  171. package/skills/core/traffic-accident-assessor/references//351/253/230/345/260/224/345/244/253/350/257/264/346/230/216/344/271/246.pdf +32576 -106
  172. package/skills/core/traffic-accident-assessor/scripts/generate_official_statement.py +588 -0
  173. package/skills/core/traffic-accident-assessor/scripts/generate_report.py +495 -0
  174. package/skills/core/traffic-accident-assessor/scripts/generate_statement.py +528 -0
  175. package/skills/core/traffic-accident-assessor.zip +0 -0
  176. package/skills/entropy/expert-arch-enforcer/SKILL.md +292 -0
  177. package/skills/entropy/expert-arch-enforcer/_meta.json +1 -0
  178. package/skills/entropy/expert-arch-enforcer/evals/default-evals.json +1 -0
  179. package/skills/entropy/expert-auto-refactor/SKILL.md +327 -0
  180. package/skills/entropy/expert-auto-refactor/_meta.json +1 -0
  181. package/skills/entropy/expert-auto-refactor/evals/default-evals.json +1 -0
  182. package/skills/entropy/expert-code-quality/SKILL.md +468 -0
  183. package/skills/entropy/expert-code-quality/_meta.json +1 -0
  184. package/skills/entropy/expert-code-quality/evals/default-evals.json +1 -0
  185. package/skills/entropy/expert-code-quality/evals/evals.json +109 -0
  186. package/skills/entropy/expert-code-quality/references/code-smells.md +605 -0
  187. package/skills/entropy/expert-code-quality/references/design-patterns.md +1111 -0
  188. package/skills/entropy/expert-code-quality/references/refactoring-catalog.md +1281 -0
  189. package/skills/entropy/expert-code-quality/references/solid-principles.md +524 -0
  190. package/skills/entropy/expert-entropy-auditor/SKILL.md +276 -0
  191. package/skills/entropy/expert-entropy-auditor/_meta.json +1 -0
  192. package/skills/entropy/expert-entropy-auditor/evals/default-evals.json +1 -0
  193. package/skills/expert/expert-activiti/SKILL.md +497 -0
  194. package/skills/expert/expert-activiti/_meta.json +1 -0
  195. package/skills/expert/expert-mysql/SKILL.md +832 -0
  196. package/skills/expert/expert-mysql/_meta.json +1 -0
  197. package/skills/expert/expert-performance/SKILL.md +379 -0
  198. package/skills/expert/expert-performance/_meta.json +1 -0
  199. package/skills/expert/expert-performance/evals/default-evals.json +1 -0
  200. package/skills/expert/expert-ruoyi/SKILL.md +472 -0
  201. package/skills/expert/expert-ruoyi/_meta.json +1 -0
  202. package/skills/expert/expert-security/SKILL.md +1341 -0
  203. package/skills/expert/expert-security/_meta.json +1 -0
  204. package/skills/expert/expert-security/evals/default-evals.json +1 -0
  205. package/skills/expert/software-architect/SKILL.md +350 -0
  206. package/skills/expert/software-architect/_meta.json +1 -0
  207. package/skills/expert/software-engineer/SKILL.md +437 -0
  208. package/skills/expert/software-engineer/_meta.json +1 -0
  209. package/skills/expert/software-engineer/architecture.md +130 -0
  210. package/skills/expert/software-engineer/patterns.md +151 -0
  211. package/skills/expert/software-engineer/testing.md +135 -0
  212. package/skills/expert/system-architect/SKILL.md +628 -0
  213. package/skills/expert/system-architect/_meta.json +1 -0
  214. package/skills/expert/system-architect/assets/templates/ARCHITECTURE.md +25 -0
  215. package/skills/expert/system-architect/assets/templates/README.md +44 -0
  216. package/skills/expert/system-architect/references/js-ts-standards.md +18 -0
  217. package/skills/expert/system-architect/references/python-standards.md +19 -0
  218. package/skills/expert/system-architect/references/scaffolding.md +61 -0
  219. package/skills/expert/system-architect/references/security-checklist.md +21 -0
  220. package/skills/openspec/openspec-apply-change/SKILL.md +156 -0
  221. package/skills/openspec/openspec-apply-change/_meta.json +1 -0
  222. package/skills/openspec/openspec-archive-change/SKILL.md +114 -0
  223. package/skills/openspec/openspec-archive-change/_meta.json +1 -0
  224. package/skills/openspec/openspec-bulk-archive-change/SKILL.md +246 -0
  225. package/skills/openspec/openspec-bulk-archive-change/_meta.json +1 -0
  226. package/skills/openspec/openspec-continue-change/SKILL.md +118 -0
  227. package/skills/openspec/openspec-continue-change/_meta.json +1 -0
  228. package/skills/openspec/openspec-explore/SKILL.md +288 -0
  229. package/skills/openspec/openspec-explore/_meta.json +1 -0
  230. package/skills/openspec/openspec-ff-change/SKILL.md +101 -0
  231. package/skills/openspec/openspec-ff-change/_meta.json +1 -0
  232. package/skills/openspec/openspec-new-change/SKILL.md +74 -0
  233. package/skills/openspec/openspec-new-change/_meta.json +1 -0
  234. package/skills/openspec/openspec-onboard/SKILL.md +554 -0
  235. package/skills/openspec/openspec-onboard/_meta.json +1 -0
  236. package/skills/openspec/openspec-sync-specs/SKILL.md +138 -0
  237. package/skills/openspec/openspec-sync-specs/_meta.json +1 -0
  238. package/skills/openspec/openspec-verify-change/SKILL.md +168 -0
  239. package/skills/openspec/openspec-verify-change/_meta.json +1 -0
  240. package/skills/pr/pdd-multi-review/SKILL.md +534 -0
  241. package/skills/pr/pdd-multi-review/_meta.json +1 -0
  242. package/skills/pr/pdd-pr-batch/SKILL.md +303 -0
  243. package/skills/pr/pdd-pr-batch/_meta.json +1 -0
  244. package/skills/pr/pdd-pr-create/SKILL.md +344 -0
  245. package/skills/pr/pdd-pr-create/_meta.json +1 -0
  246. package/skills/pr/pdd-pr-merge/SKILL.md +286 -0
  247. package/skills/pr/pdd-pr-merge/_meta.json +1 -0
  248. package/skills/pr/pdd-pr-review/SKILL.md +217 -0
  249. package/skills/pr/pdd-pr-review/_meta.json +1 -0
  250. package/skills/pr/pdd-task-manager/SKILL.md +636 -0
  251. package/skills/pr/pdd-task-manager/_meta.json +1 -0
  252. package/skills/pr/pdd-template-engine/SKILL.md +306 -0
  253. package/skills/pr/pdd-template-engine/_meta.json +1 -0
  254. package/templates/behavior-shaping/iron-law-template.md +87 -0
  255. package/templates/behavior-shaping/rationalization-template.md +62 -0
  256. package/templates/behavior-shaping/red-flags-template.md +70 -0
  257. package/templates/bilingual-template.md +139 -0
  258. package/templates/config/default.yaml +47 -0
  259. package/templates/project/default/README.md +31 -0
  260. package/templates/project/frontend/README.md +46 -0
  261. package/templates/project/java/README.md +48 -0
@@ -0,0 +1,750 @@
1
+ /**
2
+ * PDD API Routes
3
+ * 定义所有API端点和对应的处理函数
4
+ */
5
+
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ import { parseSpecFile } from './generate.js';
10
+ import { verifyFeature as runVerification } from './verify.js';
11
+ import { collectProjectData } from './report.js';
12
+ import { loadConfig, findConfigFile } from './config-manager.js';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = path.dirname(__filename);
16
+
17
+ /**
18
+ * API路由定义
19
+ * 每个路由包含: method, path, handler, description
20
+ */
21
+ export const apiRoutes = [
22
+ // ==================== 基础端点 ====================
23
+
24
+ {
25
+ method: 'GET',
26
+ path: '/api/v1/status',
27
+ description: '获取服务状态和基本信息',
28
+ handler: handleStatus
29
+ },
30
+
31
+ {
32
+ method: 'GET',
33
+ path: '/api/v1/docs',
34
+ description: '获取API文档',
35
+ handler: handleApiDocs
36
+ },
37
+
38
+ {
39
+ method: 'GET',
40
+ path: '/api/v1/health',
41
+ description: '健康检查端点',
42
+ handler: handleHealthCheck
43
+ },
44
+
45
+ // ==================== 规格相关 ====================
46
+
47
+ {
48
+ method: 'POST',
49
+ path: '/api/v1/spec/parse',
50
+ description: '解析规格文档,提取功能点信息',
51
+ handler: handleParseSpec
52
+ },
53
+
54
+ {
55
+ method: 'POST',
56
+ path: '/api/v1/spec/generate',
57
+ description: '基于PRD生成开发规格文档',
58
+ handler: handleGenerateSpec
59
+ },
60
+
61
+ // ==================== 代码生成 ====================
62
+
63
+ {
64
+ method: 'POST',
65
+ path: '/api/v1/generate',
66
+ description: '基于开发规格生成代码',
67
+ handler: handleGenerateCode
68
+ },
69
+
70
+ {
71
+ method: 'POST',
72
+ path: '/api/v1/generate/dry-run',
73
+ description: '预览将要生成的代码(不实际生成)',
74
+ handler: handleDryRun
75
+ },
76
+
77
+ // ==================== 验证功能 ====================
78
+
79
+ {
80
+ method: 'POST',
81
+ path: '/api/v1/verify',
82
+ description: '验证功能实现是否符合规格',
83
+ handler: handleVerify
84
+ },
85
+
86
+ {
87
+ method: 'POST',
88
+ path: '/api/v1/verify/quick',
89
+ description: '快速验证(仅基础检查)',
90
+ handler: handleQuickVerify
91
+ },
92
+
93
+ // ==================== 报告生成 ====================
94
+
95
+ {
96
+ method: 'POST',
97
+ path: '/api/v1/report',
98
+ description: '生成项目分析报告',
99
+ handler: handleGenerateReport
100
+ },
101
+
102
+ {
103
+ method: 'GET',
104
+ path: '/api/v1/report/stats',
105
+ description: '获取项目统计信息(轻量级)',
106
+ handler: handleProjectStats
107
+ },
108
+
109
+ // ==================== 配置管理 ====================
110
+
111
+ {
112
+ method: 'GET',
113
+ path: '/api/v1/config',
114
+ description: '获取当前PDD配置',
115
+ handler: handleGetConfig
116
+ },
117
+
118
+ {
119
+ method: 'PUT',
120
+ path: '/api/v1/config',
121
+ description: '更新PDD配置',
122
+ handler: handleUpdateConfig
123
+ },
124
+
125
+ {
126
+ method: 'POST',
127
+ path: '/api/v1/config/reset',
128
+ description: '重置为默认配置',
129
+ handler: handleResetConfig
130
+ },
131
+
132
+ // ==================== 技能管理 ====================
133
+
134
+ {
135
+ method: 'GET',
136
+ path: '/api/v1/skills',
137
+ description: '列出所有可用技能',
138
+ handler: handleListSkills
139
+ },
140
+
141
+ {
142
+ method: 'GET',
143
+ path: '/api/v1/skills/:category',
144
+ description: '列出指定分类的技能',
145
+ handler: handleListSkillsByCategory
146
+ },
147
+
148
+ {
149
+ method: 'GET',
150
+ path: '/api/v1/skills/:category/:name',
151
+ description: '获取指定技能的详细信息',
152
+ handler: handleGetSkillDetail
153
+ }
154
+ ];
155
+
156
+ // ==================== 路由处理器实现 ====================
157
+
158
+ /**
159
+ * 处理服务状态请求
160
+ */
161
+ async function handleStatus(req) {
162
+ const startTime = Date.now(); // 服务器启动时间(简化为当前时间)
163
+ const uptime = process.uptime();
164
+
165
+ return {
166
+ status: 'running',
167
+ version: '3.0.0',
168
+ name: 'PDD-Skills API Server',
169
+ uptime: {
170
+ seconds: Math.floor(uptime),
171
+ human: formatUptime(uptime)
172
+ },
173
+ environment: process.env.NODE_ENV || 'development',
174
+ nodeVersion: process.version,
175
+ memory: {
176
+ used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
177
+ total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
178
+ unit: 'MB'
179
+ },
180
+ endpoints: apiRoutes.length,
181
+ timestamp: new Date().toISOString()
182
+ };
183
+ }
184
+
185
+ /**
186
+ * 处理API文档请求
187
+ */
188
+ async function handleApiDocs(req) {
189
+ return {
190
+ title: 'PDD-Skills API Documentation',
191
+ version: 'v1',
192
+ baseUrl: `http://${req.headers.host}`,
193
+ endpoints: apiRoutes.map(route => ({
194
+ method: route.method,
195
+ path: route.path,
196
+ description: route.description
197
+ })),
198
+ usage: {
199
+ authentication: '暂无认证机制(后续版本支持)',
200
+ rateLimit: '100 requests per minute per IP',
201
+ responseFormat: 'JSON',
202
+ errorCodes: {
203
+ 400: 'Bad Request - 请求参数错误',
204
+ 404: 'Not Found - 路由不存在',
205
+ 429: 'Too Many Requests - 请求过于频繁',
206
+ 500: 'Internal Server Error - 服务器内部错误'
207
+ }
208
+ },
209
+ examples: [
210
+ {
211
+ endpoint: 'GET /api/v1/status',
212
+ description: '检查服务状态',
213
+ curl: `curl http://localhost:3000/api/v1/status`
214
+ },
215
+ {
216
+ endpoint: 'POST /api/v1/generate',
217
+ description: '生成代码',
218
+ curl: `curl -X POST http://localhost:3000/api/v1/generate \\
219
+ -H "Content-Type: application/json" \\
220
+ -d '{"spec": "dev-specs/spec.md", "output": "./generated"}'`
221
+ }
222
+ ]
223
+ };
224
+ }
225
+
226
+ /**
227
+ * 健康检查
228
+ */
229
+ async function handleHealthCheck(req) {
230
+ return {
231
+ status: 'healthy',
232
+ timestamp: new Date().toISOString(),
233
+ checks: {
234
+ filesystem: fs.accessSync ? 'ok' : 'warning',
235
+ memory: process.memoryUsage().heapUsed < 500000000 ? 'ok' : 'warning',
236
+ cpu: 'ok' // 简化处理
237
+ }
238
+ };
239
+ }
240
+
241
+ /**
242
+ * 解析规格文档
243
+ */
244
+ async function handleParseSpec(req) {
245
+ const { specPath } = req.body;
246
+
247
+ if (!specPath) {
248
+ throw new Error('缺少必要参数: specPath');
249
+ }
250
+
251
+ const resolvedPath = path.resolve(specPath);
252
+
253
+ if (!fs.existsSync(resolvedPath)) {
254
+ throw new Error(`规格文件不存在: ${resolvedPath}`);
255
+ }
256
+
257
+ const specData = await parseSpecFile(resolvedPath);
258
+
259
+ return {
260
+ spec: resolvedPath,
261
+ parsedAt: new Date().toISOString(),
262
+ ...specData
263
+ };
264
+ }
265
+
266
+ /**
267
+ * 生成开发规格(占位实现)
268
+ */
269
+ async function handleGenerateSpec(req) {
270
+ const { prdPath, outputDir, template } = req.body;
271
+
272
+ // TODO: 实现完整的PRD到规格的转换逻辑
273
+
274
+ return {
275
+ message: '规格生成功能正在开发中',
276
+ input: prdPath,
277
+ outputDir: outputDir || './dev-specs',
278
+ template: template || 'default',
279
+ status: 'not_implemented',
280
+ suggestion: '请使用 CLI 命令: pdd-generate-spec'
281
+ };
282
+ }
283
+
284
+ /**
285
+ * 生成代码
286
+ */
287
+ async function handleGenerateCode(req) {
288
+ const {
289
+ spec = 'dev-specs/spec.md',
290
+ output = './generated',
291
+ feature,
292
+ dryRun = false
293
+ } = req.body;
294
+
295
+ // 调用generate模块
296
+ const { generateCode } = await import('./generate.js');
297
+
298
+ // 由于generateCode是CLI导向的,这里需要适配
299
+ // 简化版:直接调用核心逻辑
300
+ try {
301
+ const specData = await parseSpecFile(path.resolve(spec));
302
+
303
+ let targetFeatures = specData.features;
304
+ if (feature) {
305
+ targetFeatures = specData.features.filter(f =>
306
+ f.title.toLowerCase().includes(feature.toLowerCase())
307
+ );
308
+ }
309
+
310
+ const resultDir = path.resolve(output);
311
+
312
+ if (!fs.existsSync(resultDir)) {
313
+ await fs.promises.mkdir(resultDir, { recursive: true });
314
+ }
315
+
316
+ // 返回将要生成的信息
317
+ return {
318
+ spec: path.resolve(spec),
319
+ features: targetFeatures.length,
320
+ outputDir: resultDir,
321
+ dryRun: dryRun,
322
+ status: dryRun ? 'preview' : 'generated',
323
+ generatedFiles: [], // 实际实现中会填充
324
+ message: dryRun ? '预览模式:未实际生成文件' : '代码生成完成'
325
+ };
326
+
327
+ } catch (error) {
328
+ throw new Error(`代码生成失败: ${error.message}`);
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Dry-run 预览
334
+ */
335
+ async function handleDryRun(req) {
336
+ // 复用generate逻辑,但设置dryRun=true
337
+ req.body.dryRun = true;
338
+ return handleGenerateCode(req);
339
+ }
340
+
341
+ /**
342
+ * 验证功能实现
343
+ */
344
+ async function handleVerify(req) {
345
+ const {
346
+ spec,
347
+ code = './src',
348
+ verbose = false
349
+ } = req.body;
350
+
351
+ // 调用verify模块
352
+ // 注意:verifyFeature是为CLI设计的,需要适配为返回结果而非打印
353
+ try {
354
+ const codeDir = path.resolve(code);
355
+
356
+ if (!fs.existsSync(codeDir)) {
357
+ throw new Error(`代码目录不存在: ${codeDir}`);
358
+ }
359
+
360
+ // 收集基本验证数据
361
+ const files = [];
362
+
363
+ async function collectFiles(dir) {
364
+ const entries = await fs.promises.readdir(dir, { withFileTypes: true });
365
+
366
+ for (const entry of entries) {
367
+ const fullPath = path.join(dir, entry.name);
368
+
369
+ if (entry.isDirectory() && !['node_modules', '.git'].includes(entry.name)) {
370
+ await collectFiles(fullPath);
371
+ } else if (entry.isFile()) {
372
+ files.push(fullPath);
373
+ }
374
+ }
375
+ }
376
+
377
+ await collectFiles(codeDir);
378
+
379
+ // 如果有规格文件,进行更详细的验证
380
+ let specData = null;
381
+ if (spec && fs.existsSync(path.resolve(spec))) {
382
+ specData = await parseSpecFile(path.resolve(spec));
383
+ }
384
+
385
+ return {
386
+ verifiedAt: new Date().toISOString(),
387
+ codeDirectory: codeDir,
388
+ totalFiles: files.length,
389
+ specFile: spec ? path.resolve(spec) : null,
390
+ specFeatures: specData ? specData.features.length : null,
391
+ status: 'verified',
392
+ verbose: verbose,
393
+ message: '验证完成(完整报告请使用 pdd verify CLI命令)'
394
+ };
395
+
396
+ } catch (error) {
397
+ throw new Error(`验证失败: ${error.message}`);
398
+ }
399
+ }
400
+
401
+ /**
402
+ * 快速验证
403
+ */
404
+ async function handleQuickVerify(req) {
405
+ // 简化版验证,只做基础检查
406
+ const { code = './src' } = req.body;
407
+ const codeDir = path.resolve(code);
408
+
409
+ const checks = {
410
+ directoryExists: fs.existsSync(codeDir),
411
+ hasPackageJson: false,
412
+ hasReadme: false,
413
+ hasTestFiles: false,
414
+ fileCount: 0
415
+ };
416
+
417
+ if (checks.directoryExists) {
418
+ checks.hasPackageJson = fs.existsSync(path.join(codeDir, 'package.json'));
419
+ checks.hasReadme = fs.existsSync(path.join(codeDir, 'README.md'));
420
+
421
+ // 统计文件数
422
+ async function countFiles(dir) {
423
+ const entries = await fs.promises.readdir(dir, { withFileTypes: true });
424
+
425
+ for (const entry of entries) {
426
+ const fullPath = path.join(dir, entry.name);
427
+
428
+ if (entry.isDirectory() && !['node_modules', '.git', 'dist', 'build'].includes(entry.name)) {
429
+ await countFiles(fullPath);
430
+ } else if (entry.isFile() && (entry.name.includes('.test.') || entry.name.includes('.spec.'))) {
431
+ checks.hasTestFiles = true;
432
+ }
433
+
434
+ if (entry.isFile()) {
435
+ checks.fileCount++;
436
+ }
437
+ }
438
+ }
439
+
440
+ await countFiles(codeDir);
441
+ }
442
+
443
+ const passedChecks = Object.values(checks).filter(v => v === true).length;
444
+ const totalChecks = Object.keys(checks).length - 1; // 排除fileCount
445
+
446
+ return {
447
+ verifiedAt: new Date().toISOString(),
448
+ codeDirectory: codeDir,
449
+ checks,
450
+ summary: {
451
+ passed: passedChecks,
452
+ total: totalChecks,
453
+ passRate: `${Math.round((passedChecks / totalChecks) * 100)}%`,
454
+ status: passedChecks === totalChecks ? 'passed' : 'warning'
455
+ }
456
+ };
457
+ }
458
+
459
+ /**
460
+ * 生成报告
461
+ */
462
+ async function handleGenerateReport(req) {
463
+ const {
464
+ type = 'md',
465
+ output = './reports/pdd-report',
466
+ includeStats = true,
467
+ includeCharts = false
468
+ } = req.body;
469
+
470
+ const projectDir = process.cwd();
471
+ const data = await collectProjectData(projectDir);
472
+
473
+ // 根据类型生成不同格式
474
+ const outputPath = path.resolve(output);
475
+ const outputDir = path.dirname(outputPath);
476
+
477
+ if (!fs.existsSync(outputDir)) {
478
+ await fs.promises.mkdir(outputDir, { recursive: true });
479
+ }
480
+
481
+ // 保存报告数据(实际文件生成在report模块中完成)
482
+ const reportData = {
483
+ generatedAt: new Date().toISOString(),
484
+ type: type.toLowerCase(),
485
+ outputPath: outputPath + '.' + type.toLowerCase(),
486
+ projectData: data,
487
+ options: { includeStats, includeCharts }
488
+ };
489
+
490
+ // 如果是JSON格式,直接返回数据
491
+ if (type.toLowerCase() === 'json') {
492
+ return reportData;
493
+ }
494
+
495
+ return {
496
+ message: `报告已排队生成`,
497
+ format: type.toUpperCase(),
498
+ outputPath: reportData.outputPath,
499
+ preview: {
500
+ totalFiles: data.structure.totalFiles,
501
+ skillsCount: data.skills.length,
502
+ specsCount: data.specs.length,
503
+ testsCount: data.tests.length
504
+ }
505
+ };
506
+ }
507
+
508
+ /**
509
+ * 项目统计信息(轻量级)
510
+ */
511
+ async function handleProjectStats(req) {
512
+ const projectDir = process.cwd();
513
+
514
+ // 快速统计,不深入遍历
515
+ const stats = {
516
+ name: '',
517
+ version: '',
518
+ fileTypes: {},
519
+ quickCounts: {
520
+ skills: 0,
521
+ specs: 0,
522
+ tests: 0
523
+ }
524
+ };
525
+
526
+ // 读取package.json
527
+ try {
528
+ const pkg = JSON.parse(await fs.promises.readFile(
529
+ path.join(projectDir, 'package.json'), 'utf-8'
530
+ ));
531
+ stats.name = pkg.name;
532
+ stats.version = pkg.version;
533
+ } catch {}
534
+
535
+ // 快速统计目录
536
+ const dirsToCheck = [
537
+ { name: 'skills', dir: 'skills' },
538
+ { name: 'specs', dir: 'dev-specs' },
539
+ { name: 'tests', dir: 'tests' }
540
+ ];
541
+
542
+ for (const { name, dir } of dirsToCheck) {
543
+ const fullPath = path.join(projectDir, dir);
544
+ if (fs.existsSync(fullPath)) {
545
+ try {
546
+ const files = await fs.promises.readdir(fullPath);
547
+ stats.quickCounts[name] = files.filter(f =>
548
+ f.endsWith('.md') || f.endsWith('.js')
549
+ ).length;
550
+ } catch {}
551
+ }
552
+ }
553
+
554
+ stats.collectedAt = new Date().toISOString();
555
+
556
+ return stats;
557
+ }
558
+
559
+ /**
560
+ * 获取配置
561
+ */
562
+ async function handleGetConfig(req) {
563
+ const configPath = findConfigFile();
564
+ const config = await loadConfig(configPath);
565
+
566
+ return {
567
+ configFile: configPath || '未找到配置文件(使用默认配置)',
568
+ config: config,
569
+ isDefault: !configPath
570
+ };
571
+ }
572
+
573
+ /**
574
+ * 更新配置
575
+ */
576
+ async function handleUpdateConfig(req) {
577
+ const { updates } = req.body;
578
+
579
+ if (!updates || typeof updates !== 'object') {
580
+ throw new Error('请提供有效的配置更新对象');
581
+ }
582
+
583
+ const configPath = findConfigFile() || path.join(process.cwd(), 'config', 'config.yaml');
584
+ const config = await loadConfig(configPath);
585
+
586
+ // 应用更新
587
+ for (const [key, value] of Object.entries(updates)) {
588
+ if (key in config) {
589
+ if (typeof value === 'object' && !Array.isArray(value)) {
590
+ Object.assign(config[key], value);
591
+ } else {
592
+ config[key] = value;
593
+ }
594
+ }
595
+ }
596
+
597
+ // 保存配置
598
+ const { saveConfig } = await import('./config-manager.js');
599
+ await saveConfig(config, configPath);
600
+
601
+ return {
602
+ message: '配置已更新',
603
+ configFile: configPath,
604
+ updatedKeys: Object.keys(updates),
605
+ config: config
606
+ };
607
+ }
608
+
609
+ /**
610
+ * 重置配置
611
+ */
612
+ async function handleResetConfig(req) {
613
+ const { DEFAULT_CONFIG } = await import('./config-manager.js');
614
+ const configPath = findConfigFile() || path.join(process.cwd(), 'config', 'config.yaml');
615
+
616
+ const { saveConfig } = await import('./config-manager.js');
617
+ await saveConfig({ ...DEFAULT_CONFIG }, configPath);
618
+
619
+ return {
620
+ message: '配置已重置为默认值',
621
+ configFile: configPath,
622
+ defaultConfig: DEFAULT_CONFIG
623
+ };
624
+ }
625
+
626
+ /**
627
+ * 列出所有技能
628
+ */
629
+ async function handleListSkills(req) {
630
+ const skillsDir = path.join(process.cwd(), 'skills');
631
+
632
+ if (!fs.existsSync(skillsDir)) {
633
+ return {
634
+ skills: [],
635
+ count: 0,
636
+ message: '未找到skills目录'
637
+ };
638
+ }
639
+
640
+ const categories = await fs.promises.readdir(skillsDir);
641
+ const allSkills = [];
642
+
643
+ for (const category of categories) {
644
+ const categoryPath = path.join(skillsDir, category);
645
+
646
+ if (!fs.statSync(categoryPath).isDirectory()) continue;
647
+
648
+ const skillFiles = (await fs.promises.readdir(categoryPath))
649
+ .filter(f => f.endsWith('.md'));
650
+
651
+ for (const skillFile of skillFiles) {
652
+ allSkills.push({
653
+ name: skillFile.replace('.md', ''),
654
+ category,
655
+ path: path.join('skills', category, skillFile)
656
+ });
657
+ }
658
+ }
659
+
660
+ return {
661
+ skills: allSkills,
662
+ count: allSkills.length,
663
+ categories: categories.filter(c =>
664
+ fs.statSync(path.join(skillsDir, c)).isDirectory()
665
+ )
666
+ };
667
+ }
668
+
669
+ /**
670
+ * 按分类列出技能
671
+ */
672
+ async function handleListSkillsByCategory(req) {
673
+ const { category } = req.params;
674
+ const categoryPath = path.join(process.cwd(), 'skills', category);
675
+
676
+ if (!fs.existsSync(categoryPath)) {
677
+ throw new Error(`分类不存在: ${category}`);
678
+ }
679
+
680
+ const skillFiles = (await fs.promises.readdir(categoryPath))
681
+ .filter(f => f.endsWith('.md'));
682
+
683
+ const skills = skillFiles.map(file => ({
684
+ name: file.replace('.md', ''),
685
+ path: path.join('skills', category, file)
686
+ }));
687
+
688
+ return {
689
+ category,
690
+ skills,
691
+ count: skills.length
692
+ };
693
+ }
694
+
695
+ /**
696
+ * 获取技能详情
697
+ */
698
+ async function handleGetSkillDetail(req) {
699
+ const { category, name } = req.params;
700
+ const skillPath = path.join(process.cwd(), 'skills', category, `${name}.md`);
701
+
702
+ if (!fs.existsSync(skillPath)) {
703
+ throw new Error(`技能不存在: ${category}/${name}`);
704
+ }
705
+
706
+ const content = await fs.promises.readFile(skillPath, 'utf-8');
707
+
708
+ // 提取基本信息
709
+ const titleMatch = content.match(/^#\s+(.+)$/m);
710
+ const descMatch = content.match(/description:\s*(.+)/i);
711
+ const triggersMatch = content.match(/triggers:\s*\n((?:-\s*.+\n?)+)/i);
712
+
713
+ return {
714
+ name,
715
+ category,
716
+ path: skillPath,
717
+ title: titleMatch ? titleMatch[1] : name,
718
+ description: descMatch ? descMatch[1].trim() : '',
719
+ triggers: triggersMatch
720
+ ? triggersMatch[1].split('\n')
721
+ .filter(l => l.trim())
722
+ .map(l => l.replace(/^-\s*/, '').trim())
723
+ : [],
724
+ contentLength: content.length,
725
+ lines: content.split('\n').length,
726
+ lastModified: (await fs.promises.stat(skillPath)).mtime.toISOString()
727
+ };
728
+ }
729
+
730
+ // ==================== 工具函数 ====================
731
+
732
+ /**
733
+ * 格式化运行时间
734
+ * @param {number} seconds - 秒数
735
+ * @returns {string} 格式化的时间字符串
736
+ */
737
+ function formatUptime(seconds) {
738
+ const days = Math.floor(seconds / 86400);
739
+ const hours = Math.floor((seconds % 86400) / 3600);
740
+ const minutes = Math.floor((seconds % 3600) / 60);
741
+ const secs = Math.floor(seconds % 60);
742
+
743
+ const parts = [];
744
+ if (days > 0) parts.push(`${days}天`);
745
+ if (hours > 0) parts.push(`${hours}小时`);
746
+ if (minutes > 0) parts.push(`${minutes}分钟`);
747
+ parts.push(`${secs}秒`);
748
+
749
+ return parts.join(' ');
750
+ }