autosnippet 3.3.5 → 3.3.7
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.
- package/dashboard/dist/assets/icons-FHns2ypa.js +1 -0
- package/dashboard/dist/assets/index-BRJv5Y3r.js +135 -0
- package/dashboard/dist/assets/index-DzoB7kxK.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/api-server.js +1 -0
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.js +137 -9
- package/dist/lib/agent/AgentFactory.d.ts +0 -17
- package/dist/lib/agent/AgentFactory.js +1 -25
- package/dist/lib/agent/AgentRuntime.d.ts +2 -2
- package/dist/lib/agent/AgentRuntime.js +26 -18
- package/dist/lib/agent/capabilities.d.ts +11 -0
- package/dist/lib/agent/capabilities.js +29 -5
- package/dist/lib/agent/context/ExplorationTracker.js +10 -1
- package/dist/lib/agent/context/exploration/ExplorationStrategies.d.ts +2 -0
- package/dist/lib/agent/context/exploration/ExplorationStrategies.js +2 -2
- package/dist/lib/agent/domain/ChatAgentTasks.js +4 -0
- package/dist/lib/agent/domain/insight-analyst.d.ts +47 -3
- package/dist/lib/agent/domain/insight-analyst.js +111 -11
- package/dist/lib/agent/domain/insight-evolver.d.ts +69 -0
- package/dist/lib/agent/domain/insight-evolver.js +230 -0
- package/dist/lib/agent/domain/insight-gate.d.ts +42 -0
- package/dist/lib/agent/domain/insight-gate.js +41 -0
- package/dist/lib/agent/domain/insight-producer.d.ts +27 -2
- package/dist/lib/agent/domain/insight-producer.js +60 -5
- package/dist/lib/agent/domain/scan-prompts.js +10 -7
- package/dist/lib/agent/forced-summary.js +7 -2
- package/dist/lib/agent/memory/ActiveContext.d.ts +2 -28
- package/dist/lib/agent/memory/MemoryCoordinator.d.ts +2 -2
- package/dist/lib/agent/memory/SessionStore.d.ts +6 -12
- package/dist/lib/agent/memory/SessionStore.js +9 -15
- package/dist/lib/agent/memory/memory-flush-contract.d.ts +49 -0
- package/dist/lib/agent/memory/memory-flush-contract.js +16 -0
- package/dist/lib/agent/memory/session-store-schema.d.ts +20 -0
- package/dist/lib/agent/memory/session-store-schema.js +41 -0
- package/dist/lib/agent/presets.d.ts +89 -1
- package/dist/lib/agent/presets.js +53 -5
- package/dist/lib/agent/tools/_shared.d.ts +7 -15
- package/dist/lib/agent/tools/_shared.js +20 -21
- package/dist/lib/agent/tools/composite.d.ts +25 -22
- package/dist/lib/agent/tools/composite.js +108 -109
- package/dist/lib/agent/tools/evolution-tools.d.ts +145 -0
- package/dist/lib/agent/tools/evolution-tools.js +161 -0
- package/dist/lib/agent/tools/index.d.ts +163 -92
- package/dist/lib/agent/tools/index.js +9 -1
- package/dist/lib/agent/tools/lifecycle.d.ts +7 -1
- package/dist/lib/agent/tools/lifecycle.js +59 -75
- package/dist/lib/cli/AiScanService.js +5 -5
- package/dist/lib/cli/KnowledgeSyncService.js +1 -1
- package/dist/lib/core/AstAnalyzer.d.ts +1 -0
- package/dist/lib/core/discovery/ConfigWatcher.d.ts +64 -0
- package/dist/lib/core/discovery/ConfigWatcher.js +336 -0
- package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +30 -0
- package/dist/lib/core/discovery/CustomConfigDiscoverer.js +1305 -0
- package/dist/lib/core/discovery/DiscovererPreference.d.ts +44 -0
- package/dist/lib/core/discovery/DiscovererPreference.js +141 -0
- package/dist/lib/core/discovery/DiscovererRegistry.d.ts +10 -1
- package/dist/lib/core/discovery/DiscovererRegistry.js +42 -2
- package/dist/lib/core/discovery/ProjectDiscoverer.d.ts +19 -0
- package/dist/lib/core/discovery/index.d.ts +2 -0
- package/dist/lib/core/discovery/index.js +4 -0
- package/dist/lib/core/discovery/parsers/CMakeParser.d.ts +32 -0
- package/dist/lib/core/discovery/parsers/CMakeParser.js +148 -0
- package/dist/lib/core/discovery/parsers/GradleDslParser.d.ts +43 -0
- package/dist/lib/core/discovery/parsers/GradleDslParser.js +171 -0
- package/dist/lib/core/discovery/parsers/JsonConfigParser.d.ts +45 -0
- package/dist/lib/core/discovery/parsers/JsonConfigParser.js +122 -0
- package/dist/lib/core/discovery/parsers/RubyDslParser.d.ts +49 -0
- package/dist/lib/core/discovery/parsers/RubyDslParser.js +282 -0
- package/dist/lib/core/discovery/parsers/StarlarkParser.d.ts +33 -0
- package/dist/lib/core/discovery/parsers/StarlarkParser.js +229 -0
- package/dist/lib/core/discovery/parsers/YamlConfigParser.d.ts +37 -0
- package/dist/lib/core/discovery/parsers/YamlConfigParser.js +212 -0
- package/dist/lib/{service/bootstrap/DimensionCopyRegistry.d.ts → domain/dimension/DimensionCopy.d.ts} +2 -2
- package/dist/lib/{service/bootstrap/DimensionCopyRegistry.js → domain/dimension/DimensionCopy.js} +22 -72
- package/dist/lib/domain/dimension/DimensionRegistry.d.ts +54 -0
- package/dist/lib/domain/dimension/DimensionRegistry.js +620 -0
- package/dist/lib/domain/dimension/DimensionSop.d.ts +55 -0
- package/dist/lib/domain/dimension/DimensionSop.js +1604 -0
- package/dist/lib/domain/dimension/UnifiedDimension.d.ts +61 -0
- package/dist/lib/domain/dimension/UnifiedDimension.js +53 -0
- package/dist/lib/domain/dimension/index.d.ts +10 -0
- package/dist/lib/domain/dimension/index.js +9 -0
- package/dist/lib/domain/knowledge/FieldSpec.d.ts +1 -1
- package/dist/lib/domain/knowledge/FieldSpec.js +29 -16
- package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +40 -112
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +44 -9
- package/dist/lib/domain/knowledge/KnowledgeRepository.d.ts +1 -0
- package/dist/lib/domain/knowledge/KnowledgeRepository.js +3 -0
- package/dist/lib/domain/knowledge/Lifecycle.js +1 -1
- package/dist/lib/domain/knowledge/StyleGuide.d.ts +1 -1
- package/dist/lib/domain/knowledge/StyleGuide.js +1 -1
- package/dist/lib/domain/knowledge/UnifiedValidator.js +15 -0
- package/dist/lib/external/ai/AiProvider.d.ts +12 -0
- package/dist/lib/external/ai/AiProvider.js +24 -0
- package/dist/lib/external/ai/AiProviderManager.d.ts +101 -0
- package/dist/lib/external/ai/AiProviderManager.js +193 -0
- package/dist/lib/external/ai/providers/ClaudeProvider.js +11 -0
- package/dist/lib/external/ai/providers/GoogleGeminiProvider.js +18 -0
- package/dist/lib/external/ai/providers/MockProvider.d.ts +21 -3
- package/dist/lib/external/ai/providers/MockProvider.js +290 -14
- package/dist/lib/external/ai/providers/OpenAiProvider.js +16 -0
- package/dist/lib/external/lark/LarkTransport.d.ts +5 -1
- package/dist/lib/external/lark/LarkTransport.js +10 -2
- package/dist/lib/external/mcp/McpServer.js +4 -0
- package/dist/lib/external/mcp/handlers/TargetClassifier.d.ts +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.d.ts +8 -16
- package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +10 -10
- package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.d.ts +7 -0
- package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +20 -0
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +52 -132
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +204 -17
- package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.d.ts +11 -75
- package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.js +40 -191
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.d.ts +13 -78
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +30 -52
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.d.ts +0 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.d.ts +20 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.js +432 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.d.ts +99 -12
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +188 -169
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +7 -17
- package/dist/lib/external/mcp/handlers/bootstrap/refine.js +8 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.d.ts +46 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.js +58 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.d.ts +25 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.js +47 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +50 -12
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +30 -10
- package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-text.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.d.ts +24 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.js +14 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.d.ts +14 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.js +48 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.d.ts +21 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.js +45 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/skill-generator.d.ts +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.d.ts +27 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.js +44 -0
- package/dist/lib/external/mcp/handlers/bootstrap-external.d.ts +23 -10
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +41 -51
- package/dist/lib/external/mcp/handlers/bootstrap-internal.d.ts +2 -0
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +117 -82
- package/dist/lib/external/mcp/handlers/consolidated.d.ts +4 -4
- package/dist/lib/external/mcp/handlers/consolidated.js +108 -332
- package/dist/lib/external/mcp/handlers/dimension-complete-external.js +71 -2
- package/dist/lib/external/mcp/handlers/evolve-external.d.ts +54 -0
- package/dist/lib/external/mcp/handlers/evolve-external.js +229 -0
- package/dist/lib/external/mcp/handlers/knowledge.js +30 -5
- package/dist/lib/external/mcp/handlers/rescan-external.d.ts +76 -0
- package/dist/lib/external/mcp/handlers/rescan-external.js +335 -0
- package/dist/lib/external/mcp/handlers/rescan-internal.d.ts +120 -0
- package/dist/lib/external/mcp/handlers/rescan-internal.js +359 -0
- package/dist/lib/external/mcp/handlers/search.d.ts +6 -5
- package/dist/lib/external/mcp/handlers/search.js +6 -5
- package/dist/lib/external/mcp/handlers/types.d.ts +2 -1
- package/dist/lib/external/mcp/handlers/wiki-external.js +2 -2
- package/dist/lib/external/mcp/tools.d.ts +8 -18
- package/dist/lib/external/mcp/tools.js +58 -2
- package/dist/lib/http/routes/ai.js +111 -30
- package/dist/lib/http/routes/candidates.js +11 -4
- package/dist/lib/http/routes/commands.js +10 -1
- package/dist/lib/http/routes/health.js +11 -0
- package/dist/lib/http/routes/knowledge.js +122 -1
- package/dist/lib/http/routes/modules.js +52 -3
- package/dist/lib/http/routes/panorama.js +16 -4
- package/dist/lib/http/routes/recipes.js +7 -0
- package/dist/lib/http/utils/routeHelpers.js +2 -1
- package/dist/lib/infrastructure/cache/CacheCoordinator.d.ts +41 -0
- package/dist/lib/infrastructure/cache/CacheCoordinator.js +105 -0
- package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.d.ts +7 -0
- package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.js +28 -0
- package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +1 -1
- package/dist/lib/injection/ServiceContainer.d.ts +6 -5
- package/dist/lib/injection/ServiceContainer.js +64 -25
- package/dist/lib/injection/ServiceMap.d.ts +10 -1
- package/dist/lib/injection/modules/AiModule.d.ts +6 -9
- package/dist/lib/injection/modules/AiModule.js +82 -39
- package/dist/lib/injection/modules/KnowledgeModule.js +15 -1
- package/dist/lib/injection/modules/PanoramaModule.js +1 -1
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +4 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +16 -1
- package/dist/lib/service/bootstrap/BootstrapEventEmitter.d.ts +3 -2
- package/dist/lib/service/bootstrap/BootstrapEventEmitter.js +1 -1
- package/dist/lib/service/bootstrap/DeliveryVerifier.d.ts +51 -0
- package/dist/lib/service/bootstrap/DeliveryVerifier.js +163 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.d.ts +5 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.js +20 -0
- package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +54 -0
- package/dist/lib/service/bootstrap/bootstrap-event-types.js +10 -0
- package/dist/lib/service/cleanup/CleanupService.d.ts +132 -0
- package/dist/lib/service/cleanup/CleanupService.js +571 -0
- package/dist/lib/service/delivery/AgentInstructionsGenerator.js +39 -43
- package/dist/lib/service/delivery/FileProtection.d.ts +20 -0
- package/dist/lib/service/delivery/FileProtection.js +54 -0
- package/dist/lib/service/delivery/SkillsSyncer.js +16 -21
- package/dist/lib/service/evolution/ContentPatcher.d.ts +44 -0
- package/dist/lib/service/evolution/ContentPatcher.js +310 -0
- package/dist/lib/service/evolution/ProposalExecutor.d.ts +4 -0
- package/dist/lib/service/evolution/ProposalExecutor.js +77 -13
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +64 -0
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +458 -0
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +89 -0
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +492 -0
- package/dist/lib/service/evolution/createSupersedeProposal.d.ts +44 -0
- package/dist/lib/service/evolution/createSupersedeProposal.js +81 -0
- package/dist/lib/service/guard/ComplianceReporter.d.ts +4 -0
- package/dist/lib/service/guard/ComplianceReporter.js +51 -0
- package/dist/lib/service/guard/GuardCheckEngine.js +5 -4
- package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +6 -0
- package/dist/lib/service/knowledge/CodeEntityGraph.js +16 -0
- package/dist/lib/service/knowledge/ConfidenceRouter.js +1 -1
- package/dist/lib/service/knowledge/KnowledgeService.d.ts +11 -1
- package/dist/lib/service/knowledge/KnowledgeService.js +67 -14
- package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +225 -0
- package/dist/lib/service/knowledge/RecipeProductionGateway.js +384 -0
- package/dist/lib/service/module/ModuleService.js +10 -19
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +10 -1
- package/dist/lib/service/panorama/CouplingAnalyzer.js +44 -2
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +4 -3
- package/dist/lib/service/panorama/DimensionAnalyzer.js +40 -151
- package/dist/lib/service/panorama/LayerInferrer.d.ts +16 -1
- package/dist/lib/service/panorama/LayerInferrer.js +118 -1
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +9 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.js +58 -2
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +6 -2
- package/dist/lib/service/panorama/PanoramaAggregator.js +84 -6
- package/dist/lib/service/panorama/PanoramaScanner.js +28 -0
- package/dist/lib/service/panorama/PanoramaService.js +10 -5
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +38 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +2 -0
- package/dist/lib/service/panorama/RoleRefiner.js +41 -0
- package/dist/lib/service/panorama/TechStackProfiler.d.ts +13 -0
- package/dist/lib/service/panorama/TechStackProfiler.js +191 -0
- package/dist/lib/service/search/BM25Scorer.d.ts +2 -2
- package/dist/lib/service/search/SearchEngine.d.ts +11 -10
- package/dist/lib/service/search/SearchEngine.js +38 -36
- package/dist/lib/service/search/SearchTypes.d.ts +14 -8
- package/dist/lib/service/search/SearchTypes.js +1 -1
- package/dist/lib/service/search/tokenizer.d.ts +1 -1
- package/dist/lib/service/search/tokenizer.js +2 -2
- package/dist/lib/service/skills/SignalCollector.d.ts +1 -0
- package/dist/lib/service/skills/SignalCollector.js +6 -5
- package/dist/lib/service/vector/ContextualEnricher.d.ts +1 -0
- package/dist/lib/service/vector/ContextualEnricher.js +4 -0
- package/dist/lib/shared/LanguageService.js +3 -0
- package/dist/lib/shared/developer-identity.d.ts +18 -0
- package/dist/lib/shared/developer-identity.js +62 -0
- package/dist/lib/shared/schemas/common.d.ts +4 -4
- package/dist/lib/shared/schemas/http-requests.d.ts +20 -18
- package/dist/lib/shared/schemas/http-requests.js +17 -6
- package/dist/lib/shared/schemas/mcp-tools.d.ts +32 -2
- package/dist/lib/shared/schemas/mcp-tools.js +38 -0
- package/dist/lib/types/evolution.d.ts +135 -0
- package/dist/lib/types/evolution.js +6 -0
- package/dist/lib/types/graph-shared.d.ts +25 -0
- package/dist/lib/types/graph-shared.js +7 -0
- package/dist/lib/types/knowledge-wire.d.ts +132 -0
- package/dist/lib/types/knowledge-wire.js +7 -0
- package/dist/lib/types/project-snapshot-builder.d.ts +19 -0
- package/dist/lib/types/project-snapshot-builder.js +189 -0
- package/dist/lib/types/project-snapshot.d.ts +399 -0
- package/dist/lib/types/project-snapshot.js +17 -0
- package/dist/lib/types/search-wire.d.ts +46 -0
- package/dist/lib/types/search-wire.js +7 -0
- package/dist/lib/types/snapshot-views.d.ts +58 -0
- package/dist/lib/types/snapshot-views.js +103 -0
- package/package.json +1 -1
- package/skills/autosnippet-recipes/SKILL.md +1 -1
- package/templates/instructions/agent-static.md +2 -0
- package/templates/instructions/conventions.md +3 -1
- package/templates/recipes-setup/README.md +2 -2
- package/dashboard/dist/assets/icons-BJ2mUBi8.js +0 -1
- package/dashboard/dist/assets/index-B659K9t5.js +0 -128
- package/dashboard/dist/assets/index-NCm40PMD.css +0 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.d.ts +0 -169
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +0 -727
- package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.d.ts +0 -370
- package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +0 -821
|
@@ -1,140 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DimensionAnalyzer — 多维度知识健康分析
|
|
3
3
|
*
|
|
4
|
+
* **v2: 从统一维度注册表 (DimensionRegistry) 派生维度**
|
|
5
|
+
*
|
|
4
6
|
* 灵感来源:
|
|
5
7
|
* - ISO/IEC 25010 质量模型 (8 大特性: 可靠性、安全性、可维护性…)
|
|
6
8
|
* - ThoughtWorks Tech Radar (Adopt/Trial/Assess/Hold 四环)
|
|
7
9
|
* - 雷达图/蛛网图可视化模型
|
|
8
10
|
*
|
|
9
|
-
* 核心思路:
|
|
10
|
-
* 而是按「知识维度」衡量项目在各工程方向上的规范成熟度。
|
|
11
|
+
* 核心思路: 按「知识维度」衡量项目在各工程方向上的规范成熟度。
|
|
11
12
|
* 某维度 Recipe 为 0 → 该方向完全空白,标示为 gap。
|
|
12
13
|
*
|
|
13
14
|
* @module DimensionAnalyzer
|
|
14
15
|
*/
|
|
15
|
-
|
|
16
|
-
* 标准维度列表
|
|
17
|
-
*
|
|
18
|
-
* 覆盖主流软件工程关切方向,任何项目都应有所涉猎。
|
|
19
|
-
* `topics` 与 `categories` 匹配 knowledge_entries 的字段。
|
|
20
|
-
*/
|
|
21
|
-
const DIMENSION_DEFS = [
|
|
22
|
-
{
|
|
23
|
-
id: 'architecture',
|
|
24
|
-
name: '架构设计',
|
|
25
|
-
description: '模块结构、分层策略、依赖管理、设计模式',
|
|
26
|
-
topics: ['architecture', 'scaffold', 'workflow'],
|
|
27
|
-
categories: ['architecture', 'project-profile'],
|
|
28
|
-
weight: 1.0,
|
|
29
|
-
suggestedTopics: ['module-boundary', 'dependency-rule', 'layer-strategy'],
|
|
30
|
-
relatedRoles: ['core', 'foundation', 'app'],
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
id: 'coding-standards',
|
|
34
|
-
name: '编码规范',
|
|
35
|
-
description: '命名约定、代码风格、文档注释、import 顺序',
|
|
36
|
-
topics: ['conventions'],
|
|
37
|
-
categories: ['code-standard'],
|
|
38
|
-
weight: 0.8,
|
|
39
|
-
suggestedTopics: ['naming-convention', 'code-style', 'documentation'],
|
|
40
|
-
relatedRoles: [],
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
id: 'error-handling',
|
|
44
|
-
name: '错误处理',
|
|
45
|
-
description: '异常模式、错误恢复、输入验证、防御性编程',
|
|
46
|
-
topics: ['error-handling', 'constraints'],
|
|
47
|
-
categories: [],
|
|
48
|
-
weight: 1.0,
|
|
49
|
-
suggestedTopics: ['exception-pattern', 'error-recovery', 'input-validation'],
|
|
50
|
-
relatedRoles: ['service', 'networking', 'core'],
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
id: 'concurrency',
|
|
54
|
-
name: '并发与线程',
|
|
55
|
-
description: '线程安全、异步模式、竞态条件防护、锁策略',
|
|
56
|
-
topics: ['concurrency', 'async'],
|
|
57
|
-
categories: [],
|
|
58
|
-
weight: 0.9,
|
|
59
|
-
suggestedTopics: ['thread-safety', 'async-pattern', 'race-condition'],
|
|
60
|
-
relatedRoles: ['service', 'networking', 'storage'],
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: 'data-management',
|
|
64
|
-
name: '数据管理',
|
|
65
|
-
description: '持久化、缓存、序列化、数据流向完整性',
|
|
66
|
-
topics: ['data', 'data-flow', 'memory'],
|
|
67
|
-
categories: ['event-and-data-flow'],
|
|
68
|
-
weight: 0.8,
|
|
69
|
-
suggestedTopics: ['persistence', 'caching', 'serialization', 'data-integrity'],
|
|
70
|
-
relatedRoles: ['storage', 'model'],
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
id: 'networking',
|
|
74
|
-
name: '网络通信',
|
|
75
|
-
description: 'API 契约、请求模式、重试策略、实时通信',
|
|
76
|
-
topics: ['networking', 'real-time'],
|
|
77
|
-
categories: [],
|
|
78
|
-
weight: 0.7,
|
|
79
|
-
suggestedTopics: ['api-contract', 'retry-strategy', 'request-pattern'],
|
|
80
|
-
relatedRoles: ['networking'],
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
id: 'ui-patterns',
|
|
84
|
-
name: '界面模式',
|
|
85
|
-
description: 'UI 组件规范、生命周期、导航、数据绑定',
|
|
86
|
-
topics: ['ui', 'binding', 'pagination'],
|
|
87
|
-
categories: [],
|
|
88
|
-
weight: 0.7,
|
|
89
|
-
suggestedTopics: ['component-pattern', 'lifecycle', 'navigation'],
|
|
90
|
-
relatedRoles: ['ui', 'feature'],
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
id: 'testing',
|
|
94
|
-
name: '测试策略',
|
|
95
|
-
description: '测试模式、Mock 策略、CI/CD 流程',
|
|
96
|
-
topics: ['testing', 'test'],
|
|
97
|
-
categories: [],
|
|
98
|
-
weight: 0.9,
|
|
99
|
-
suggestedTopics: ['unit-test', 'mock-strategy', 'ci-cd'],
|
|
100
|
-
relatedRoles: [],
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
id: 'security',
|
|
104
|
-
name: '安全',
|
|
105
|
-
description: '认证授权、输入校验、加密、权限控制',
|
|
106
|
-
topics: ['security', 'auth'],
|
|
107
|
-
categories: [],
|
|
108
|
-
weight: 1.0,
|
|
109
|
-
suggestedTopics: ['authentication', 'authorization', 'encryption'],
|
|
110
|
-
relatedRoles: ['networking', 'service'],
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
id: 'performance',
|
|
114
|
-
name: '性能优化',
|
|
115
|
-
description: '内存管理、懒加载、缓存策略、渲染优化',
|
|
116
|
-
topics: ['performance', 'optimization'],
|
|
117
|
-
categories: [],
|
|
118
|
-
weight: 0.8,
|
|
119
|
-
suggestedTopics: ['memory-management', 'lazy-loading', 'rendering'],
|
|
120
|
-
relatedRoles: ['ui', 'storage'],
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
id: 'observability',
|
|
124
|
-
name: '可观测性',
|
|
125
|
-
description: '日志规范、事件追踪、监控诊断',
|
|
126
|
-
topics: ['logging', 'event', 'monitoring'],
|
|
127
|
-
categories: [],
|
|
128
|
-
weight: 0.7,
|
|
129
|
-
suggestedTopics: ['logging-standard', 'event-tracking', 'diagnostics'],
|
|
130
|
-
relatedRoles: ['service', 'core'],
|
|
131
|
-
},
|
|
132
|
-
];
|
|
16
|
+
import { classifyRecipeToDimension, DIMENSION_REGISTRY, resolveActiveDimensions, } from '#domain/dimension/index.js';
|
|
133
17
|
/* ═══ DimensionAnalyzer Class ═════════════════════════════ */
|
|
134
18
|
export class DimensionAnalyzer {
|
|
135
19
|
#db;
|
|
136
|
-
|
|
20
|
+
#projectRoot;
|
|
21
|
+
constructor(db, projectRoot) {
|
|
137
22
|
this.#db = db;
|
|
23
|
+
this.#projectRoot = projectRoot;
|
|
138
24
|
}
|
|
139
25
|
/**
|
|
140
26
|
* 分析项目知识健康雷达
|
|
@@ -142,11 +28,13 @@ export class DimensionAnalyzer {
|
|
|
142
28
|
* @param moduleRoles — 项目中存在的模块角色 (用于 gap 优先级推断)
|
|
143
29
|
*/
|
|
144
30
|
analyze(moduleRoles) {
|
|
31
|
+
// 0. 按项目语言过滤活跃维度(排除无关语言/框架维度)
|
|
32
|
+
const activeDims = this.#resolveActiveDims();
|
|
145
33
|
// 1. 从 DB 获取所有活跃 recipe 的维度分类信息
|
|
146
34
|
const recipes = this.#fetchRecipeMetadata();
|
|
147
35
|
// 2. 将每条 recipe 映射到维度
|
|
148
36
|
const dimensionCounts = new Map();
|
|
149
|
-
for (const def of
|
|
37
|
+
for (const def of activeDims) {
|
|
150
38
|
dimensionCounts.set(def.id, { count: 0, titles: [] });
|
|
151
39
|
}
|
|
152
40
|
let totalRecipes = 0;
|
|
@@ -162,16 +50,16 @@ export class DimensionAnalyzer {
|
|
|
162
50
|
}
|
|
163
51
|
}
|
|
164
52
|
// 3. 计算各维度得分与状态
|
|
165
|
-
const dimensions =
|
|
53
|
+
const dimensions = activeDims.map((def) => {
|
|
166
54
|
const entry = dimensionCounts.get(def.id);
|
|
167
55
|
return this.#scoreDimension(def, entry.count, entry.titles);
|
|
168
56
|
});
|
|
169
57
|
// 4. 加权平均健康分
|
|
170
58
|
let weightedSum = 0;
|
|
171
59
|
let weightTotal = 0;
|
|
172
|
-
for (let i = 0; i <
|
|
173
|
-
weightedSum += dimensions[i].score *
|
|
174
|
-
weightTotal +=
|
|
60
|
+
for (let i = 0; i < activeDims.length; i++) {
|
|
61
|
+
weightedSum += dimensions[i].score * activeDims[i].weight;
|
|
62
|
+
weightTotal += activeDims[i].weight;
|
|
175
63
|
}
|
|
176
64
|
const overallScore = weightTotal > 0 ? Math.round(weightedSum / weightTotal) : 0;
|
|
177
65
|
// 5. 统计覆盖
|
|
@@ -187,9 +75,26 @@ export class DimensionAnalyzer {
|
|
|
187
75
|
};
|
|
188
76
|
// 6. 生成维度空白 (gaps)
|
|
189
77
|
const roleSet = new Set(moduleRoles);
|
|
190
|
-
const gaps = this.#detectDimensionGaps(dimensions, roleSet);
|
|
78
|
+
const gaps = this.#detectDimensionGaps(dimensions, activeDims, roleSet);
|
|
191
79
|
return { radar, gaps };
|
|
192
80
|
}
|
|
81
|
+
/* ─── 按项目语言解析活跃维度 ───────────────────── */
|
|
82
|
+
#resolveActiveDims() {
|
|
83
|
+
try {
|
|
84
|
+
const row = this.#db
|
|
85
|
+
.prepare(`SELECT primary_lang FROM bootstrap_snapshots
|
|
86
|
+
WHERE project_root = ? ORDER BY created_at DESC LIMIT 1`)
|
|
87
|
+
.get(this.#projectRoot);
|
|
88
|
+
const primaryLang = row?.primary_lang;
|
|
89
|
+
if (primaryLang) {
|
|
90
|
+
return resolveActiveDimensions(primaryLang);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// 无 bootstrap 数据 → 回退全量维度
|
|
95
|
+
}
|
|
96
|
+
return DIMENSION_REGISTRY;
|
|
97
|
+
}
|
|
193
98
|
/* ─── 从 DB 获取 recipe 元数据 ─────────────────── */
|
|
194
99
|
#fetchRecipeMetadata() {
|
|
195
100
|
try {
|
|
@@ -213,26 +118,10 @@ export class DimensionAnalyzer {
|
|
|
213
118
|
/**
|
|
214
119
|
* 将 recipe 分类到最匹配的维度
|
|
215
120
|
*
|
|
216
|
-
*
|
|
121
|
+
* 委托给 DimensionRegistry.classifyRecipeToDimension()
|
|
217
122
|
*/
|
|
218
123
|
#classifyRecipe(recipe) {
|
|
219
|
-
|
|
220
|
-
if (recipe.topicHint) {
|
|
221
|
-
for (const def of DIMENSION_DEFS) {
|
|
222
|
-
if (def.topics.includes(recipe.topicHint)) {
|
|
223
|
-
return def.id;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
// 2. category 匹配
|
|
228
|
-
if (recipe.category) {
|
|
229
|
-
for (const def of DIMENSION_DEFS) {
|
|
230
|
-
if (def.categories.includes(recipe.category)) {
|
|
231
|
-
return def.id;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return null;
|
|
124
|
+
return classifyRecipeToDimension(recipe.topicHint, recipe.category);
|
|
236
125
|
}
|
|
237
126
|
/* ─── 维度评分 ─────────────────────────────────── */
|
|
238
127
|
#scoreDimension(def, recipeCount, titles) {
|
|
@@ -268,8 +157,8 @@ export class DimensionAnalyzer {
|
|
|
268
157
|
}
|
|
269
158
|
return {
|
|
270
159
|
id: def.id,
|
|
271
|
-
name: def.
|
|
272
|
-
description: def.
|
|
160
|
+
name: def.label,
|
|
161
|
+
description: def.qualityDescription,
|
|
273
162
|
recipeCount,
|
|
274
163
|
score,
|
|
275
164
|
status,
|
|
@@ -278,11 +167,11 @@ export class DimensionAnalyzer {
|
|
|
278
167
|
};
|
|
279
168
|
}
|
|
280
169
|
/* ─── 维度空白检测 ─────────────────────────────── */
|
|
281
|
-
#detectDimensionGaps(dimensions, moduleRoles) {
|
|
170
|
+
#detectDimensionGaps(dimensions, activeDims, moduleRoles) {
|
|
282
171
|
const gaps = [];
|
|
283
172
|
for (let i = 0; i < dimensions.length; i++) {
|
|
284
173
|
const dim = dimensions[i];
|
|
285
|
-
const def =
|
|
174
|
+
const def = activeDims[i];
|
|
286
175
|
if (dim.status !== 'missing' && dim.status !== 'weak') {
|
|
287
176
|
continue;
|
|
288
177
|
}
|
|
@@ -305,11 +194,11 @@ export class DimensionAnalyzer {
|
|
|
305
194
|
const affectedRoles = def.relatedRoles.filter((r) => moduleRoles.has(r));
|
|
306
195
|
gaps.push({
|
|
307
196
|
dimension: def.id,
|
|
308
|
-
dimensionName: def.
|
|
197
|
+
dimensionName: def.label,
|
|
309
198
|
recipeCount: dim.recipeCount,
|
|
310
199
|
status: dim.status,
|
|
311
200
|
priority,
|
|
312
|
-
suggestedTopics: def.suggestedTopics,
|
|
201
|
+
suggestedTopics: [...def.suggestedTopics],
|
|
313
202
|
affectedRoles,
|
|
314
203
|
});
|
|
315
204
|
}
|
|
@@ -4,9 +4,23 @@
|
|
|
4
4
|
* 基于模块依赖图,通过去环 + 拓扑排序 + 最长路径法推断架构层级 (L0-Ln)。
|
|
5
5
|
* 底层 (L0) = Foundation/Core,顶层 = App/UI。
|
|
6
6
|
*
|
|
7
|
+
* 当配置文件声明了明确的层级结构时(如 Boxfile 的 layer 定义),
|
|
8
|
+
* 优先使用配置层级,仅对未覆盖的模块做拓扑推断。
|
|
9
|
+
*
|
|
7
10
|
* @module LayerInferrer
|
|
8
11
|
*/
|
|
9
12
|
import type { CyclicDependency, Edge, LayerHierarchy } from './PanoramaTypes.js';
|
|
13
|
+
export interface ConfigLayer {
|
|
14
|
+
name: string;
|
|
15
|
+
order: number;
|
|
16
|
+
accessibleLayers: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface InferOptions {
|
|
19
|
+
/** 来自配置文件的层级定义(如 Boxfile、Project.swift 等) */
|
|
20
|
+
configLayers?: ConfigLayer[] | null;
|
|
21
|
+
/** 模块 → 配置层级名映射 */
|
|
22
|
+
moduleLayerMap?: Map<string, string>;
|
|
23
|
+
}
|
|
10
24
|
export declare class LayerInferrer {
|
|
11
25
|
#private;
|
|
12
26
|
/**
|
|
@@ -14,6 +28,7 @@ export declare class LayerInferrer {
|
|
|
14
28
|
* @param edges - 模块间依赖边 (from depends_on/calls/data_flow to)
|
|
15
29
|
* @param modules - 所有模块名
|
|
16
30
|
* @param cycles - 已检测到的循环依赖
|
|
31
|
+
* @param options - 可选配置:configLayers(配置声明的层级)和 moduleLayerMap(模块→层级映射)
|
|
17
32
|
*/
|
|
18
|
-
infer(edges: Edge[], modules: string[], cycles: CyclicDependency[]): LayerHierarchy;
|
|
33
|
+
infer(edges: Edge[], modules: string[], cycles: CyclicDependency[], options?: InferOptions): LayerHierarchy;
|
|
19
34
|
}
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* 基于模块依赖图,通过去环 + 拓扑排序 + 最长路径法推断架构层级 (L0-Ln)。
|
|
5
5
|
* 底层 (L0) = Foundation/Core,顶层 = App/UI。
|
|
6
6
|
*
|
|
7
|
+
* 当配置文件声明了明确的层级结构时(如 Boxfile 的 layer 定义),
|
|
8
|
+
* 优先使用配置层级,仅对未覆盖的模块做拓扑推断。
|
|
9
|
+
*
|
|
7
10
|
* @module LayerInferrer
|
|
8
11
|
*/
|
|
9
12
|
/* ═══ Constants ═══════════════════════════════════════════ */
|
|
@@ -26,8 +29,122 @@ export class LayerInferrer {
|
|
|
26
29
|
* @param edges - 模块间依赖边 (from depends_on/calls/data_flow to)
|
|
27
30
|
* @param modules - 所有模块名
|
|
28
31
|
* @param cycles - 已检测到的循环依赖
|
|
32
|
+
* @param options - 可选配置:configLayers(配置声明的层级)和 moduleLayerMap(模块→层级映射)
|
|
29
33
|
*/
|
|
30
|
-
infer(edges, modules, cycles) {
|
|
34
|
+
infer(edges, modules, cycles, options) {
|
|
35
|
+
// 如果有配置文件声明的层级且覆盖了大部分模块,优先使用
|
|
36
|
+
if (options?.configLayers?.length && options.moduleLayerMap?.size) {
|
|
37
|
+
const coverage = this.#computeConfigCoverage(modules, options.moduleLayerMap);
|
|
38
|
+
if (coverage >= 0.5) {
|
|
39
|
+
return this.#inferFromConfig(edges, modules, options.configLayers, options.moduleLayerMap);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return this.#inferFromTopology(edges, modules, cycles);
|
|
43
|
+
}
|
|
44
|
+
/* ─── Config-based layer inference ──────────────── */
|
|
45
|
+
/**
|
|
46
|
+
* 基于配置文件声明的层级直接分配
|
|
47
|
+
* 未被配置覆盖的模块附加到最近匹配的层级
|
|
48
|
+
*/
|
|
49
|
+
#inferFromConfig(edges, modules, configLayers, moduleLayerMap) {
|
|
50
|
+
// 按 order 排序层级
|
|
51
|
+
const sortedLayers = [...configLayers].sort((a, b) => a.order - b.order);
|
|
52
|
+
// 构建层级名 → level 映射 (底层 = L0, 反序: order 最大的是底层)
|
|
53
|
+
// 配置中 order=0 是最高层 (如 Accessories), order=N 是最底层 (如 Vendors)
|
|
54
|
+
const maxOrder = sortedLayers.length > 0 ? sortedLayers[sortedLayers.length - 1].order : 0;
|
|
55
|
+
const layerNameToLevel = new Map();
|
|
56
|
+
for (const cl of sortedLayers) {
|
|
57
|
+
// 反转: 配置中 order 越大越底层 → level 越小
|
|
58
|
+
layerNameToLevel.set(cl.name, maxOrder - cl.order);
|
|
59
|
+
}
|
|
60
|
+
// 分配每个模块到层级
|
|
61
|
+
const moduleLevels = new Map();
|
|
62
|
+
const uncovered = [];
|
|
63
|
+
for (const mod of modules) {
|
|
64
|
+
const layerName = moduleLayerMap.get(mod);
|
|
65
|
+
if (layerName && layerNameToLevel.has(layerName)) {
|
|
66
|
+
moduleLevels.set(mod, layerNameToLevel.get(layerName));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
uncovered.push(mod);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// 未覆盖的模块: 基于依赖关系推断最可能的层级
|
|
73
|
+
for (const mod of uncovered) {
|
|
74
|
+
const depEdges = edges.filter((e) => e.from === mod);
|
|
75
|
+
let bestLevel = maxOrder + 1; // 默认最高层
|
|
76
|
+
for (const e of depEdges) {
|
|
77
|
+
const targetLevel = moduleLevels.get(e.to);
|
|
78
|
+
if (targetLevel !== undefined) {
|
|
79
|
+
bestLevel = Math.min(bestLevel, targetLevel + 1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// 如果没有依赖线索, 查看谁依赖它
|
|
83
|
+
if (bestLevel > maxOrder) {
|
|
84
|
+
const reverseEdges = edges.filter((e) => e.to === mod);
|
|
85
|
+
for (const e of reverseEdges) {
|
|
86
|
+
const sourceLevel = moduleLevels.get(e.from);
|
|
87
|
+
if (sourceLevel !== undefined) {
|
|
88
|
+
bestLevel = Math.min(bestLevel, Math.max(0, sourceLevel - 1));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// 兜底: 放到最高层
|
|
93
|
+
if (bestLevel > maxOrder) {
|
|
94
|
+
bestLevel = maxOrder;
|
|
95
|
+
}
|
|
96
|
+
moduleLevels.set(mod, bestLevel);
|
|
97
|
+
}
|
|
98
|
+
// 聚合: 同层模块分组
|
|
99
|
+
const layerGroups = new Map();
|
|
100
|
+
for (const [mod, level] of moduleLevels) {
|
|
101
|
+
if (!layerGroups.has(level)) {
|
|
102
|
+
layerGroups.set(level, []);
|
|
103
|
+
}
|
|
104
|
+
layerGroups.get(level).push(mod);
|
|
105
|
+
}
|
|
106
|
+
// 构建 levelEntries, 使用配置中的层级名
|
|
107
|
+
const levelToConfigName = new Map();
|
|
108
|
+
for (const cl of sortedLayers) {
|
|
109
|
+
levelToConfigName.set(maxOrder - cl.order, cl.name);
|
|
110
|
+
}
|
|
111
|
+
const sortedLevels = [...layerGroups.entries()].sort((a, b) => a[0] - b[0]);
|
|
112
|
+
const levelEntries = sortedLevels.map(([level, mods]) => ({
|
|
113
|
+
level,
|
|
114
|
+
name: levelToConfigName.get(level) ?? this.#inferLayerName(mods, level, sortedLevels.length),
|
|
115
|
+
modules: mods.sort(),
|
|
116
|
+
}));
|
|
117
|
+
// 检测层级违规(基于 access 规则)
|
|
118
|
+
const violations = [];
|
|
119
|
+
for (const edge of edges) {
|
|
120
|
+
const fromLevel = moduleLevels.get(edge.from);
|
|
121
|
+
const toLevel = moduleLevels.get(edge.to);
|
|
122
|
+
if (fromLevel !== undefined && toLevel !== undefined && fromLevel < toLevel) {
|
|
123
|
+
violations.push({
|
|
124
|
+
from: edge.from,
|
|
125
|
+
to: edge.to,
|
|
126
|
+
fromLayer: fromLevel,
|
|
127
|
+
toLayer: toLevel,
|
|
128
|
+
relation: edge.relation,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { levels: levelEntries, violations };
|
|
133
|
+
}
|
|
134
|
+
#computeConfigCoverage(modules, moduleLayerMap) {
|
|
135
|
+
if (modules.length === 0) {
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
let covered = 0;
|
|
139
|
+
for (const mod of modules) {
|
|
140
|
+
if (moduleLayerMap.has(mod)) {
|
|
141
|
+
covered++;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return covered / modules.length;
|
|
145
|
+
}
|
|
146
|
+
/* ─── Topology-based layer inference ────────────── */
|
|
147
|
+
#inferFromTopology(edges, modules, cycles) {
|
|
31
148
|
// 1. 建图 (邻接表: from → to[])
|
|
32
149
|
const adjacency = new Map();
|
|
33
150
|
const reverseAdj = new Map();
|
|
@@ -21,4 +21,13 @@ export declare class ModuleDiscoverer {
|
|
|
21
21
|
* 若无 module 实体,返回空数组(让调用侧决定是否重新扫描)。
|
|
22
22
|
*/
|
|
23
23
|
discover(): ModuleCandidate[];
|
|
24
|
+
/**
|
|
25
|
+
* 读取 config layers 元数据(如果存在)
|
|
26
|
+
* @returns 从 `__config_layers__` 实体中恢复的层级定义
|
|
27
|
+
*/
|
|
28
|
+
readConfigLayers(): Array<{
|
|
29
|
+
name: string;
|
|
30
|
+
order: number;
|
|
31
|
+
accessibleLayers: string[];
|
|
32
|
+
}> | null;
|
|
24
33
|
}
|
|
@@ -58,10 +58,11 @@ export class ModuleDiscoverer {
|
|
|
58
58
|
* 若无 module 实体,返回空数组(让调用侧决定是否重新扫描)。
|
|
59
59
|
*/
|
|
60
60
|
discover() {
|
|
61
|
-
// 从 code_entities 查 entity_type = 'module'
|
|
61
|
+
// 从 code_entities 查 entity_type = 'module'(排除 external/host 节点)
|
|
62
62
|
const moduleEntities = this.#db
|
|
63
63
|
.prepare(`SELECT DISTINCT entity_id, name FROM code_entities
|
|
64
|
-
WHERE entity_type = 'module' AND project_root =
|
|
64
|
+
WHERE entity_type = 'module' AND project_root = ?
|
|
65
|
+
AND COALESCE(json_extract(metadata_json, '$.nodeType'), 'local') NOT IN ('external', 'host')`)
|
|
65
66
|
.all(this.#projectRoot);
|
|
66
67
|
if (moduleEntities.length === 0) {
|
|
67
68
|
return [];
|
|
@@ -90,13 +91,68 @@ export class ModuleDiscoverer {
|
|
|
90
91
|
if (totalFileCount === 0) {
|
|
91
92
|
this.#enrichModuleFiles(moduleFiles);
|
|
92
93
|
}
|
|
94
|
+
// 读取模块 metadata 中的 configLayer 信息
|
|
95
|
+
const moduleLayerMap = this.#readModuleLayerMetadata(moduleEntities);
|
|
93
96
|
return [...moduleFiles.entries()].map(([name, files]) => ({
|
|
94
97
|
name,
|
|
95
98
|
inferredRole: inferTargetRole(name),
|
|
96
99
|
files: [...files],
|
|
100
|
+
configLayer: moduleLayerMap.get(name),
|
|
97
101
|
}));
|
|
98
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* 读取 config layers 元数据(如果存在)
|
|
105
|
+
* @returns 从 `__config_layers__` 实体中恢复的层级定义
|
|
106
|
+
*/
|
|
107
|
+
readConfigLayers() {
|
|
108
|
+
try {
|
|
109
|
+
const row = this.#db
|
|
110
|
+
.prepare(`SELECT metadata_json FROM code_entities
|
|
111
|
+
WHERE entity_id = '__config_layers__' AND entity_type = 'config' AND project_root = ?
|
|
112
|
+
LIMIT 1`)
|
|
113
|
+
.get(this.#projectRoot);
|
|
114
|
+
if (!row?.metadata_json) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const meta = typeof row.metadata_json === 'string' ? JSON.parse(row.metadata_json) : row.metadata_json;
|
|
118
|
+
if (Array.isArray(meta.layers) && meta.layers.length > 0) {
|
|
119
|
+
return meta.layers;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
/* skip parse error */
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
99
127
|
/* ─── 策略 1.5: 模块文件充填 ───────────────────── */
|
|
128
|
+
/**
|
|
129
|
+
* 从 code_entities metadata 中读取每个模块的 layer 信息
|
|
130
|
+
*/
|
|
131
|
+
#readModuleLayerMetadata(moduleEntities) {
|
|
132
|
+
const result = new Map();
|
|
133
|
+
for (const me of moduleEntities) {
|
|
134
|
+
const moduleName = me.entity_id;
|
|
135
|
+
try {
|
|
136
|
+
const row = this.#db
|
|
137
|
+
.prepare(`SELECT metadata_json FROM code_entities
|
|
138
|
+
WHERE entity_id = ? AND entity_type = 'module' AND project_root = ?
|
|
139
|
+
LIMIT 1`)
|
|
140
|
+
.get(moduleName, this.#projectRoot);
|
|
141
|
+
if (row?.metadata_json) {
|
|
142
|
+
const meta = typeof row.metadata_json === 'string'
|
|
143
|
+
? JSON.parse(row.metadata_json)
|
|
144
|
+
: row.metadata_json;
|
|
145
|
+
if (meta.layer && typeof meta.layer === 'string') {
|
|
146
|
+
result.set(moduleName, meta.layer);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
/* skip parse error */
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
100
156
|
/**
|
|
101
157
|
* 为已知模块名填充文件路径:
|
|
102
158
|
* a. 文件系统扫描(递归 4 层找模块同名目录)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { CouplingAnalyzer } from './CouplingAnalyzer.js';
|
|
10
10
|
import { DimensionAnalyzer } from './DimensionAnalyzer.js';
|
|
11
|
-
import type { LayerInferrer } from './LayerInferrer.js';
|
|
11
|
+
import type { ConfigLayer, LayerInferrer } from './LayerInferrer.js';
|
|
12
12
|
import type { CeDbLike, PanoramaResult } from './PanoramaTypes.js';
|
|
13
13
|
import type { ModuleCandidate, RoleRefiner } from './RoleRefiner.js';
|
|
14
14
|
export interface PanoramaAggregatorOptions {
|
|
@@ -24,6 +24,10 @@ export declare class PanoramaAggregator {
|
|
|
24
24
|
constructor(opts: PanoramaAggregatorOptions);
|
|
25
25
|
/**
|
|
26
26
|
* 计算完整全景数据
|
|
27
|
+
* @param moduleCandidates 模块候选列表
|
|
28
|
+
* @param options.configLayers 来自配置文件的层级声明(如 Boxfile layer 定义)
|
|
27
29
|
*/
|
|
28
|
-
compute(moduleCandidates: ModuleCandidate[]
|
|
30
|
+
compute(moduleCandidates: ModuleCandidate[], options?: {
|
|
31
|
+
configLayers?: ConfigLayer[] | null;
|
|
32
|
+
}): PanoramaResult;
|
|
29
33
|
}
|