super-dev 2.3.7__tar.gz → 2.3.8__tar.gz

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 (185) hide show
  1. {super_dev-2.3.7/super_dev.egg-info → super_dev-2.3.8}/PKG-INFO +6 -6
  2. {super_dev-2.3.7 → super_dev-2.3.8}/README.md +5 -5
  3. {super_dev-2.3.7 → super_dev-2.3.8}/pyproject.toml +1 -1
  4. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/__init__.py +1 -1
  5. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/analyzer.py +3 -11
  6. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/dependency_graph.py +13 -4
  7. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/detectors.py +67 -21
  8. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/feature_checklist.py +29 -8
  9. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/impact.py +61 -17
  10. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/models.py +32 -26
  11. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/product_audit.py +16 -4
  12. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/regression_guard.py +3 -1
  13. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/repo_map.py +21 -6
  14. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/branding.py +1 -1
  15. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/catalogs.py +8 -0
  16. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli.py +117 -84
  17. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_analysis_mixin.py +3 -3
  18. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_deploy_runtime_mixin.py +125 -36
  19. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_experience_mixin.py +340 -70
  20. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_governance_mixin.py +59 -36
  21. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_host_ops_mixin.py +87 -17
  22. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_host_report_renderers.py +32 -15
  23. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_parser_mixin.py +82 -23
  24. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_spec_mixin.py +25 -28
  25. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/config/frontend.py +6 -11
  26. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/config/manager.py +20 -8
  27. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/config/schema_validator.py +13 -0
  28. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/adr_generator.py +28 -22
  29. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/creator.py +17 -19
  30. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/document_generator.py +171 -90
  31. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/document_generator_content_mixin.py +557 -185
  32. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/frontend_builder.py +124 -100
  33. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/implementation_builder.py +273 -243
  34. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/prompt_generator.py +9 -3
  35. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/prompt_templates.py +17 -4
  36. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/requirement_parser.py +315 -66
  37. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/spec_builder.py +12 -12
  38. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/task_executor.py +22 -17
  39. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/deployers/cicd.py +1 -2
  40. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/deployers/delivery.py +32 -14
  41. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/deployers/migration.py +212 -146
  42. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/deployers/rehearsal.py +6 -3
  43. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/deployers/rehearsal_runner.py +75 -26
  44. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/__init__.py +2 -1
  45. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/aesthetics.py +89 -39
  46. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/charts.py +71 -39
  47. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/codegen.py +45 -45
  48. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/engine.py +207 -51
  49. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/generator.py +33 -29
  50. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/landing.py +43 -31
  51. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/tech_stack.py +45 -50
  52. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/tokens.py +0 -1
  53. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/ui_intelligence.py +1503 -320
  54. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/design/ux_guide.py +41 -41
  55. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/enforcement/host_hooks.py +6 -3
  56. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/enforcement/validation.py +6 -6
  57. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/experts/service.py +4 -1
  58. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/framework_harness.py +45 -19
  59. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/frameworks.py +15 -5
  60. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/guard.py +1 -3
  61. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/hook_harness.py +15 -5
  62. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/hooks/manager.py +5 -1
  63. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/host_adapters.py +16 -3
  64. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/integrations/manager.py +26 -3
  65. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/integrations/manager_content_mixin.py +29 -0
  66. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/knowledge_evolution.py +100 -55
  67. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/knowledge_tracker.py +34 -21
  68. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/migrate.py +1 -3
  69. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/operational_harness.py +26 -8
  70. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/contracts.py +9 -3
  71. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/engine.py +26 -28
  72. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/experts.py +91 -65
  73. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/governance.py +13 -17
  74. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/knowledge.py +98 -31
  75. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/knowledge_pusher.py +107 -88
  76. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/overseer.py +5 -12
  77. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/plan_executor.py +14 -12
  78. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/quality.py +73 -51
  79. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/telemetry.py +18 -4
  80. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/pipeline_cost.py +0 -1
  81. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/policy/manager.py +14 -4
  82. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/proof_pack.py +153 -64
  83. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/protocols/a2a.py +1 -1
  84. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/release_readiness.py +124 -41
  85. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/retry.py +2 -1
  86. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/review_state.py +9 -3
  87. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/code_review.py +114 -98
  88. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/quality_gate.py +6 -12
  89. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/ui_review.py +270 -75
  90. super_dev-2.3.8/super_dev/runtime_evidence.py +377 -0
  91. super_dev-2.3.8/super_dev/seeai_design_system.py +288 -0
  92. super_dev-2.3.8/super_dev/seeai_smoke_scenarios.py +130 -0
  93. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/sequential_thinking.py +71 -15
  94. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/session_checkpoint.py +1 -1
  95. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/skills/skill_template.py +160 -27
  96. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/specs/generator.py +56 -52
  97. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/specs/manager.py +107 -58
  98. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/specs/models.py +65 -97
  99. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/terminal.py +5 -4
  100. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/utils/__init__.py +1 -1
  101. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/api.py +122 -49
  102. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/routers/workflow.py +2 -0
  103. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/workflow_contract.py +7 -5
  104. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/workflow_harness.py +28 -11
  105. {super_dev-2.3.7 → super_dev-2.3.8/super_dev.egg-info}/PKG-INFO +6 -6
  106. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev.egg-info/SOURCES.txt +2 -0
  107. super_dev-2.3.7/super_dev/runtime_evidence.py +0 -203
  108. {super_dev-2.3.7 → super_dev-2.3.8}/LICENSE +0 -0
  109. {super_dev-2.3.7 → super_dev-2.3.8}/setup.cfg +0 -0
  110. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/_enforcement_bridge.py +0 -0
  111. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/analyzer/__init__.py +0 -0
  112. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/cli_release_quality_mixin.py +0 -0
  113. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/completion.py +0 -0
  114. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/config/__init__.py +0 -0
  115. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/__init__.py +0 -0
  116. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/api_contract.py +0 -0
  117. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/compact_template.py +0 -0
  118. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/component_scaffold.py +0 -0
  119. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/nextjs_scaffold.py +0 -0
  120. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/creators/prompt_sections.py +0 -0
  121. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/deployers/__init__.py +0 -0
  122. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/enforcement/__init__.py +0 -0
  123. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/enforcement/pre_code_gate.py +0 -0
  124. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/error_handler.py +0 -0
  125. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/exceptions.py +0 -0
  126. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/experts/__init__.py +0 -0
  127. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/experts/behavioral_prompts.py +0 -0
  128. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/experts/loader.py +0 -0
  129. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/experts/review_protocol.py +0 -0
  130. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/experts/toolkit.py +0 -0
  131. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/harness_registry.py +0 -0
  132. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/hooks/__init__.py +0 -0
  133. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/hooks/models.py +0 -0
  134. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/host_registry.py +0 -0
  135. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/i18n.py +0 -0
  136. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/integrations/__init__.py +0 -0
  137. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/integrations/install_manifest.py +0 -0
  138. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/memory/__init__.py +0 -0
  139. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/memory/consolidator.py +0 -0
  140. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/memory/extractor.py +0 -0
  141. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/memory/store.py +0 -0
  142. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/merge_safety.py +0 -0
  143. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/metrics/__init__.py +0 -0
  144. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/metrics/pipeline_metrics.py +0 -0
  145. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/onboarding.py +0 -0
  146. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/__init__.py +0 -0
  147. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/orchestrator/context_compact.py +0 -0
  148. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/policy/__init__.py +0 -0
  149. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/project_templates.py +0 -0
  150. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/protocols/__init__.py +0 -0
  151. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/protocols/output_schemas.py +0 -0
  152. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reminders.py +0 -0
  153. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/__init__.py +0 -0
  154. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/external_reviews.py +0 -0
  155. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/quality_advisor.py +0 -0
  156. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/redteam.py +0 -0
  157. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/review_agents.py +0 -0
  158. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/rules/__init__.py +0 -0
  159. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/reviewers/validation_rules.py +0 -0
  160. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/rules/__init__.py +0 -0
  161. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/rules/loader.py +0 -0
  162. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/session/__init__.py +0 -0
  163. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/session/brief.py +0 -0
  164. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/skills/__init__.py +0 -0
  165. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/skills/manager.py +0 -0
  166. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/specs/__init__.py +0 -0
  167. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/specs/consistency_checker.py +0 -0
  168. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/specs/traceability.py +0 -0
  169. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/specs/validator.py +0 -0
  170. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/tips.py +0 -0
  171. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/utils/logger.py +0 -0
  172. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/utils/structured_logging.py +0 -0
  173. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/version_check.py +0 -0
  174. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/helpers.py +0 -0
  175. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/rate_limit.py +0 -0
  176. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/routers/__init__.py +0 -0
  177. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/routers/config_routes.py +0 -0
  178. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/routers/experts.py +0 -0
  179. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/web/routers/health.py +0 -0
  180. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/webhooks.py +0 -0
  181. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev/workflow_state.py +0 -0
  182. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev.egg-info/dependency_links.txt +0 -0
  183. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev.egg-info/entry_points.txt +0 -0
  184. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev.egg-info/requires.txt +0 -0
  185. {super_dev-2.3.7 → super_dev-2.3.8}/super_dev.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: super-dev
