autosnippet 3.2.21 → 3.3.2
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-BJ2mUBi8.js +1 -0
- package/dashboard/dist/assets/index-B659K9t5.js +128 -0
- package/dashboard/dist/assets/index-NCm40PMD.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.d.ts +1 -1
- package/dist/bin/cli.js +244 -261
- package/dist/lib/agent/context/ExplorationTracker.d.ts +2 -0
- package/dist/lib/agent/context/ExplorationTracker.js +21 -3
- package/dist/lib/agent/core/ToolExecutionPipeline.d.ts +3 -1
- package/dist/lib/agent/core/ToolExecutionPipeline.js +8 -1
- package/dist/lib/agent/forge/DynamicComposer.d.ts +58 -0
- package/dist/lib/agent/forge/DynamicComposer.js +99 -0
- package/dist/lib/agent/forge/SandboxRunner.d.ts +60 -0
- package/dist/lib/agent/forge/SandboxRunner.js +251 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.d.ts +76 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.js +154 -0
- package/dist/lib/agent/forge/ToolForge.d.ts +92 -0
- package/dist/lib/agent/forge/ToolForge.js +239 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.d.ts +44 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.js +119 -0
- package/dist/lib/agent/tools/ToolRegistry.d.ts +2 -0
- package/dist/lib/agent/tools/ToolRegistry.js +4 -0
- package/dist/lib/agent/tools/composite.js +0 -1
- package/dist/lib/agent/tools/index.d.ts +2 -50
- package/dist/lib/agent/tools/index.js +2 -3
- package/dist/lib/agent/tools/lifecycle.d.ts +1 -58
- package/dist/lib/agent/tools/lifecycle.js +2 -75
- package/dist/lib/cli/SetupService.d.ts +46 -2
- package/dist/lib/cli/SetupService.js +2 -27
- package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
- package/dist/lib/cli/deploy/FileManifest.js +0 -11
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.d.ts +2 -5
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.js +159 -44
- package/dist/lib/core/discovery/index.d.ts +1 -1
- package/dist/lib/core/discovery/index.js +2 -2
- package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +10 -0
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +2 -0
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +19 -2
- package/dist/lib/domain/knowledge/Lifecycle.js +32 -6
- package/dist/lib/domain/knowledge/UnifiedValidator.d.ts +1 -5
- package/dist/lib/domain/knowledge/UnifiedValidator.js +7 -44
- package/dist/lib/domain/knowledge/values/Stats.d.ts +29 -0
- package/dist/lib/domain/knowledge/values/Stats.js +41 -0
- package/dist/lib/external/mcp/McpServer.d.ts +19 -38
- package/dist/lib/external/mcp/McpServer.js +145 -117
- package/dist/lib/external/mcp/autoApproveInjector.js +0 -2
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +26 -1
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +41 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +3 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +27 -0
- package/dist/lib/external/mcp/handlers/bootstrap/skills.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -0
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
- package/dist/lib/external/mcp/handlers/consolidated.d.ts +116 -6
- package/dist/lib/external/mcp/handlers/consolidated.js +251 -71
- package/dist/lib/external/mcp/handlers/guard.d.ts +150 -0
- package/dist/lib/external/mcp/handlers/guard.js +245 -8
- package/dist/lib/external/mcp/handlers/knowledge.d.ts +0 -29
- package/dist/lib/external/mcp/handlers/knowledge.js +1 -76
- package/dist/lib/external/mcp/handlers/panorama.d.ts +36 -0
- package/dist/lib/external/mcp/handlers/panorama.js +156 -0
- package/dist/lib/external/mcp/handlers/system.d.ts +2 -54
- package/dist/lib/external/mcp/handlers/system.js +3 -113
- package/dist/lib/external/mcp/handlers/task.d.ts +13 -24
- package/dist/lib/external/mcp/handlers/task.js +217 -557
- package/dist/lib/external/mcp/handlers/types.d.ts +91 -8
- package/dist/lib/external/mcp/handlers/types.js +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.d.ts +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.js +16 -1
- package/dist/lib/external/mcp/tools.d.ts +14 -20
- package/dist/lib/external/mcp/tools.js +62 -91
- package/dist/lib/http/HttpServer.js +52 -6
- package/dist/lib/http/routes/{snippets.d.ts → audit.d.ts} +4 -2
- package/dist/lib/http/routes/audit.js +51 -0
- package/dist/lib/http/routes/commands.d.ts +1 -1
- package/dist/lib/http/routes/commands.js +1 -66
- package/dist/lib/http/routes/guardReport.d.ts +10 -0
- package/dist/lib/http/routes/guardReport.js +143 -0
- package/dist/lib/http/routes/knowledge.js +32 -1
- package/dist/lib/http/routes/panorama.d.ts +11 -0
- package/dist/lib/http/routes/panorama.js +322 -0
- package/dist/lib/http/routes/remote.js +0 -5
- package/dist/lib/http/routes/signals.d.ts +10 -0
- package/dist/lib/http/routes/signals.js +104 -0
- package/dist/lib/http/routes/task.d.ts +2 -3
- package/dist/lib/http/routes/task.js +17 -347
- package/dist/lib/http/routes/violations.js +1 -1
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +6 -1
- package/dist/lib/infrastructure/audit/AuditLogger.js +14 -1
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +181 -583
- package/dist/lib/infrastructure/database/drizzle/schema.js +28 -69
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.d.ts +8 -0
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.js +43 -0
- package/dist/lib/infrastructure/logging/Logger.d.ts +2 -0
- package/dist/lib/infrastructure/logging/Logger.js +34 -7
- package/dist/lib/infrastructure/monitoring/ErrorTracker.js +3 -1
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.d.ts +2 -2
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -10
- package/dist/lib/infrastructure/notification/LarkNotifier.d.ts +24 -0
- package/dist/lib/infrastructure/notification/LarkNotifier.js +97 -0
- package/dist/lib/infrastructure/report/ReportStore.d.ts +45 -0
- package/dist/lib/infrastructure/report/ReportStore.js +133 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.d.ts +18 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.js +84 -0
- package/dist/lib/infrastructure/signal/SignalBridge.d.ts +13 -0
- package/dist/lib/infrastructure/signal/SignalBridge.js +20 -0
- package/dist/lib/infrastructure/signal/SignalBus.d.ts +63 -0
- package/dist/lib/infrastructure/signal/SignalBus.js +106 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.d.ts +36 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.js +130 -0
- package/dist/lib/injection/ServiceContainer.js +6 -0
- package/dist/lib/injection/ServiceMap.d.ts +16 -19
- package/dist/lib/injection/modules/AgentModule.d.ts +1 -1
- package/dist/lib/injection/modules/AgentModule.js +7 -1
- package/dist/lib/injection/modules/AppModule.d.ts +3 -4
- package/dist/lib/injection/modules/AppModule.js +7 -43
- package/dist/lib/injection/modules/GuardModule.js +59 -2
- package/dist/lib/injection/modules/InfraModule.d.ts +0 -1
- package/dist/lib/injection/modules/InfraModule.js +9 -7
- package/dist/lib/injection/modules/KnowledgeModule.js +51 -0
- package/dist/lib/injection/modules/PanoramaModule.d.ts +18 -0
- package/dist/lib/injection/modules/PanoramaModule.js +76 -0
- package/dist/lib/injection/modules/SignalModule.d.ts +10 -0
- package/dist/lib/injection/modules/SignalModule.js +84 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +1 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +6 -0
- package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +3 -1
- package/dist/lib/service/bootstrap/BootstrapTaskManager.js +20 -1
- package/dist/lib/service/delivery/AgentInstructionsGenerator.js +4 -5
- package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +3 -1
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +13 -10
- package/dist/lib/service/delivery/RulesGenerator.js +3 -2
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +114 -0
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +542 -0
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +54 -0
- package/dist/lib/service/evolution/ContradictionDetector.js +253 -0
- package/dist/lib/service/evolution/DecayDetector.d.ts +71 -0
- package/dist/lib/service/evolution/DecayDetector.js +244 -0
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +38 -0
- package/dist/lib/service/evolution/EnhancementSuggester.js +220 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +82 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +167 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +53 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +210 -0
- package/dist/lib/service/evolution/StagingManager.d.ts +57 -0
- package/dist/lib/service/evolution/StagingManager.js +201 -0
- package/dist/lib/service/guard/ComplianceReporter.d.ts +42 -2
- package/dist/lib/service/guard/ComplianceReporter.js +43 -5
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +54 -0
- package/dist/lib/service/guard/CoverageAnalyzer.js +149 -0
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +55 -1
- package/dist/lib/service/guard/GuardCheckEngine.js +508 -15
- package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -0
- package/dist/lib/service/guard/GuardFeedbackLoop.js +9 -0
- package/dist/lib/service/guard/ReverseGuard.d.ts +73 -0
- package/dist/lib/service/guard/ReverseGuard.js +256 -0
- package/dist/lib/service/guard/RuleLearner.d.ts +12 -0
- package/dist/lib/service/guard/RuleLearner.js +38 -0
- package/dist/lib/service/guard/UncertaintyCollector.d.ts +83 -0
- package/dist/lib/service/guard/UncertaintyCollector.js +149 -0
- package/dist/lib/service/guard/ViolationsStore.d.ts +1 -0
- package/dist/lib/service/guard/ViolationsStore.js +33 -3
- package/dist/lib/service/knowledge/ConfidenceRouter.d.ts +13 -0
- package/dist/lib/service/knowledge/ConfidenceRouter.js +14 -0
- package/dist/lib/service/knowledge/KnowledgeService.js +22 -4
- package/dist/lib/service/module/ModuleService.js +3 -13
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +27 -0
- package/dist/lib/service/panorama/CouplingAnalyzer.js +192 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +28 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.js +320 -0
- package/dist/lib/service/panorama/LayerInferrer.d.ts +19 -0
- package/dist/lib/service/panorama/LayerInferrer.js +182 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +24 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.js +185 -0
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +29 -0
- package/dist/lib/service/panorama/PanoramaAggregator.js +228 -0
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +52 -0
- package/dist/lib/service/panorama/PanoramaScanner.js +188 -0
- package/dist/lib/service/panorama/PanoramaService.d.ts +108 -0
- package/dist/lib/service/panorama/PanoramaService.js +220 -0
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +134 -0
- package/dist/lib/service/panorama/PanoramaTypes.js +6 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +48 -0
- package/dist/lib/service/panorama/RoleRefiner.js +535 -0
- package/dist/lib/service/search/MultiSignalRanker.d.ts +1 -0
- package/dist/lib/service/search/MultiSignalRanker.js +16 -0
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +9 -1
- package/dist/lib/service/search/SearchTypes.d.ts +2 -0
- package/dist/lib/service/signal/HitRecorder.d.ts +68 -0
- package/dist/lib/service/signal/HitRecorder.js +173 -0
- package/dist/lib/service/skills/SignalCollector.d.ts +3 -1
- package/dist/lib/service/skills/SignalCollector.js +31 -1
- package/dist/lib/service/task/IntentExtractor.d.ts +58 -0
- package/dist/lib/service/task/IntentExtractor.js +142 -0
- package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
- package/dist/lib/service/task/PrimeSearchPipeline.js +98 -0
- package/dist/lib/shared/constants.d.ts +0 -15
- package/dist/lib/shared/constants.js +0 -10
- package/dist/lib/shared/schemas/config.d.ts +4 -1
- package/dist/lib/shared/schemas/config.js +8 -1
- package/dist/lib/shared/schemas/mcp-tools.d.ts +41 -96
- package/dist/lib/shared/schemas/mcp-tools.js +59 -119
- package/dist/scripts/analyze-signals.d.ts +20 -0
- package/dist/scripts/analyze-signals.js +155 -0
- package/dist/scripts/diagnose-mcp.js +1 -1
- package/dist/scripts/release.js +2 -10
- package/package.json +4 -19
- package/skills/autosnippet-devdocs/SKILL.md +11 -8
- package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
- package/templates/cursor-hooks/hooks/session-start.sh +1 -1
- package/templates/instructions/agent-static.md +2 -1
- package/templates/instructions/conventions.md +5 -6
- package/templates/recipes-setup/README.md +1 -2
- package/dashboard/dist/assets/icons-C1dUryS-.js +0 -1
- package/dashboard/dist/assets/index-D0whuycy.css +0 -1
- package/dashboard/dist/assets/index-DdvZE4Yd.js +0 -128
- package/dist/lib/domain/task/Task.d.ts +0 -140
- package/dist/lib/domain/task/Task.js +0 -254
- package/dist/lib/domain/task/TaskDependency.d.ts +0 -23
- package/dist/lib/domain/task/TaskDependency.js +0 -34
- package/dist/lib/domain/task/TaskIdGenerator.d.ts +0 -40
- package/dist/lib/domain/task/TaskIdGenerator.js +0 -75
- package/dist/lib/domain/task/index.d.ts +0 -4
- package/dist/lib/domain/task/index.js +0 -4
- package/dist/lib/http/routes/snippets.js +0 -49
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.d.ts +0 -11
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.js +0 -86
- package/dist/lib/platform/ClipboardManager.d.ts +0 -24
- package/dist/lib/platform/ClipboardManager.js +0 -142
- package/dist/lib/platform/NativeUi.d.ts +0 -53
- package/dist/lib/platform/NativeUi.js +0 -284
- package/dist/lib/platform/ios/index.d.ts +0 -38
- package/dist/lib/platform/ios/index.js +0 -42
- package/dist/lib/platform/ios/routes/spm.d.ts +0 -9
- package/dist/lib/platform/ios/routes/spm.js +0 -371
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.d.ts +0 -21
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.js +0 -48
- package/dist/lib/platform/ios/snippet/XcodeCodec.d.ts +0 -23
- package/dist/lib/platform/ios/snippet/XcodeCodec.js +0 -96
- package/dist/lib/platform/ios/spm/DependencyGraph.d.ts +0 -56
- package/dist/lib/platform/ios/spm/DependencyGraph.js +0 -195
- package/dist/lib/platform/ios/spm/PackageSwiftParser.d.ts +0 -69
- package/dist/lib/platform/ios/spm/PackageSwiftParser.js +0 -231
- package/dist/lib/platform/ios/spm/PathFinder.d.ts +0 -28
- package/dist/lib/platform/ios/spm/PathFinder.js +0 -117
- package/dist/lib/platform/ios/spm/PolicyEngine.d.ts +0 -44
- package/dist/lib/platform/ios/spm/PolicyEngine.js +0 -79
- package/dist/lib/platform/ios/spm/SpmHelper.d.ts +0 -102
- package/dist/lib/platform/ios/spm/SpmHelper.js +0 -464
- package/dist/lib/platform/ios/xcode/HeaderResolver.d.ts +0 -33
- package/dist/lib/platform/ios/xcode/HeaderResolver.js +0 -90
- package/dist/lib/platform/ios/xcode/SaveEventFilter.d.ts +0 -66
- package/dist/lib/platform/ios/xcode/SaveEventFilter.js +0 -142
- package/dist/lib/platform/ios/xcode/XcodeAutomation.d.ts +0 -71
- package/dist/lib/platform/ios/xcode/XcodeAutomation.js +0 -327
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.d.ts +0 -130
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.js +0 -404
- package/dist/lib/platform/ios/xcode/XcodeIntegration.d.ts +0 -89
- package/dist/lib/platform/ios/xcode/XcodeIntegration.js +0 -588
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.d.ts +0 -99
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.js +0 -190
- package/dist/lib/repository/task/TaskRepository.impl.d.ts +0 -171
- package/dist/lib/repository/task/TaskRepository.impl.js +0 -347
- package/dist/lib/service/automation/ActionPipeline.d.ts +0 -34
- package/dist/lib/service/automation/ActionPipeline.js +0 -53
- package/dist/lib/service/automation/AutomationOrchestrator.d.ts +0 -86
- package/dist/lib/service/automation/AutomationOrchestrator.js +0 -57
- package/dist/lib/service/automation/ContextCollector.d.ts +0 -24
- package/dist/lib/service/automation/ContextCollector.js +0 -35
- package/dist/lib/service/automation/DirectiveDetector.d.ts +0 -51
- package/dist/lib/service/automation/DirectiveDetector.js +0 -112
- package/dist/lib/service/automation/FileWatcher.d.ts +0 -51
- package/dist/lib/service/automation/FileWatcher.js +0 -366
- package/dist/lib/service/automation/TriggerResolver.d.ts +0 -36
- package/dist/lib/service/automation/TriggerResolver.js +0 -62
- package/dist/lib/service/automation/handlers/AlinkHandler.d.ts +0 -7
- package/dist/lib/service/automation/handlers/AlinkHandler.js +0 -80
- package/dist/lib/service/automation/handlers/CreateHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/CreateHandler.js +0 -170
- package/dist/lib/service/automation/handlers/GuardHandler.d.ts +0 -17
- package/dist/lib/service/automation/handlers/GuardHandler.js +0 -218
- package/dist/lib/service/automation/handlers/HeaderHandler.d.ts +0 -2
- package/dist/lib/service/automation/handlers/HeaderHandler.js +0 -32
- package/dist/lib/service/automation/handlers/SearchHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/SearchHandler.js +0 -278
- package/dist/lib/service/snippet/SnippetFactory.d.ts +0 -101
- package/dist/lib/service/snippet/SnippetFactory.js +0 -145
- package/dist/lib/service/snippet/SnippetInstaller.d.ts +0 -91
- package/dist/lib/service/snippet/SnippetInstaller.js +0 -276
- package/dist/lib/service/snippet/codecs/SnippetCodec.d.ts +0 -44
- package/dist/lib/service/snippet/codecs/SnippetCodec.js +0 -35
- package/dist/lib/service/snippet/codecs/VSCodeCodec.d.ts +0 -27
- package/dist/lib/service/snippet/codecs/VSCodeCodec.js +0 -82
- package/dist/lib/service/task/TaskGraphService.d.ts +0 -222
- package/dist/lib/service/task/TaskGraphService.js +0 -597
- package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +0 -95
- package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -298
- package/dist/lib/service/task/TaskReadyEngine.d.ts +0 -84
- package/dist/lib/service/task/TaskReadyEngine.js +0 -115
- package/dist/scripts/build-native-ui.d.ts +0 -3
- package/dist/scripts/build-native-ui.js +0 -62
- package/dist/scripts/init-snippets.d.ts +0 -30
- package/dist/scripts/init-snippets.js +0 -298
- package/dist/scripts/install-full.d.ts +0 -7
- package/dist/scripts/install-full.js +0 -38
- package/resources/native-ui/README.md +0 -29
- package/resources/native-ui/combined-window.swift +0 -494
- package/resources/native-ui/main.swift +0 -598
- package/scripts/postinstall-safe.mjs +0 -89
|
@@ -2,20 +2,27 @@
|
|
|
2
2
|
* @module SpmDiscoverer
|
|
3
3
|
* @description SPM 项目发现器,适配 ProjectDiscoverer 接口
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* SpmHelper 仅用于 Xcode 工作流的依赖检查/修复,不在此链路加载。
|
|
5
|
+
* 内置 Package.swift 正则解析,提供模块列表和文件遍历。
|
|
7
6
|
*
|
|
8
7
|
* 检测: 项目根或子目录存在 Package.swift
|
|
9
8
|
*/
|
|
10
|
-
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
9
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
11
10
|
import { basename, dirname, extname, join } from 'node:path';
|
|
12
|
-
import { ProjectDiscoverer } from '#core/discovery/ProjectDiscoverer.js';
|
|
13
11
|
import { LanguageService } from '#shared/LanguageService.js';
|
|
14
|
-
import {
|
|
12
|
+
import { ProjectDiscoverer } from './ProjectDiscoverer.js';
|
|
13
|
+
const SKIP_DIRS = new Set([
|
|
14
|
+
'node_modules',
|
|
15
|
+
'.git',
|
|
16
|
+
'Build',
|
|
17
|
+
'.build',
|
|
18
|
+
'.swiftpm',
|
|
19
|
+
'Pods',
|
|
20
|
+
'DerivedData',
|
|
21
|
+
'Carthage',
|
|
22
|
+
'.cursor',
|
|
23
|
+
]);
|
|
15
24
|
export class SpmDiscoverer extends ProjectDiscoverer {
|
|
16
|
-
#parser = null;
|
|
17
25
|
#projectRoot = null;
|
|
18
|
-
/** >} */
|
|
19
26
|
#parsedPackages = [];
|
|
20
27
|
get id() {
|
|
21
28
|
return 'spm';
|
|
@@ -24,12 +31,10 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
24
31
|
return 'Swift Package Manager (SPM)';
|
|
25
32
|
}
|
|
26
33
|
async detect(projectRoot) {
|
|
27
|
-
// 检查项目根是否有 Package.swift
|
|
28
34
|
const hasRoot = existsSync(join(projectRoot, 'Package.swift'));
|
|
29
35
|
if (hasRoot) {
|
|
30
36
|
return { match: true, confidence: 0.95, reason: 'Package.swift found at project root' };
|
|
31
37
|
}
|
|
32
|
-
// 检查子目录是否有 Package.swift(多包项目)
|
|
33
38
|
try {
|
|
34
39
|
const entries = readdirSync(projectRoot, { withFileTypes: true });
|
|
35
40
|
for (const entry of entries) {
|
|
@@ -51,12 +56,11 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
51
56
|
}
|
|
52
57
|
async load(projectRoot) {
|
|
53
58
|
this.#projectRoot = projectRoot;
|
|
54
|
-
this.#parser = new PackageSwiftParser(projectRoot);
|
|
55
59
|
this.#parsedPackages = [];
|
|
56
|
-
const allPaths = this.#
|
|
60
|
+
const allPaths = this.#findAllPackageSwifts(projectRoot);
|
|
57
61
|
for (const pkgPath of allPaths) {
|
|
58
62
|
try {
|
|
59
|
-
const parsed = this.#
|
|
63
|
+
const parsed = this.#parsePackageSwift(pkgPath);
|
|
60
64
|
if (parsed) {
|
|
61
65
|
this.#parsedPackages.push({ pkgPath, parsed });
|
|
62
66
|
}
|
|
@@ -67,9 +71,6 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
async listTargets() {
|
|
70
|
-
if (!this.#parser) {
|
|
71
|
-
return [];
|
|
72
|
-
}
|
|
73
74
|
const targets = [];
|
|
74
75
|
for (const { pkgPath, parsed } of this.#parsedPackages) {
|
|
75
76
|
const pkgDir = dirname(pkgPath);
|
|
@@ -91,17 +92,12 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
91
92
|
return targets;
|
|
92
93
|
}
|
|
93
94
|
async getTargetFiles(target) {
|
|
94
|
-
if (!this.#parser) {
|
|
95
|
-
return [];
|
|
96
|
-
}
|
|
97
95
|
const targetName = typeof target === 'string' ? target : target.name;
|
|
98
|
-
// 找到 target 所在的包目录和自定义 path
|
|
99
96
|
let sourcesDir = null;
|
|
100
97
|
for (const { pkgPath, parsed } of this.#parsedPackages) {
|
|
101
98
|
const matchTarget = parsed.targets?.find((t) => t.name === targetName);
|
|
102
99
|
if (matchTarget) {
|
|
103
100
|
const pkgDir = dirname(pkgPath);
|
|
104
|
-
// 优先使用 target 声明的自定义 path
|
|
105
101
|
const candidates = [];
|
|
106
102
|
if (matchTarget.path) {
|
|
107
103
|
candidates.push(join(pkgDir, matchTarget.path));
|
|
@@ -120,7 +116,6 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
120
116
|
}
|
|
121
117
|
}
|
|
122
118
|
if (!sourcesDir) {
|
|
123
|
-
// Fallback: projectRoot/Sources/targetName
|
|
124
119
|
const fallback = join(this.#projectRoot, 'Sources', targetName);
|
|
125
120
|
if (existsSync(fallback)) {
|
|
126
121
|
sourcesDir = fallback;
|
|
@@ -137,7 +132,7 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
137
132
|
}));
|
|
138
133
|
}
|
|
139
134
|
async getDependencyGraph() {
|
|
140
|
-
if (!this.#projectRoot
|
|
135
|
+
if (!this.#projectRoot) {
|
|
141
136
|
return { nodes: [], edges: [] };
|
|
142
137
|
}
|
|
143
138
|
if (this.#parsedPackages.length === 0) {
|
|
@@ -147,7 +142,6 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
147
142
|
const edges = [];
|
|
148
143
|
const pkgNameSet = new Set();
|
|
149
144
|
const targetToPkg = new Map();
|
|
150
|
-
// ── 第一遍:收集所有 package + target 节点 ──
|
|
151
145
|
const allParsed = [];
|
|
152
146
|
const umbrellaNames = new Set();
|
|
153
147
|
for (const { pkgPath, parsed } of this.#parsedPackages) {
|
|
@@ -156,14 +150,12 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
156
150
|
}
|
|
157
151
|
pkgNameSet.add(parsed.name);
|
|
158
152
|
allParsed.push({ ...parsed, _dir: dirname(pkgPath) });
|
|
159
|
-
// 跳过 umbrella 包(无 targets + 无 products)——它只是组织子包的入口
|
|
160
153
|
const hasTargets = parsed.targets && parsed.targets.length > 0;
|
|
161
154
|
const hasProducts = parsed.products && parsed.products.length > 0;
|
|
162
155
|
if (!hasTargets && !hasProducts) {
|
|
163
156
|
umbrellaNames.add(parsed.name);
|
|
164
157
|
continue;
|
|
165
158
|
}
|
|
166
|
-
// package 节点
|
|
167
159
|
nodes.push({
|
|
168
160
|
id: parsed.name,
|
|
169
161
|
label: parsed.name,
|
|
@@ -171,7 +163,6 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
171
163
|
fullPath: dirname(pkgPath),
|
|
172
164
|
targetCount: parsed.targets.length,
|
|
173
165
|
});
|
|
174
|
-
// target 节点
|
|
175
166
|
for (const t of parsed.targets) {
|
|
176
167
|
nodes.push({
|
|
177
168
|
id: t.name,
|
|
@@ -182,27 +173,22 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
182
173
|
});
|
|
183
174
|
targetToPkg.set(t.name, parsed.name);
|
|
184
175
|
}
|
|
185
|
-
// product name → package(product 名可能和 target 名不同)
|
|
186
176
|
for (const prod of parsed.products || []) {
|
|
187
177
|
if (!targetToPkg.has(prod.name)) {
|
|
188
178
|
targetToPkg.set(prod.name, parsed.name);
|
|
189
179
|
}
|
|
190
180
|
}
|
|
191
181
|
}
|
|
192
|
-
// ── 第二遍:构建 edges ──
|
|
193
182
|
for (const parsed of allParsed) {
|
|
194
|
-
// 跳过 umbrella 包的边
|
|
195
183
|
if (umbrellaNames.has(parsed.name)) {
|
|
196
184
|
continue;
|
|
197
185
|
}
|
|
198
|
-
// 包级 local path 依赖
|
|
199
186
|
for (const dep of parsed.dependencies || []) {
|
|
200
187
|
if (dep.type === 'local' && 'path' in dep && dep.path) {
|
|
201
188
|
const depPkgSwift = join(parsed._dir, dep.path, 'Package.swift');
|
|
202
189
|
if (existsSync(depPkgSwift)) {
|
|
203
190
|
try {
|
|
204
|
-
const depParsed = this.#
|
|
205
|
-
// 跳过指向 umbrella 包的边
|
|
191
|
+
const depParsed = this.#parsePackageSwift(depPkgSwift);
|
|
206
192
|
if (!umbrellaNames.has(depParsed.name)) {
|
|
207
193
|
edges.push({ from: parsed.name, to: depParsed.name, type: 'depends_on' });
|
|
208
194
|
}
|
|
@@ -224,12 +210,9 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
224
210
|
edges.push({ from: parsed.name, to: remoteName, type: 'depends_on' });
|
|
225
211
|
}
|
|
226
212
|
}
|
|
227
|
-
// target 级依赖
|
|
228
213
|
for (const t of parsed.targets || []) {
|
|
229
|
-
// target → parent package (contains)
|
|
230
214
|
edges.push({ from: parsed.name, to: t.name, type: 'contains' });
|
|
231
215
|
for (const depName of t.dependencies || []) {
|
|
232
|
-
// target → target 依赖(跳过指向 umbrella 包的)
|
|
233
216
|
if (!umbrellaNames.has(depName)) {
|
|
234
217
|
edges.push({ from: t.name, to: depName, type: 'depends_on' });
|
|
235
218
|
}
|
|
@@ -238,16 +221,148 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
238
221
|
}
|
|
239
222
|
return { nodes, edges };
|
|
240
223
|
}
|
|
241
|
-
/** @deprecated SpmHelper 不再由 SpmDiscoverer 持有,仅 XcodeIntegration 通过 container 使用 */
|
|
242
|
-
getSpmService() {
|
|
243
|
-
return null;
|
|
244
|
-
}
|
|
245
224
|
// ─────────────── Private Helpers ───────────────
|
|
246
|
-
/**
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
225
|
+
/** 向下递归扫描所有 Package.swift(支持多 Package 项目) */
|
|
226
|
+
#findAllPackageSwifts(rootDir) {
|
|
227
|
+
const results = [];
|
|
228
|
+
const scan = (dir, depth = 0) => {
|
|
229
|
+
if (depth > 5) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
234
|
+
for (const entry of entries) {
|
|
235
|
+
if (entry.isDirectory()) {
|
|
236
|
+
if (SKIP_DIRS.has(entry.name)) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
scan(join(dir, entry.name), depth + 1);
|
|
240
|
+
}
|
|
241
|
+
else if (entry.name === 'Package.swift') {
|
|
242
|
+
results.push(join(dir, entry.name));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// 权限错误等,跳过
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
scan(rootDir);
|
|
251
|
+
return results;
|
|
252
|
+
}
|
|
253
|
+
/** 简易解析 Package.swift(无 Swift 编译器,使用正则) */
|
|
254
|
+
#parsePackageSwift(packagePath) {
|
|
255
|
+
if (!packagePath || !existsSync(packagePath)) {
|
|
256
|
+
throw new Error(`Package.swift not found: ${packagePath}`);
|
|
257
|
+
}
|
|
258
|
+
const content = readFileSync(packagePath, 'utf-8');
|
|
259
|
+
return {
|
|
260
|
+
path: packagePath,
|
|
261
|
+
name: this.#extractName(content),
|
|
262
|
+
version: this.#extractVersion(content),
|
|
263
|
+
targets: this.#extractTargets(content),
|
|
264
|
+
dependencies: this.#extractDependencies(content),
|
|
265
|
+
products: this.#extractProducts(content),
|
|
266
|
+
platforms: this.#extractPlatforms(content),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
#extractName(content) {
|
|
270
|
+
const m = content.match(/name\s*:\s*"([^"]+)"/);
|
|
271
|
+
return m ? m[1] : 'unknown';
|
|
272
|
+
}
|
|
273
|
+
#extractVersion(content) {
|
|
274
|
+
const m = content.match(/version\s*:\s*"([^"]+)"/);
|
|
275
|
+
return m ? m[1] : '0.0.0';
|
|
276
|
+
}
|
|
277
|
+
#extractTargets(content) {
|
|
278
|
+
const targets = [];
|
|
279
|
+
const re = /\.(?:target|testTarget|executableTarget)\s*\(/g;
|
|
280
|
+
let match;
|
|
281
|
+
while ((match = re.exec(content)) !== null) {
|
|
282
|
+
const type = match[0].includes('testTarget')
|
|
283
|
+
? 'testTarget'
|
|
284
|
+
: match[0].includes('executableTarget')
|
|
285
|
+
? 'executableTarget'
|
|
286
|
+
: 'target';
|
|
287
|
+
const startPos = match.index + match[0].length;
|
|
288
|
+
let depth = 1;
|
|
289
|
+
let endPos = startPos;
|
|
290
|
+
while (depth > 0 && endPos < content.length) {
|
|
291
|
+
if (content[endPos] === '(') {
|
|
292
|
+
depth++;
|
|
293
|
+
}
|
|
294
|
+
else if (content[endPos] === ')') {
|
|
295
|
+
depth--;
|
|
296
|
+
}
|
|
297
|
+
endPos++;
|
|
298
|
+
}
|
|
299
|
+
if (depth === 0) {
|
|
300
|
+
const block = content.substring(startPos, endPos - 1);
|
|
301
|
+
const nameMatch = block.match(/name\s*:\s*"([^"]+)"/);
|
|
302
|
+
if (!nameMatch) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
const pathMatch = block.match(/path\s*:\s*"([^"]+)"/);
|
|
306
|
+
const depsMatch = block.match(/dependencies\s*:\s*\[([^\]]*)\]/s);
|
|
307
|
+
const deps = [];
|
|
308
|
+
if (depsMatch) {
|
|
309
|
+
const depRe = /\.(?:product|target)\s*\(\s*name\s*:\s*"([^"]+)"/g;
|
|
310
|
+
let dm;
|
|
311
|
+
while ((dm = depRe.exec(depsMatch[1])) !== null) {
|
|
312
|
+
deps.push(dm[1]);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
targets.push({
|
|
316
|
+
name: nameMatch[1],
|
|
317
|
+
type,
|
|
318
|
+
path: pathMatch ? pathMatch[1] : null,
|
|
319
|
+
dependencies: deps,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return targets;
|
|
324
|
+
}
|
|
325
|
+
#extractDependencies(content) {
|
|
326
|
+
const deps = [];
|
|
327
|
+
const urlRe = /\.package\s*\(\s*url\s*:\s*"([^"]+)"[^)]*\)/g;
|
|
328
|
+
let m;
|
|
329
|
+
while ((m = urlRe.exec(content)) !== null) {
|
|
330
|
+
const block = m[0];
|
|
331
|
+
const fromMatch = block.match(/from\s*:\s*"([^"]+)"/);
|
|
332
|
+
const exactMatch = block.match(/exact\s*:\s*"([^"]+)"/);
|
|
333
|
+
deps.push({
|
|
334
|
+
url: m[1],
|
|
335
|
+
version: fromMatch ? fromMatch[1] : exactMatch ? exactMatch[1] : null,
|
|
336
|
+
type: 'package',
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
const pathRe = /\.package\s*\(\s*path\s*:\s*"([^"]+)"\s*\)/g;
|
|
340
|
+
while ((m = pathRe.exec(content)) !== null) {
|
|
341
|
+
deps.push({
|
|
342
|
+
path: m[1],
|
|
343
|
+
type: 'local',
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
return deps;
|
|
347
|
+
}
|
|
348
|
+
#extractProducts(content) {
|
|
349
|
+
const products = [];
|
|
350
|
+
const re = /\.(library|executable)\s*\(\s*name\s*:\s*"([^"]+)"/g;
|
|
351
|
+
let m;
|
|
352
|
+
while ((m = re.exec(content)) !== null) {
|
|
353
|
+
products.push({ name: m[2], type: m[1] });
|
|
354
|
+
}
|
|
355
|
+
return products;
|
|
356
|
+
}
|
|
357
|
+
#extractPlatforms(content) {
|
|
358
|
+
const platforms = [];
|
|
359
|
+
const re = /\.(iOS|macOS|tvOS|watchOS|visionOS)\s*\(\s*\.v(\d+(?:_\d+)?)\s*\)/g;
|
|
360
|
+
let m;
|
|
361
|
+
while ((m = re.exec(content)) !== null) {
|
|
362
|
+
platforms.push({ name: m[1], version: m[2].replace(/_/g, '.') });
|
|
363
|
+
}
|
|
364
|
+
return platforms;
|
|
365
|
+
}
|
|
251
366
|
#walkSourceFiles(dir) {
|
|
252
367
|
const CODE_EXTS = new Set(['.swift', '.m', '.h', '.c', '.cpp', '.mm']);
|
|
253
368
|
const SKIP_DIRS = new Set([
|
|
@@ -7,7 +7,6 @@ import { DiscovererRegistry } from './DiscovererRegistry.js';
|
|
|
7
7
|
export declare function getDiscovererRegistry(): DiscovererRegistry;
|
|
8
8
|
/** 重置 Registry(仅用于测试) */
|
|
9
9
|
export declare function resetDiscovererRegistry(): void;
|
|
10
|
-
export { SpmDiscoverer } from '../../platform/ios/spm/SpmDiscoverer.js';
|
|
11
10
|
export { DartDiscoverer } from './DartDiscoverer.js';
|
|
12
11
|
export { DiscovererRegistry } from './DiscovererRegistry.js';
|
|
13
12
|
export { GenericDiscoverer } from './GenericDiscoverer.js';
|
|
@@ -17,3 +16,4 @@ export { NodeDiscoverer } from './NodeDiscoverer.js';
|
|
|
17
16
|
export { ProjectDiscoverer } from './ProjectDiscoverer.js';
|
|
18
17
|
export { PythonDiscoverer } from './PythonDiscoverer.js';
|
|
19
18
|
export { RustDiscoverer } from './RustDiscoverer.js';
|
|
19
|
+
export { SpmDiscoverer } from './SpmDiscoverer.js';
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* @module discovery/index
|
|
3
3
|
* @description ProjectDiscoverer 系统入口 - 初始化 Registry 并注册所有 Discoverer
|
|
4
4
|
*/
|
|
5
|
-
import { SpmDiscoverer } from '../../platform/ios/spm/SpmDiscoverer.js';
|
|
6
5
|
import { DartDiscoverer } from './DartDiscoverer.js';
|
|
7
6
|
import { DiscovererRegistry } from './DiscovererRegistry.js';
|
|
8
7
|
import { GenericDiscoverer } from './GenericDiscoverer.js';
|
|
@@ -11,6 +10,7 @@ import { JvmDiscoverer } from './JvmDiscoverer.js';
|
|
|
11
10
|
import { NodeDiscoverer } from './NodeDiscoverer.js';
|
|
12
11
|
import { PythonDiscoverer } from './PythonDiscoverer.js';
|
|
13
12
|
import { RustDiscoverer } from './RustDiscoverer.js';
|
|
13
|
+
import { SpmDiscoverer } from './SpmDiscoverer.js';
|
|
14
14
|
let _registry = null;
|
|
15
15
|
/** 获取全局 DiscovererRegistry 单例 */
|
|
16
16
|
export function getDiscovererRegistry() {
|
|
@@ -32,7 +32,6 @@ export function getDiscovererRegistry() {
|
|
|
32
32
|
export function resetDiscovererRegistry() {
|
|
33
33
|
_registry = null;
|
|
34
34
|
}
|
|
35
|
-
export { SpmDiscoverer } from '../../platform/ios/spm/SpmDiscoverer.js';
|
|
36
35
|
export { DartDiscoverer } from './DartDiscoverer.js';
|
|
37
36
|
export { DiscovererRegistry } from './DiscovererRegistry.js';
|
|
38
37
|
export { GenericDiscoverer } from './GenericDiscoverer.js';
|
|
@@ -43,3 +42,4 @@ export { NodeDiscoverer } from './NodeDiscoverer.js';
|
|
|
43
42
|
export { ProjectDiscoverer } from './ProjectDiscoverer.js';
|
|
44
43
|
export { PythonDiscoverer } from './PythonDiscoverer.js';
|
|
45
44
|
export { RustDiscoverer } from './RustDiscoverer.js';
|
|
45
|
+
export { SpmDiscoverer } from './SpmDiscoverer.js';
|
|
@@ -11,6 +11,7 @@ export interface KnowledgeEntryProps {
|
|
|
11
11
|
at: number;
|
|
12
12
|
}>;
|
|
13
13
|
autoApprovable?: boolean;
|
|
14
|
+
stagingDeadline?: number | null;
|
|
14
15
|
language?: string;
|
|
15
16
|
category?: string;
|
|
16
17
|
knowledgeType?: string;
|
|
@@ -62,6 +63,7 @@ export declare class KnowledgeEntry {
|
|
|
62
63
|
at: number;
|
|
63
64
|
}>;
|
|
64
65
|
autoApprovable: boolean;
|
|
66
|
+
stagingDeadline: number | null;
|
|
65
67
|
language: string;
|
|
66
68
|
category: string;
|
|
67
69
|
knowledgeType: string;
|
|
@@ -240,6 +242,14 @@ export declare class KnowledgeEntry {
|
|
|
240
242
|
guardHits: number;
|
|
241
243
|
searchHits: number;
|
|
242
244
|
authority: number;
|
|
245
|
+
lastHitAt: number | null;
|
|
246
|
+
lastSearchedAt: number | null;
|
|
247
|
+
lastGuardHitAt: number | null;
|
|
248
|
+
hitsLast30d: number;
|
|
249
|
+
hitsLast90d: number;
|
|
250
|
+
searchHitsLast30d: number;
|
|
251
|
+
version: number;
|
|
252
|
+
ruleFalsePositiveRate: number | null;
|
|
243
253
|
};
|
|
244
254
|
headers: string[];
|
|
245
255
|
headerPaths: string[];
|
|
@@ -10,6 +10,7 @@ export class KnowledgeEntry {
|
|
|
10
10
|
lifecycle;
|
|
11
11
|
lifecycleHistory;
|
|
12
12
|
autoApprovable;
|
|
13
|
+
stagingDeadline;
|
|
13
14
|
// Language & Classification
|
|
14
15
|
language;
|
|
15
16
|
category;
|
|
@@ -65,6 +66,7 @@ export class KnowledgeEntry {
|
|
|
65
66
|
this.lifecycle = normalizeLifecycle(props.lifecycle || Lifecycle.PENDING);
|
|
66
67
|
this.lifecycleHistory = props.lifecycleHistory || [];
|
|
67
68
|
this.autoApprovable = props.autoApprovable ?? false;
|
|
69
|
+
this.stagingDeadline = props.stagingDeadline ?? null;
|
|
68
70
|
// ── 语言与分类 ──
|
|
69
71
|
this.language = props.language || '';
|
|
70
72
|
this.category = props.category || '';
|
|
@@ -1,28 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lifecycle —
|
|
2
|
+
* Lifecycle — 知识实体生命周期状态机(六态版)
|
|
3
3
|
*
|
|
4
4
|
* pending — 待审核(所有新条目初始状态)
|
|
5
|
+
* staging — 暂存期(高置信度,Grace Period 后自动 active)
|
|
5
6
|
* active — 已发布(可被搜索/Guard/Export 消费)
|
|
7
|
+
* evolving — 进化中(有 EvolutionProposal 附着,内容待更新)
|
|
8
|
+
* decaying — 衰退观察(30d Grace + 3x 确认后 deprecated)
|
|
6
9
|
* deprecated — 已废弃
|
|
7
10
|
*/
|
|
8
11
|
export declare const Lifecycle: {
|
|
9
12
|
/** 待审核 */
|
|
10
13
|
PENDING: string;
|
|
14
|
+
/** 暂存期(高置信度,Grace Period 后自动 active) */
|
|
15
|
+
STAGING: string;
|
|
11
16
|
/** 已发布(可被搜索/Guard/Export 消费) */
|
|
12
17
|
ACTIVE: string;
|
|
18
|
+
/** 进化中(有 EvolutionProposal 附着) */
|
|
19
|
+
EVOLVING: string;
|
|
20
|
+
/** 衰退观察期 */
|
|
21
|
+
DECAYING: string;
|
|
13
22
|
/** 已弃用 */
|
|
14
23
|
DEPRECATED: string;
|
|
15
24
|
};
|
|
16
25
|
/** 候选阶段的所有状态 */
|
|
17
26
|
export declare const CANDIDATE_STATES: string[];
|
|
27
|
+
/** 可消费状态(Guard/Search/Delivery 可使用的状态) */
|
|
28
|
+
export declare const CONSUMABLE_STATES: string[];
|
|
29
|
+
/** 降级消费状态(Guard violation 降为 warning,Search 降权) */
|
|
30
|
+
export declare const DEGRADED_STATES: string[];
|
|
18
31
|
/** 规范化生命周期值 */
|
|
19
32
|
export declare function normalizeLifecycle(lifecycle: string): string;
|
|
20
33
|
/** 检查状态转移是否合法 */
|
|
21
34
|
export declare function isValidTransition(from: string, to: string): boolean;
|
|
22
35
|
/** 是否为合法的生命周期值 */
|
|
23
36
|
export declare function isValidLifecycle(lifecycle: string): boolean;
|
|
24
|
-
/**
|
|
37
|
+
/** 是否处于候选阶段(待审核或暂存) */
|
|
25
38
|
export declare function isCandidate(lifecycle: string): boolean;
|
|
39
|
+
/** 是否为可消费状态(Guard/Search/Delivery 可使用) */
|
|
40
|
+
export declare function isConsumable(lifecycle: string): boolean;
|
|
41
|
+
/** 是否为降级消费状态 */
|
|
42
|
+
export declare function isDegraded(lifecycle: string): boolean;
|
|
26
43
|
/** 从 knowledgeType 推导 kind */
|
|
27
44
|
export declare function inferKind(knowledgeType: string): 'rule' | 'pattern' | 'fact';
|
|
28
45
|
export default Lifecycle;
|
|
@@ -1,24 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lifecycle —
|
|
2
|
+
* Lifecycle — 知识实体生命周期状态机(六态版)
|
|
3
3
|
*
|
|
4
4
|
* pending — 待审核(所有新条目初始状态)
|
|
5
|
+
* staging — 暂存期(高置信度,Grace Period 后自动 active)
|
|
5
6
|
* active — 已发布(可被搜索/Guard/Export 消费)
|
|
7
|
+
* evolving — 进化中(有 EvolutionProposal 附着,内容待更新)
|
|
8
|
+
* decaying — 衰退观察(30d Grace + 3x 确认后 deprecated)
|
|
6
9
|
* deprecated — 已废弃
|
|
7
10
|
*/
|
|
8
11
|
export const Lifecycle = {
|
|
9
12
|
/** 待审核 */
|
|
10
13
|
PENDING: 'pending',
|
|
14
|
+
/** 暂存期(高置信度,Grace Period 后自动 active) */
|
|
15
|
+
STAGING: 'staging',
|
|
11
16
|
/** 已发布(可被搜索/Guard/Export 消费) */
|
|
12
17
|
ACTIVE: 'active',
|
|
18
|
+
/** 进化中(有 EvolutionProposal 附着) */
|
|
19
|
+
EVOLVING: 'evolving',
|
|
20
|
+
/** 衰退观察期 */
|
|
21
|
+
DECAYING: 'decaying',
|
|
13
22
|
/** 已弃用 */
|
|
14
23
|
DEPRECATED: 'deprecated',
|
|
15
24
|
};
|
|
16
25
|
/** 候选阶段的所有状态 */
|
|
17
|
-
export const CANDIDATE_STATES = [Lifecycle.PENDING];
|
|
26
|
+
export const CANDIDATE_STATES = [Lifecycle.PENDING, Lifecycle.STAGING];
|
|
27
|
+
/** 可消费状态(Guard/Search/Delivery 可使用的状态) */
|
|
28
|
+
export const CONSUMABLE_STATES = [Lifecycle.STAGING, Lifecycle.ACTIVE, Lifecycle.EVOLVING];
|
|
29
|
+
/** 降级消费状态(Guard violation 降为 warning,Search 降权) */
|
|
30
|
+
export const DEGRADED_STATES = [Lifecycle.DECAYING];
|
|
18
31
|
/** 合法状态转移表 */
|
|
19
32
|
const VALID_TRANSITIONS = {
|
|
20
|
-
[Lifecycle.PENDING]: [Lifecycle.ACTIVE, Lifecycle.DEPRECATED],
|
|
21
|
-
[Lifecycle.
|
|
33
|
+
[Lifecycle.PENDING]: [Lifecycle.STAGING, Lifecycle.ACTIVE, Lifecycle.DEPRECATED],
|
|
34
|
+
[Lifecycle.STAGING]: [Lifecycle.ACTIVE, Lifecycle.PENDING],
|
|
35
|
+
[Lifecycle.ACTIVE]: [Lifecycle.EVOLVING, Lifecycle.DECAYING, Lifecycle.DEPRECATED],
|
|
36
|
+
[Lifecycle.EVOLVING]: [Lifecycle.ACTIVE, Lifecycle.DECAYING],
|
|
37
|
+
[Lifecycle.DECAYING]: [Lifecycle.ACTIVE, Lifecycle.DEPRECATED],
|
|
22
38
|
[Lifecycle.DEPRECATED]: [Lifecycle.PENDING],
|
|
23
39
|
};
|
|
24
40
|
/** 规范化生命周期值 */
|
|
@@ -39,10 +55,20 @@ export function isValidTransition(from, to) {
|
|
|
39
55
|
export function isValidLifecycle(lifecycle) {
|
|
40
56
|
return Object.values(Lifecycle).includes(lifecycle);
|
|
41
57
|
}
|
|
42
|
-
/**
|
|
58
|
+
/** 是否处于候选阶段(待审核或暂存) */
|
|
43
59
|
export function isCandidate(lifecycle) {
|
|
44
60
|
const normalized = normalizeLifecycle(lifecycle);
|
|
45
|
-
return normalized === Lifecycle.PENDING;
|
|
61
|
+
return normalized === Lifecycle.PENDING || normalized === Lifecycle.STAGING;
|
|
62
|
+
}
|
|
63
|
+
/** 是否为可消费状态(Guard/Search/Delivery 可使用) */
|
|
64
|
+
export function isConsumable(lifecycle) {
|
|
65
|
+
const normalized = normalizeLifecycle(lifecycle);
|
|
66
|
+
return CONSUMABLE_STATES.includes(normalized);
|
|
67
|
+
}
|
|
68
|
+
/** 是否为降级消费状态 */
|
|
69
|
+
export function isDegraded(lifecycle) {
|
|
70
|
+
const normalized = normalizeLifecycle(lifecycle);
|
|
71
|
+
return DEGRADED_STATES.includes(normalized);
|
|
46
72
|
}
|
|
47
73
|
/* ── knowledgeType → kind 映射 ── */
|
|
48
74
|
const KIND_MAP = {
|
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
* 替代 CandidateGuardrail + RecipeReadinessChecker 的分裂验证,
|
|
5
5
|
* 提供单一入口的三层验证 (字段完整性 + 内容质量 + 去重)。
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* strict — 默认:完整 REQUIRED 字段检查(标准知识条目)
|
|
9
|
-
* document — knowledgeType='dev-document' 时自动切换:跳过 Cursor 交付字段
|
|
10
|
-
* fallback — source 含 'fallback' 时:REQUIRED 降级为 WARNING
|
|
7
|
+
* 统一严格模式:完整 REQUIRED 字段检查,无宽松降级。
|
|
11
8
|
*
|
|
12
9
|
* @module shared/UnifiedValidator
|
|
13
10
|
*/
|
|
@@ -31,7 +28,6 @@ export declare class UnifiedValidator {
|
|
|
31
28
|
* @returns }
|
|
32
29
|
*/
|
|
33
30
|
validate(candidate: Record<string, unknown>, options?: {
|
|
34
|
-
mode?: 'strict' | 'document' | 'fallback';
|
|
35
31
|
systemInjectedFields?: string[];
|
|
36
32
|
skipUniqueness?: boolean;
|
|
37
33
|
}): {
|
|
@@ -4,25 +4,12 @@
|
|
|
4
4
|
* 替代 CandidateGuardrail + RecipeReadinessChecker 的分裂验证,
|
|
5
5
|
* 提供单一入口的三层验证 (字段完整性 + 内容质量 + 去重)。
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* strict — 默认:完整 REQUIRED 字段检查(标准知识条目)
|
|
9
|
-
* document — knowledgeType='dev-document' 时自动切换:跳过 Cursor 交付字段
|
|
10
|
-
* fallback — source 含 'fallback' 时:REQUIRED 降级为 WARNING
|
|
7
|
+
* 统一严格模式:完整 REQUIRED 字段检查,无宽松降级。
|
|
11
8
|
*
|
|
12
9
|
* @module shared/UnifiedValidator
|
|
13
10
|
*/
|
|
14
11
|
import { LanguageService } from '#shared/LanguageService.js';
|
|
15
12
|
import { FieldLevel, STANDARD_CATEGORIES, V3_FIELD_SPEC, VALID_KINDS, WHITELISTED_CATEGORIES, } from './FieldSpec.js';
|
|
16
|
-
// ── Cursor 交付字段集合(document 模式跳过这些) ────────────
|
|
17
|
-
const CURSOR_DELIVERY_FIELDS = new Set([
|
|
18
|
-
'trigger',
|
|
19
|
-
'kind',
|
|
20
|
-
'doClause',
|
|
21
|
-
'dontClause',
|
|
22
|
-
'whenClause',
|
|
23
|
-
'coreCode',
|
|
24
|
-
'topicHint',
|
|
25
|
-
]);
|
|
26
13
|
// ── 代码指纹工具函数 ───────────────────────────────────────
|
|
27
14
|
/** 生成代码模式指纹 — 去除空白/注释后取前 200 字符的小写形式 */
|
|
28
15
|
function codeFingerprint(code) {
|
|
@@ -33,17 +20,6 @@ function codeFingerprint(code) {
|
|
|
33
20
|
.toLowerCase()
|
|
34
21
|
.slice(0, 200);
|
|
35
22
|
}
|
|
36
|
-
// ── 模式自动检测 ────────────────────────────────────────────
|
|
37
|
-
/** 自动检测适合的验证模式 */
|
|
38
|
-
function detectMode(candidate) {
|
|
39
|
-
if (candidate.knowledgeType === 'dev-document') {
|
|
40
|
-
return 'document';
|
|
41
|
-
}
|
|
42
|
-
if (typeof candidate.source === 'string' && candidate.source.includes('fallback')) {
|
|
43
|
-
return 'fallback';
|
|
44
|
-
}
|
|
45
|
-
return 'strict';
|
|
46
|
-
}
|
|
47
23
|
// ── UnifiedValidator ────────────────────────────────────────
|
|
48
24
|
export class UnifiedValidator {
|
|
49
25
|
/** 已提交标题 (小写) */
|
|
@@ -70,14 +46,11 @@ export class UnifiedValidator {
|
|
|
70
46
|
validate(candidate, options = {}) {
|
|
71
47
|
const errors = [];
|
|
72
48
|
const warnings = [];
|
|
73
|
-
const mode = options.mode || detectMode(candidate);
|
|
74
49
|
const systemInjected = new Set(options.systemInjectedFields || []);
|
|
75
50
|
// ── Layer 1: 字段完整性 (基于 V3_FIELD_SPEC) ──
|
|
76
|
-
this.#checkFields(candidate,
|
|
51
|
+
this.#checkFields(candidate, systemInjected, errors, warnings);
|
|
77
52
|
// ── Layer 2: 内容质量 (来自 CandidateGuardrail.validateQuality) ──
|
|
78
|
-
|
|
79
|
-
this.#checkContentQuality(candidate, mode, errors, warnings);
|
|
80
|
-
}
|
|
53
|
+
this.#checkContentQuality(candidate, errors, warnings);
|
|
81
54
|
// ── Layer 3: 唯一性 (来自 CandidateGuardrail.validateUniqueness) ──
|
|
82
55
|
if (!options.skipUniqueness) {
|
|
83
56
|
this.#checkUniqueness(candidate, errors);
|
|
@@ -89,13 +62,9 @@ export class UnifiedValidator {
|
|
|
89
62
|
};
|
|
90
63
|
}
|
|
91
64
|
// ── Layer 1: 基于 FieldSpec 检查 ─────────────────────────
|
|
92
|
-
#checkFields(candidate,
|
|
65
|
+
#checkFields(candidate, systemInjected, errors, warnings) {
|
|
93
66
|
for (const field of V3_FIELD_SPEC) {
|
|
94
67
|
const { name, level, rule } = field;
|
|
95
|
-
// document 模式:跳过 Cursor 交付字段
|
|
96
|
-
if (mode === 'document' && CURSOR_DELIVERY_FIELDS.has(name.split('.')[0])) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
68
|
// 系统注入字段:跳过
|
|
100
69
|
if (systemInjected.has(name)) {
|
|
101
70
|
continue;
|
|
@@ -106,13 +75,7 @@ export class UnifiedValidator {
|
|
|
106
75
|
continue;
|
|
107
76
|
}
|
|
108
77
|
if (level === FieldLevel.REQUIRED) {
|
|
109
|
-
|
|
110
|
-
// fallback 模式:REQUIRED 降级为 warning
|
|
111
|
-
warnings.push(`${name}: ${rule}`);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
errors.push(`缺少必填字段: ${name} — ${rule}`);
|
|
115
|
-
}
|
|
78
|
+
errors.push(`缺少必填字段: ${name} — ${rule}`);
|
|
116
79
|
}
|
|
117
80
|
else if (level === FieldLevel.EXPECTED) {
|
|
118
81
|
warnings.push(`建议填写: ${name} — ${rule}`);
|
|
@@ -149,7 +112,7 @@ export class UnifiedValidator {
|
|
|
149
112
|
}
|
|
150
113
|
}
|
|
151
114
|
// ── Layer 2: 内容质量启发式 ──────────────────────────────
|
|
152
|
-
#checkContentQuality(candidate,
|
|
115
|
+
#checkContentQuality(candidate, errors, warnings) {
|
|
153
116
|
const markdown = candidate.content?.markdown || '';
|
|
154
117
|
// markdown ≥ 200 字符
|
|
155
118
|
if (markdown && markdown.length > 0 && markdown.length < 200) {
|
|
@@ -171,7 +134,7 @@ export class UnifiedValidator {
|
|
|
171
134
|
}
|
|
172
135
|
}
|
|
173
136
|
// coreCode 语法完整性
|
|
174
|
-
|
|
137
|
+
{
|
|
175
138
|
const coreCode = (candidate.coreCode || '').trim();
|
|
176
139
|
if (coreCode) {
|
|
177
140
|
const firstChar = coreCode[0];
|