3
- Version: 2.3.7
3
+ Version: 2.3.8
4
4
  Summary: Super Dev - Pipeline AI Coding Assistant
5
5
  Author-email: Excellent <11964948@qq.com>
6
6
  License-Expression: MIT
@@ -60,9 +60,9 @@ Dynamic: license-file
60
60
 
61
61
  ## 版本
62
62
 
63
- 当前版本:`2.3.6`
63
+ 当前版本:`2.3.8`
64
64
 
65
- - 发布说明:[v2.3.6 更新内容](docs/releases/2.3.6.md)
65
+ - 发布说明:[v2.3.8 更新内容](docs/releases/2.3.8.md)
66
66
  - 官网更新历史:[superdev.goder.ai/changelog](https://superdev.goder.ai/changelog)
67
67
 
68
68
  ---
@@ -437,13 +437,13 @@ super-dev
437
437
  ### 3. 指定版本安装
438
438
 
439
439
  ```bash
440
- pip install super-dev==2.3.6
440
+ pip install super-dev==2.3.8
441
441
  ```
442
442
 
443
443
  ### 4. GitHub 指定标签安装
444
444
 
445
445
  ```bash
446
- pip install git+https://github.com/shangyankeji/super-dev.git@v2.3.6
446
+ pip install git+https://github.com/shangyankeji/super-dev.git@v2.3.8
447
447
  ```
448
448
 
449
449
  ### 5. 源码开发安装
@@ -614,7 +614,7 @@ super-dev bootstrap --name my-project --platform web --frontend next --backend n
614
614
 
615
615
  ## 架构概览
616
616
 
617
- Super Dev 2.3.6 架构由四层组成:**宿主接入层**(20 个统一接入宿主 + 1 个 OpenClaw 手动插件宿主)、**知识治理层**(306 索引 / 渐进式加载 / 自演化)、**编排引擎层**(9 阶段流水线 / 11 专家 + Overseer / 验证规则引擎)、**交付审计层**(DORA 度量 / ADR / 一致性检测 / proof-pack)。
617
+ Super Dev 2.3.8 架构由四层组成:**宿主接入层**(20 个统一接入宿主 + 1 个 OpenClaw 手动插件宿主)、**知识治理层**(306 索引 / 渐进式加载 / 自演化)、**编排引擎层**(9 阶段流水线 / 11 专家 + Overseer / 验证规则引擎)、**交付审计层**(DORA 度量 / ADR / 一致性检测 / proof-pack)。
618
618
 
619
619
  ### 一、系统高阶流转架构
620
620
 
@@ -19,9 +19,9 @@
19
19
 
20
20
  ## 版本
21
21
 
22
- 当前版本:`2.3.6`
22
+ 当前版本:`2.3.8`
23
23
 
24
- - 发布说明:[v2.3.6 更新内容](docs/releases/2.3.6.md)
24
+ - 发布说明:[v2.3.8 更新内容](docs/releases/2.3.8.md)
25
25
  - 官网更新历史:[superdev.goder.ai/changelog](https://superdev.goder.ai/changelog)
26
26
 
27
27
  ---
@@ -396,13 +396,13 @@ super-dev
396
396
  ### 3. 指定版本安装
397
397
 
398
398
  ```bash
399
- pip install super-dev==2.3.6
399
+ pip install super-dev==2.3.8
400
400
  ```
401
401
 
402
402
  ### 4. GitHub 指定标签安装
403
403
 
404
404
  ```bash
405
- pip install git+https://github.com/shangyankeji/super-dev.git@v2.3.6
405
+ pip install git+https://github.com/shangyankeji/super-dev.git@v2.3.8
406
406
  ```
407
407
 
408
408
  ### 5. 源码开发安装
@@ -573,7 +573,7 @@ super-dev bootstrap --name my-project --platform web --frontend next --backend n
573
573
 
574
574
  ## 架构概览
575
575
 
576
- Super Dev 2.3.6 架构由四层组成:**宿主接入层**(20 个统一接入宿主 + 1 个 OpenClaw 手动插件宿主)、**知识治理层**(306 索引 / 渐进式加载 / 自演化)、**编排引擎层**(9 阶段流水线 / 11 专家 + Overseer / 验证规则引擎)、**交付审计层**(DORA 度量 / ADR / 一致性检测 / proof-pack)。
576
+ Super Dev 2.3.8 架构由四层组成:**宿主接入层**(20 个统一接入宿主 + 1 个 OpenClaw 手动插件宿主)、**知识治理层**(306 索引 / 渐进式加载 / 自演化)、**编排引擎层**(9 阶段流水线 / 11 专家 + Overseer / 验证规则引擎)、**交付审计层**(DORA 度量 / ADR / 一致性检测 / proof-pack)。
577
577
 
578
578
  ### 一、系统高阶流转架构
579
579
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "super-dev"
7
- version = "2.3.7"
7
+ version = "2.3.8"
8
8
  description = "Super Dev - Pipeline AI Coding Assistant"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -6,6 +6,6 @@
6
6
  最后修改:2025-12-30
7
7
  """
8
8
 
9
- __version__ = "2.3.7"
9
+ __version__ = "2.3.8"
10
10
  __author__ = "Excellent"
11
11
  __description__ = "超级开发战队 - 一个宿主内 AI 开发治理与编排工具"
@@ -268,10 +268,7 @@ class ProjectAnalyzer:
268
268
  except Exception:
269
269
  parts = path.parts
270
270
 
271
- return any(
272
- part.startswith(".") or part in self._ignored_dir_names
273
- for part in parts
274
- )
271
+ return any(part.startswith(".") or part in self._ignored_dir_names for part in parts)
275
272
 
276
273
  def _check_file_for_patterns(
277
274
  self, file_path: Path, patterns: list[DesignPattern], language: str
@@ -295,9 +292,7 @@ class ProjectAnalyzer:
295
292
  except (OSError, UnicodeDecodeError):
296
293
  pass
297
294
 
298
- def _detect_python_ast_patterns(
299
- self, file_path: Path, patterns: list[DesignPattern]
300
- ) -> None:
295
+ def _detect_python_ast_patterns(self, file_path: Path, patterns: list[DesignPattern]) -> None:
301
296
  """使用 AST 检测 Python 设计模式"""
302
297
  try:
303
298
  content = file_path.read_text(encoding="utf-8")
@@ -465,7 +460,4 @@ class ProjectAnalyzer:
465
460
  if total == 0:
466
461
  return {}
467
462
 
468
- return {
469
- lang: (count / total) * 100
470
- for lang, count in self._report.languages_used.items()
471
- }
463
+ return {lang: (count / total) * 100 for lang, count in self._report.languages_used.items()}
@@ -124,7 +124,9 @@ class DependencyGraphBuilder:
124
124
 
125
125
  def build(self) -> DependencyGraphReport:
126
126
  files = self._collect_source_files()
127
- path_index = {str(path.relative_to(self.project_dir)).replace("\\", "/"): path for path in files}
127
+ path_index = {
128
+ str(path.relative_to(self.project_dir)).replace("\\", "/"): path for path in files
129
+ }
128
130
  module_index = self._build_module_index(files)
129
131
  edges = self._build_edges(files, module_index, path_index)
130
132
  inbound, outbound = self._degree(edges)
@@ -152,7 +154,9 @@ class DependencyGraphBuilder:
152
154
  md_path = self.output_dir / f"{self.project_name}-dependency-graph.md"
153
155
  json_path = self.output_dir / f"{self.project_name}-dependency-graph.json"
154
156
  md_path.write_text(report.to_markdown(), encoding="utf-8")
155
- json_path.write_text(json.dumps(report.to_dict(), ensure_ascii=False, indent=2), encoding="utf-8")
157
+ json_path.write_text(
158
+ json.dumps(report.to_dict(), ensure_ascii=False, indent=2), encoding="utf-8"
159
+ )
156
160
  return {"markdown": md_path, "json": json_path}
157
161
 
158
162
  def _collect_source_files(self) -> list[Path]:
@@ -244,7 +248,10 @@ class DependencyGraphBuilder:
244
248
  @staticmethod
245
249
  def _extract_js_imports(content: str) -> list[tuple[str, str]]:
246
250
  imports: list[tuple[str, str]] = []
247
- for match in re.finditer(r"""from\s+['"]([^'"]+)['"]|require\(\s*['"]([^'"]+)['"]\s*\)|import\(\s*['"]([^'"]+)['"]\s*\)""", content):
251
+ for match in re.finditer(
252
+ r"""from\s+['"]([^'"]+)['"]|require\(\s*['"]([^'"]+)['"]\s*\)|import\(\s*['"]([^'"]+)['"]\s*\)""",
253
+ content,
254
+ ):
248
255
  raw = match.group(1) or match.group(2) or match.group(3)
249
256
  if raw:
250
257
  imports.append((raw, "module-import"))
@@ -312,7 +319,9 @@ class DependencyGraphBuilder:
312
319
  role = "entry-point" if rel in entry_paths else "internal"
313
320
  if score > 0 or role == "entry-point":
314
321
  nodes.append(
315
- DependencyNode(path=rel, inbound=in_count, outbound=out_count, score=score, role=role)
322
+ DependencyNode(
323
+ path=rel, inbound=in_count, outbound=out_count, score=score, role=role
324
+ )
316
325
  )
317
326
  nodes.sort(key=lambda item: (item.score, item.inbound, item.outbound), reverse=True)
318
327
  return nodes[:10]
@@ -97,16 +97,30 @@ def _detect_node_project_type(project_path: Path) -> ProjectCategory:
97
97
 
98
98
  # 检测前端框架
99
99
  frontend_frameworks = [
100
- "react", "react-dom", "vue", "vue-router", "@angular/core",
101
- "angular", "svelte", "next", "nuxt", "@remix-run/react",
100
+ "react",
101
+ "react-dom",
102
+ "vue",
103
+ "vue-router",
104
+ "@angular/core",
105
+ "angular",
106
+ "svelte",
107
+ "next",
108
+ "nuxt",
109
+ "@remix-run/react",
102
110
  ]
103
111
 
104
112
  has_frontend = any(fw in all_deps for fw in frontend_frameworks)
105
113
 
106
114
  # 检测后端框架
107
115
  backend_frameworks = [
108
- "express", "fastify", "koa", "nest", "@nestjs/common",
109
- "hapi", "feathers", "socket.io",
116
+ "express",
117
+ "fastify",
118
+ "koa",
119
+ "nest",
120
+ "@nestjs/common",
121
+ "hapi",
122
+ "feathers",
123
+ "socket.io",
110
124
  ]
111
125
 
112
126
  has_backend = any(bw in all_deps for bw in backend_frameworks)
@@ -159,16 +173,27 @@ def _detect_python_project_type(project_path: Path) -> ProjectCategory:
159
173
 
160
174
  # 检测 Web 框架
161
175
  web_frameworks = {
162
- "django", "flask", "fastapi", "starlette", "tornado",
163
- "aiohttp", "sanic", "quart",
176
+ "django",
177
+ "flask",
178
+ "fastapi",
179
+ "starlette",
180
+ "tornado",
181
+ "aiohttp",
182
+ "sanic",
183
+ "quart",
164
184
  }
165
185
 
166
186
  has_web = any(fw in dependencies for fw in web_frameworks)
167
187
 
168
188
  # 检测前端相关
169
189
  frontend_related = {
170
- "webpack", "vite", "rollup", "parcel",
171
- "react", "vue", "angular",
190
+ "webpack",
191
+ "vite",
192
+ "rollup",
193
+ "parcel",
194
+ "react",
195
+ "vue",
196
+ "angular",
172
197
  }
173
198
 
174
199
  has_frontend = any(fr in dependencies for fr in frontend_related)
@@ -272,9 +297,15 @@ def _detect_node_tech_stack(project_path: Path, category: ProjectCategory) -> Te
272
297
  # 检测 UI 库
273
298
  ui_library = ""
274
299
  ui_libraries = [
275
- "@mui/material", "@chakra-ui/react", "@mantine/core",
276
- "antd", "react-bootstrap", "tailwindcss",
277
- "element-plus", "vuetify", "antd-mobile",
300
+ "@mui/material",
301
+ "@chakra-ui/react",
302
+ "@mantine/core",
303
+ "antd",
304
+ "react-bootstrap",
305
+ "tailwindcss",
306
+ "element-plus",
307
+ "vuetify",
308
+ "antd-mobile",
278
309
  ]
279
310
  for lib in ui_libraries:
280
311
  if lib in all_deps:
@@ -284,8 +315,14 @@ def _detect_node_tech_stack(project_path: Path, category: ProjectCategory) -> Te
284
315
  # 检测状态管理
285
316
  state_management = ""
286
317
  state_libs = [
287
- "redux", "@reduxjs/toolkit", "zustand", "jotai",
288
- "recoil", "mobx", "pinia", "vuex",
318
+ "redux",
319
+ "@reduxjs/toolkit",
320
+ "zustand",
321
+ "jotai",
322
+ "recoil",
323
+ "mobx",
324
+ "pinia",
325
+ "vuex",
289
326
  ]
290
327
  for lib in state_libs:
291
328
  if lib in all_deps:
@@ -295,8 +332,12 @@ def _detect_node_tech_stack(project_path: Path, category: ProjectCategory) -> Te
295
332
  # 检测构建工具
296
333
  build_tool = ""
297
334
  build_tools = [
298
- "vite", "webpack", "rollup", "parcel",
299
- "esbuild", "turbo",
335
+ "vite",
336
+ "webpack",
337
+ "rollup",
338
+ "parcel",
339
+ "esbuild",
340
+ "turbo",
300
341
  ]
301
342
  for tool in build_tools:
302
343
  if tool in all_deps:
@@ -306,8 +347,12 @@ def _detect_node_tech_stack(project_path: Path, category: ProjectCategory) -> Te
306
347
  # 检测测试框架
307
348
  testing_framework = ""
308
349
  test_frameworks = [
309
- "jest", "vitest", "@testing-library/react",
310
- "mocha", "chai", "jasmine",
350
+ "jest",
351
+ "vitest",
352
+ "@testing-library/react",
353
+ "mocha",
354
+ "chai",
355
+ "jasmine",
311
356
  ]
312
357
  for fw in test_frameworks:
313
358
  if fw in all_deps:
@@ -364,9 +409,7 @@ def _detect_python_tech_stack(project_path: Path, category: ProjectCategory) ->
364
409
  if match:
365
410
  name = match.group(1)
366
411
  version = match.group(3) or ""
367
- dependencies.append(
368
- Dependency(name=name, version=version, type="prod")
369
- )
412
+ dependencies.append(Dependency(name=name, version=version, type="prod"))
370
413
  except OSError:
371
414
  pass
372
415
 
@@ -514,7 +557,10 @@ def _detect_node_architecture(project_path: Path, dirs: list[str]) -> Architectu
514
557
 
515
558
  # 整洁架构检测
516
559
  clean_arch_indicators = [
517
- "domain", "use-cases", "application", "infrastructure",
560
+ "domain",
561
+ "use-cases",
562
+ "application",
563
+ "infrastructure",
518
564
  ]
519
565
  if any(ind in src_dirs for ind in clean_arch_indicators):
520
566
  return ArchitecturePattern.CLEAN_ARCHITECTURE
@@ -20,7 +20,15 @@ GAP_KEYWORDS = ("未实现", "待实现", "未完成", "missing", "not implement
20
20
  PRIORITY_PATTERN = re.compile(r"\b(P[0-3])\b", re.IGNORECASE)
21
21
  EXPLICIT_GAP_SOURCE_KEYWORDS = ("gap", "research", "execution-plan", "coverage", "compare")
22
22
  EXPLICIT_GAP_SECTION_KEYWORDS = ("missing", "gap", "未实现", "待实现", "差距", "缺口", "coverage")
23
- FEATURE_GROUP_HEADING_KEYWORDS = ("核心功能", "扩展功能", "高级功能", "功能模块", "核心模块", "mvp", "phase")
23
+ FEATURE_GROUP_HEADING_KEYWORDS = (
24
+ "核心功能",
25
+ "扩展功能",
26
+ "高级功能",
27
+ "功能模块",
28
+ "核心模块",
29
+ "mvp",
30
+ "phase",
31
+ )
24
32
  NON_FEATURE_HEADING_KEYWORDS = (
25
33
  "用户故事",
26
34
  "优先级",
@@ -95,7 +103,9 @@ class FeatureCoverageReport:
95
103
  }
96
104
 
97
105
  def to_markdown(self) -> str:
98
- coverage_text = f"{self.coverage_rate:.1f}%" if self.coverage_rate is not None else "unknown"
106
+ coverage_text = (
107
+ f"{self.coverage_rate:.1f}%" if self.coverage_rate is not None else "unknown"
108
+ )
99
109
  lines = [
100
110
  "# Feature Checklist",
101
111
  "",
@@ -172,7 +182,9 @@ class FeatureChecklistBuilder:
172
182
  )
173
183
 
174
184
  total_features = len(items)
175
- coverage_rate = None if total_features == 0 else round((covered_count / total_features) * 100, 1)
185
+ coverage_rate = (
186
+ None if total_features == 0 else round((covered_count / total_features) * 100, 1)
187
+ )
176
188
  if explicit_gaps:
177
189
  status = "partial"
178
190
  elif total_features == 0:
@@ -182,7 +194,9 @@ class FeatureChecklistBuilder:
182
194
  else:
183
195
  status = "partial"
184
196
 
185
- summary = self._summary(status, coverage_rate, explicit_gaps, total_features, covered_count, unknown_count)
197
+ summary = self._summary(
198
+ status, coverage_rate, explicit_gaps, total_features, covered_count, unknown_count
199
+ )
186
200
  return FeatureCoverageReport(
187
201
  project_name=self.project_name,
188
202
  project_path=str(self.project_dir),
@@ -204,7 +218,9 @@ class FeatureChecklistBuilder:
204
218
  md_path = self.output_dir / f"{self.project_name}-feature-checklist.md"
205
219
  json_path = self.output_dir / f"{self.project_name}-feature-checklist.json"
206
220
  md_path.write_text(report.to_markdown(), encoding="utf-8")
207
- json_path.write_text(json.dumps(report.to_dict(), ensure_ascii=False, indent=2), encoding="utf-8")
221
+ json_path.write_text(
222
+ json.dumps(report.to_dict(), ensure_ascii=False, indent=2), encoding="utf-8"
223
+ )
208
224
  return {"markdown": md_path, "json": json_path}
209
225
 
210
226
  def _latest(self, pattern: str, base_dir: Path | None = None) -> Path | None:
@@ -250,7 +266,9 @@ class FeatureChecklistBuilder:
250
266
  if (
251
267
  normalized_title
252
268
  and normalized_title not in seen
253
- and not any(keyword in title_lower for keyword in FEATURE_GROUP_HEADING_KEYWORDS)
269
+ and not any(
270
+ keyword in title_lower for keyword in FEATURE_GROUP_HEADING_KEYWORDS
271
+ )
254
272
  ):
255
273
  seen.add(normalized_title)
256
274
  heading_items.append(
@@ -310,11 +328,14 @@ class FeatureChecklistBuilder:
310
328
  heading = re.match(r"^(#{2,4})\s+(.+)$", line)
311
329
  if heading:
312
330
  in_gap_section = any(
313
- keyword in heading.group(2).lower() for keyword in EXPLICIT_GAP_SECTION_KEYWORDS
331
+ keyword in heading.group(2).lower()
332
+ for keyword in EXPLICIT_GAP_SECTION_KEYWORDS
314
333
  )
315
334
  continue
316
335
  priority_match = PRIORITY_PATTERN.search(line)
317
- has_gap_keyword = any(keyword in line.lower() for keyword in GAP_KEYWORDS) or bool(priority_match)
336
+ has_gap_keyword = any(keyword in line.lower() for keyword in GAP_KEYWORDS) or bool(
337
+ priority_match
338
+ )
318
339
  if not in_gap_section and not priority_match:
319
340
  continue
320
341
  if not has_gap_keyword:
@@ -55,7 +55,9 @@ class ImpactAnalysisReport:
55
55
  "summary": self.summary,
56
56
  "affected_modules": [item.to_dict() for item in self.affected_modules],
57
57
  "affected_entry_points": [item.to_dict() for item in self.affected_entry_points],
58
- "affected_integration_surfaces": [item.to_dict() for item in self.affected_integration_surfaces],
58
+ "affected_integration_surfaces": [
59
+ item.to_dict() for item in self.affected_integration_surfaces
60
+ ],
59
61
  "regression_focus": list(self.regression_focus),
60
62
  "recommended_steps": list(self.recommended_steps),
61
63
  }
@@ -75,7 +77,9 @@ class ImpactAnalysisReport:
75
77
  lines.extend(["", self.summary, ""])
76
78
  self._append_items(lines, "Affected Modules", self.affected_modules)
77
79
  self._append_items(lines, "Affected Entry Points", self.affected_entry_points)
78
- self._append_items(lines, "Affected Integration Surfaces", self.affected_integration_surfaces)
80
+ self._append_items(
81
+ lines, "Affected Integration Surfaces", self.affected_integration_surfaces
82
+ )
79
83
  lines.extend(["", "## Regression Focus", ""])
80
84
  if self.regression_focus:
81
85
  for item in self.regression_focus:
@@ -113,14 +117,34 @@ class ImpactAnalyzer:
113
117
  description_tokens = _tokenize(description)
114
118
  normalized_files = [str(Path(file)).replace("\\", "/") for file in files]
115
119
 
116
- affected_modules = self._score_repo_items(repo_map.top_modules, normalized_files, description_tokens, "module")
117
- affected_entry_points = self._score_repo_items(repo_map.entry_points, normalized_files, description_tokens, "entry-point")
118
- affected_surfaces = self._score_repo_items(repo_map.integration_surfaces, normalized_files, description_tokens, "integration-surface")
120
+ affected_modules = self._score_repo_items(
121
+ repo_map.top_modules, normalized_files, description_tokens, "module"
122
+ )
123
+ affected_entry_points = self._score_repo_items(
124
+ repo_map.entry_points, normalized_files, description_tokens, "entry-point"
125
+ )
126
+ affected_surfaces = self._score_repo_items(
127
+ repo_map.integration_surfaces,
128
+ normalized_files,
129
+ description_tokens,
130
+ "integration-surface",
131
+ )
119
132
 
120
133
  risk_level = self._risk_level(affected_modules, affected_entry_points, affected_surfaces)
121
- summary = self._summary(description, normalized_files, risk_level, affected_modules, affected_entry_points, affected_surfaces)
122
- regression_focus = self._regression_focus(affected_modules, affected_surfaces, normalized_files)
123
- recommended_steps = self._recommended_steps(risk_level, affected_modules, affected_surfaces, normalized_files)
134
+ summary = self._summary(
135
+ description,
136
+ normalized_files,
137
+ risk_level,
138
+ affected_modules,
139
+ affected_entry_points,
140
+ affected_surfaces,
141
+ )
142
+ regression_focus = self._regression_focus(
143
+ affected_modules, affected_surfaces, normalized_files
144
+ )
145
+ recommended_steps = self._recommended_steps(
146
+ risk_level, affected_modules, affected_surfaces, normalized_files
147
+ )
124
148
 
125
149
  return ImpactAnalysisReport(
126
150
  project_name=self.project_name,
@@ -140,7 +164,9 @@ class ImpactAnalyzer:
140
164
  md_path = self.output_dir / f"{self.project_name}-impact-analysis.md"
141
165
  json_path = self.output_dir / f"{self.project_name}-impact-analysis.json"
142
166
  md_path.write_text(report.to_markdown(), encoding="utf-8")
143
- json_path.write_text(json.dumps(report.to_dict(), ensure_ascii=False, indent=2), encoding="utf-8")
167
+ json_path.write_text(
168
+ json.dumps(report.to_dict(), ensure_ascii=False, indent=2), encoding="utf-8"
169
+ )
144
170
  return {"markdown": md_path, "json": json_path}
145
171
 
146
172
  def _score_repo_items(
@@ -160,7 +186,11 @@ class ImpactAnalyzer:
160
186
  for file in files:
161
187
  file_lower = file.lower()
162
188
  top = file_lower.split("/")[0]
163
- if item_path == file_lower or item_path.startswith(file_lower) or file_lower.startswith(item_path):
189
+ if (
190
+ item_path == file_lower
191
+ or item_path.startswith(file_lower)
192
+ or file_lower.startswith(item_path)
193
+ ):
164
194
  confidence = max(confidence, 0.95)
165
195
  reasons.append("direct file/path overlap")
166
196
  elif item_path == top or item_path.startswith(f"{top}/") or top == item_path:
@@ -219,19 +249,27 @@ class ImpactAnalyzer:
219
249
  )
220
250
 
221
251
  @staticmethod
222
- def _regression_focus(modules: list[ImpactItem], surfaces: list[ImpactItem], files: list[str]) -> list[str]:
252
+ def _regression_focus(
253
+ modules: list[ImpactItem], surfaces: list[ImpactItem], files: list[str]
254
+ ) -> list[str]:
223
255
  focus: list[str] = []
224
- joined_paths = " ".join([item.path.lower() for item in modules + surfaces] + [file.lower() for file in files])
256
+ joined_paths = " ".join(
257
+ [item.path.lower() for item in modules + surfaces] + [file.lower() for file in files]
258
+ )
225
259
  if any(token in joined_paths for token in ["auth", "login", "session", "permission"]):
226
260
  focus.append("Authentication, session, and permission regression checks")
227
261
  if any(token in joined_paths for token in ["api", "controller", "route", "router"]):
228
262
  focus.append("API contract and route-level regression checks")
229
263
  if any(token in joined_paths for token in ["component", "ui", "page", "screen", "view"]):
230
264
  focus.append("Critical UI paths, navigation, and state transition checks")
231
- if any(token in joined_paths for token in ["db", "database", "repository", "model", "entity"]):
265
+ if any(
266
+ token in joined_paths for token in ["db", "database", "repository", "model", "entity"]
267
+ ):
232
268
  focus.append("Data model, persistence, and migration regression checks")
233
269
  if not focus:
234
- focus.append("Smoke test the primary user flow and the modules most likely to be touched")
270
+ focus.append(
271
+ "Smoke test the primary user flow and the modules most likely to be touched"
272
+ )
235
273
  return focus
236
274
 
237
275
  @staticmethod
@@ -246,10 +284,16 @@ class ImpactAnalyzer:
246
284
  "Limit edits to the highest-confidence modules before expanding the scope.",
247
285
  ]
248
286
  if risk_level == "high":
249
- steps.append("Freeze the affected surface in PRD / Architecture / UIUX or patch docs before coding.")
287
+ steps.append(
288
+ "Freeze the affected surface in PRD / Architecture / UIUX or patch docs before coding."
289
+ )
250
290
  if surfaces:
251
- steps.append("Re-test the affected integration surfaces before declaring the change complete.")
291
+ steps.append(
292
+ "Re-test the affected integration surfaces before declaring the change complete."
293
+ )
252
294
  if files:
253
- steps.append("Use the changed file list as the minimum review set, then inspect adjacent modules only if impact expands.")
295
+ steps.append(
296
+ "Use the changed file list as the minimum review set, then inspect adjacent modules only if impact expands."
297
+ )
254
298
  steps.append("Rerun bugfix/runtime/quality validation after implementation.")
255
299
  return steps
@@ -88,9 +88,7 @@ class TechStack:
88
88
  """转换为字典"""
89
89
  # 处理 framework 可能是字符串或枚举
90
90
  framework_value = (
91
- self.framework.value
92
- if isinstance(self.framework, FrameworkType)
93
- else self.framework
91
+ self.framework.value if isinstance(self.framework, FrameworkType) else self.framework
94
92
  )
95
93
 
96
94
  return {
@@ -231,31 +229,37 @@ class ArchitectureReport:
231
229
  lines.append(f"- **测试框架**: {self.tech_stack.testing_framework}")
232
230
 
233
231
  if self.architecture_pattern:
234
- lines.extend([
235
- "",
236
- "## 架构模式",
237
- "",
238
- f"识别到: **{self.architecture_pattern.value}**",
239
- ])
232
+ lines.extend(
233
+ [
234
+ "",
235
+ "## 架构模式",
236
+ "",
237
+ f"识别到: **{self.architecture_pattern.value}**",
238
+ ]
239
+ )
240
240
 
241
241
  if self.design_patterns:
242
- lines.extend([
243
- "",
244
- "## 设计模式",
245
- "",
246
- ])
242
+ lines.extend(
243
+ [
244
+ "",
245
+ "## 设计模式",
246
+ "",
247
+ ]
248
+ )
247
249
  for pattern in self.design_patterns:
248
250
  lines.append(f"- **{pattern.name.value}**: `{pattern.location}`")
249
251
  if pattern.description:
250
252
  lines.append(f" - {pattern.description}")
251
253
 
252
- lines.extend([
253
- "",
254
- "## 项目统计",
255
- "",
256
- f"- **文件数量**: {self.file_count}",
257
- f"- **代码行数**: {self.total_lines:,}",
258
- ])
254
+ lines.extend(
255
+ [
256
+ "",
257
+ "## 项目统计",
258
+ "",
259
+ f"- **文件数量**: {self.file_count}",
260
+ f"- **代码行数**: {self.total_lines:,}",
261
+ ]
262
+ )
259
263
 
260
264
  if self.languages_used:
261
265
  lines.append("- **语言分布**:")
@@ -266,11 +270,13 @@ class ArchitectureReport:
266
270
  lines.append(f" - {lang}: {count:,} 行 ({percentage:.1f}%)")
267
271
 
268
272
  if self.tech_stack.dependencies:
269
- lines.extend([
270
- "",
271
- f"## 主要依赖 ({len(self.tech_stack.dependencies)})",
272
- "",
273
- ])
273
+ lines.extend(
274
+ [
275
+ "",
276
+ f"## 主要依赖 ({len(self.tech_stack.dependencies)})",
277
+ "",
278
+ ]
279
+ )
274
280
  for dep in self.tech_stack.dependencies[:20]: # 只显示前20个
275
281
  lines.append(f"- {dep}")
276
282