autosnippet 3.3.4 → 3.3.6

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 (221) hide show
  1. package/README.md +174 -83
  2. package/config/constitution.yaml +2 -0
  3. package/dashboard/dist/assets/icons-D1aVZYFW.js +1 -0
  4. package/dashboard/dist/assets/index-CxHOu8Hd.css +1 -0
  5. package/dashboard/dist/assets/index-DDdAOpYT.js +128 -0
  6. package/dashboard/dist/index.html +3 -3
  7. package/dist/bin/api-server.js +1 -0
  8. package/dist/bin/cli.d.ts +1 -0
  9. package/dist/bin/cli.js +136 -9
  10. package/dist/lib/agent/AgentFactory.d.ts +0 -17
  11. package/dist/lib/agent/AgentFactory.js +1 -25
  12. package/dist/lib/agent/capabilities.d.ts +11 -0
  13. package/dist/lib/agent/capabilities.js +29 -5
  14. package/dist/lib/agent/context/ExplorationTracker.js +10 -1
  15. package/dist/lib/agent/context/exploration/ExplorationStrategies.d.ts +2 -0
  16. package/dist/lib/agent/context/exploration/ExplorationStrategies.js +2 -2
  17. package/dist/lib/agent/domain/insight-analyst.d.ts +47 -3
  18. package/dist/lib/agent/domain/insight-analyst.js +111 -11
  19. package/dist/lib/agent/domain/insight-evolver.d.ts +69 -0
  20. package/dist/lib/agent/domain/insight-evolver.js +230 -0
  21. package/dist/lib/agent/domain/insight-gate.d.ts +42 -0
  22. package/dist/lib/agent/domain/insight-gate.js +41 -0
  23. package/dist/lib/agent/domain/insight-producer.d.ts +27 -2
  24. package/dist/lib/agent/domain/insight-producer.js +60 -5
  25. package/dist/lib/agent/domain/scan-prompts.js +10 -7
  26. package/dist/lib/agent/memory/ActiveContext.d.ts +2 -28
  27. package/dist/lib/agent/memory/MemoryCoordinator.d.ts +2 -2
  28. package/dist/lib/agent/memory/SessionStore.d.ts +6 -12
  29. package/dist/lib/agent/memory/SessionStore.js +9 -15
  30. package/dist/lib/agent/memory/memory-flush-contract.d.ts +49 -0
  31. package/dist/lib/agent/memory/memory-flush-contract.js +16 -0
  32. package/dist/lib/agent/memory/session-store-schema.d.ts +20 -0
  33. package/dist/lib/agent/memory/session-store-schema.js +41 -0
  34. package/dist/lib/agent/presets.d.ts +89 -1
  35. package/dist/lib/agent/presets.js +53 -5
  36. package/dist/lib/agent/tools/_shared.d.ts +7 -15
  37. package/dist/lib/agent/tools/_shared.js +20 -21
  38. package/dist/lib/agent/tools/composite.d.ts +25 -22
  39. package/dist/lib/agent/tools/composite.js +108 -109
  40. package/dist/lib/agent/tools/evolution-tools.d.ts +145 -0
  41. package/dist/lib/agent/tools/evolution-tools.js +161 -0
  42. package/dist/lib/agent/tools/index.d.ts +163 -92
  43. package/dist/lib/agent/tools/index.js +9 -1
  44. package/dist/lib/agent/tools/lifecycle.d.ts +7 -1
  45. package/dist/lib/agent/tools/lifecycle.js +59 -75
  46. package/dist/lib/cli/AiScanService.js +1 -1
  47. package/dist/lib/cli/KnowledgeSyncService.d.ts +5 -1
  48. package/dist/lib/cli/KnowledgeSyncService.js +6 -3
  49. package/dist/lib/core/AstAnalyzer.d.ts +1 -0
  50. package/dist/lib/{service/bootstrap/DimensionCopyRegistry.d.ts → domain/dimension/DimensionCopy.d.ts} +2 -2
  51. package/dist/lib/{service/bootstrap/DimensionCopyRegistry.js → domain/dimension/DimensionCopy.js} +22 -72
  52. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +54 -0
  53. package/dist/lib/domain/dimension/DimensionRegistry.js +620 -0
  54. package/dist/lib/domain/dimension/DimensionSop.d.ts +55 -0
  55. package/dist/lib/domain/dimension/DimensionSop.js +1604 -0
  56. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +61 -0
  57. package/dist/lib/domain/dimension/UnifiedDimension.js +53 -0
  58. package/dist/lib/domain/dimension/index.d.ts +10 -0
  59. package/dist/lib/domain/dimension/index.js +9 -0
  60. package/dist/lib/domain/knowledge/FieldSpec.d.ts +1 -1
  61. package/dist/lib/domain/knowledge/FieldSpec.js +29 -16
  62. package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +33 -111
  63. package/dist/lib/domain/knowledge/KnowledgeEntry.js +27 -6
  64. package/dist/lib/domain/knowledge/KnowledgeRepository.d.ts +1 -0
  65. package/dist/lib/domain/knowledge/KnowledgeRepository.js +3 -0
  66. package/dist/lib/domain/knowledge/Lifecycle.js +1 -1
  67. package/dist/lib/domain/knowledge/StyleGuide.d.ts +1 -1
  68. package/dist/lib/domain/knowledge/StyleGuide.js +1 -1
  69. package/dist/lib/domain/knowledge/UnifiedValidator.js +15 -0
  70. package/dist/lib/domain/knowledge/values/Stats.d.ts +1 -1
  71. package/dist/lib/domain/knowledge/values/Stats.js +2 -2
  72. package/dist/lib/external/mcp/McpServer.js +4 -0
  73. package/dist/lib/external/mcp/handlers/TargetClassifier.d.ts +1 -1
  74. package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.d.ts +8 -16
  75. package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +10 -10
  76. package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.d.ts +7 -0
  77. package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +20 -0
  78. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +52 -132
  79. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +204 -17
  80. package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.d.ts +11 -75
  81. package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.js +40 -191
  82. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.d.ts +13 -78
  83. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +30 -52
  84. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.d.ts +0 -1
  85. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.d.ts +99 -12
  86. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +172 -161
  87. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +7 -17
  88. package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.d.ts +46 -0
  89. package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.js +58 -0
  90. package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.d.ts +25 -0
  91. package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.js +47 -0
  92. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +50 -12
  93. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +30 -10
  94. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-text.js +1 -1
  95. package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.d.ts +24 -0
  96. package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.js +14 -0
  97. package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.d.ts +14 -0
  98. package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.js +48 -0
  99. package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.d.ts +21 -0
  100. package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.js +45 -0
  101. package/dist/lib/external/mcp/handlers/bootstrap/shared/skill-generator.d.ts +1 -1
  102. package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.d.ts +27 -0
  103. package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.js +44 -0
  104. package/dist/lib/external/mcp/handlers/bootstrap-external.d.ts +14 -10
  105. package/dist/lib/external/mcp/handlers/bootstrap-external.js +39 -51
  106. package/dist/lib/external/mcp/handlers/bootstrap-internal.d.ts +2 -0
  107. package/dist/lib/external/mcp/handlers/bootstrap-internal.js +115 -82
  108. package/dist/lib/external/mcp/handlers/consolidated.d.ts +4 -4
  109. package/dist/lib/external/mcp/handlers/consolidated.js +115 -162
  110. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +69 -1
  111. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +54 -0
  112. package/dist/lib/external/mcp/handlers/evolve-external.js +226 -0
  113. package/dist/lib/external/mcp/handlers/knowledge.js +26 -2
  114. package/dist/lib/external/mcp/handlers/rescan-external.d.ts +76 -0
  115. package/dist/lib/external/mcp/handlers/rescan-external.js +335 -0
  116. package/dist/lib/external/mcp/handlers/rescan-internal.d.ts +120 -0
  117. package/dist/lib/external/mcp/handlers/rescan-internal.js +359 -0
  118. package/dist/lib/external/mcp/handlers/search.d.ts +6 -5
  119. package/dist/lib/external/mcp/handlers/search.js +6 -5
  120. package/dist/lib/external/mcp/handlers/types.d.ts +2 -1
  121. package/dist/lib/external/mcp/handlers/wiki-external.js +2 -2
  122. package/dist/lib/external/mcp/tools.d.ts +8 -18
  123. package/dist/lib/external/mcp/tools.js +60 -3
  124. package/dist/lib/http/routes/knowledge.js +122 -1
  125. package/dist/lib/http/routes/modules.js +25 -3
  126. package/dist/lib/http/routes/panorama.js +16 -4
  127. package/dist/lib/infrastructure/cache/CacheCoordinator.d.ts +41 -0
  128. package/dist/lib/infrastructure/cache/CacheCoordinator.js +105 -0
  129. package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.d.ts +7 -0
  130. package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.js +28 -0
  131. package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +1 -1
  132. package/dist/lib/injection/ServiceContainer.js +55 -0
  133. package/dist/lib/injection/ServiceMap.d.ts +8 -1
  134. package/dist/lib/injection/modules/InfraModule.js +4 -1
  135. package/dist/lib/injection/modules/KnowledgeModule.js +38 -1
  136. package/dist/lib/repository/evolution/ProposalRepository.d.ts +99 -0
  137. package/dist/lib/repository/evolution/ProposalRepository.js +255 -0
  138. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +4 -0
  139. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +16 -1
  140. package/dist/lib/service/bootstrap/BootstrapEventEmitter.d.ts +3 -2
  141. package/dist/lib/service/bootstrap/BootstrapEventEmitter.js +1 -1
  142. package/dist/lib/service/bootstrap/DeliveryVerifier.d.ts +51 -0
  143. package/dist/lib/service/bootstrap/DeliveryVerifier.js +163 -0
  144. package/dist/lib/service/bootstrap/UiStartupTasks.d.ts +22 -4
  145. package/dist/lib/service/bootstrap/UiStartupTasks.js +73 -5
  146. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +54 -0
  147. package/dist/lib/service/bootstrap/bootstrap-event-types.js +10 -0
  148. package/dist/lib/service/cleanup/CleanupService.d.ts +85 -0
  149. package/dist/lib/service/cleanup/CleanupService.js +324 -0
  150. package/dist/lib/service/delivery/AgentInstructionsGenerator.js +39 -43
  151. package/dist/lib/service/delivery/FileProtection.d.ts +20 -0
  152. package/dist/lib/service/delivery/FileProtection.js +54 -0
  153. package/dist/lib/service/delivery/SkillsSyncer.js +16 -21
  154. package/dist/lib/service/evolution/ContentPatcher.d.ts +44 -0
  155. package/dist/lib/service/evolution/ContentPatcher.js +310 -0
  156. package/dist/lib/service/evolution/DecayDetector.d.ts +4 -3
  157. package/dist/lib/service/evolution/DecayDetector.js +97 -22
  158. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -2
  159. package/dist/lib/service/evolution/KnowledgeMetabolism.js +29 -2
  160. package/dist/lib/service/evolution/ProposalExecutor.d.ts +66 -0
  161. package/dist/lib/service/evolution/ProposalExecutor.js +424 -0
  162. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +64 -0
  163. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +458 -0
  164. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +89 -0
  165. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +492 -0
  166. package/dist/lib/service/evolution/StagingManager.js +5 -3
  167. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +44 -0
  168. package/dist/lib/service/evolution/createSupersedeProposal.js +81 -0
  169. package/dist/lib/service/guard/ComplianceReporter.d.ts +4 -0
  170. package/dist/lib/service/guard/ComplianceReporter.js +51 -0
  171. package/dist/lib/service/guard/GuardCheckEngine.js +5 -4
  172. package/dist/lib/service/guard/GuardCrossFileChecks.js +2 -0
  173. package/dist/lib/service/guard/ReverseGuard.d.ts +1 -1
  174. package/dist/lib/service/guard/ReverseGuard.js +32 -2
  175. package/dist/lib/service/knowledge/ConfidenceRouter.js +1 -1
  176. package/dist/lib/service/knowledge/KnowledgeService.d.ts +11 -1
  177. package/dist/lib/service/knowledge/KnowledgeService.js +44 -4
  178. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +225 -0
  179. package/dist/lib/service/knowledge/RecipeProductionGateway.js +384 -0
  180. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +2 -0
  181. package/dist/lib/service/knowledge/SourceRefReconciler.js +48 -0
  182. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +3 -2
  183. package/dist/lib/service/panorama/DimensionAnalyzer.js +15 -140
  184. package/dist/lib/service/search/BM25Scorer.d.ts +2 -2
  185. package/dist/lib/service/search/SearchEngine.d.ts +11 -10
  186. package/dist/lib/service/search/SearchEngine.js +38 -36
  187. package/dist/lib/service/search/SearchTypes.d.ts +14 -8
  188. package/dist/lib/service/search/SearchTypes.js +1 -1
  189. package/dist/lib/service/search/tokenizer.d.ts +1 -1
  190. package/dist/lib/service/search/tokenizer.js +2 -2
  191. package/dist/lib/shared/schemas/common.d.ts +4 -4
  192. package/dist/lib/shared/schemas/http-requests.d.ts +12 -1
  193. package/dist/lib/shared/schemas/http-requests.js +8 -0
  194. package/dist/lib/shared/schemas/mcp-tools.d.ts +33 -2
  195. package/dist/lib/shared/schemas/mcp-tools.js +42 -0
  196. package/dist/lib/types/evolution.d.ts +135 -0
  197. package/dist/lib/types/evolution.js +6 -0
  198. package/dist/lib/types/graph-shared.d.ts +25 -0
  199. package/dist/lib/types/graph-shared.js +7 -0
  200. package/dist/lib/types/knowledge-wire.d.ts +131 -0
  201. package/dist/lib/types/knowledge-wire.js +7 -0
  202. package/dist/lib/types/project-snapshot-builder.d.ts +19 -0
  203. package/dist/lib/types/project-snapshot-builder.js +189 -0
  204. package/dist/lib/types/project-snapshot.d.ts +399 -0
  205. package/dist/lib/types/project-snapshot.js +17 -0
  206. package/dist/lib/types/search-wire.d.ts +46 -0
  207. package/dist/lib/types/search-wire.js +7 -0
  208. package/dist/lib/types/snapshot-views.d.ts +58 -0
  209. package/dist/lib/types/snapshot-views.js +103 -0
  210. package/package.json +1 -1
  211. package/skills/autosnippet-recipes/SKILL.md +1 -1
  212. package/templates/instructions/agent-static.md +2 -0
  213. package/templates/instructions/conventions.md +3 -1
  214. package/templates/recipes-setup/README.md +2 -2
  215. package/dashboard/dist/assets/icons-BJ2mUBi8.js +0 -1
  216. package/dashboard/dist/assets/index-B659K9t5.js +0 -128
  217. package/dashboard/dist/assets/index-NCm40PMD.css +0 -1
  218. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.d.ts +0 -169
  219. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +0 -727
  220. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.d.ts +0 -370
  221. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +0 -821
@@ -82,6 +82,53 @@ export class ComplianceReporter {
82
82
  });
83
83
  }
84
84
  }
85
+ /**
86
+ * 确保 Enhancement Pack 规则已注入到 engine
87
+ * 与 MCP guard handler 的 _injectEnhancementGuardRules 逻辑一致
88
+ */
89
+ async #ensureEnhancementPackRules() {
90
+ if (!this.engine.isEpInjected || this.engine.isEpInjected()) {
91
+ return;
92
+ }
93
+ try {
94
+ const { initEnhancementRegistry } = await import('#core/enhancement/index.js');
95
+ const enhReg = await initEnhancementRegistry();
96
+ const allPacks = enhReg.all();
97
+ const allGuardRules = [];
98
+ for (const pack of allPacks) {
99
+ try {
100
+ const rules = pack.getGuardRules();
101
+ if (rules.length > 0) {
102
+ allGuardRules.push(...rules);
103
+ }
104
+ }
105
+ catch {
106
+ /* graceful degradation per pack */
107
+ }
108
+ }
109
+ if (allGuardRules.length > 0 && this.engine.injectExternalRules) {
110
+ this.engine.injectExternalRules(allGuardRules);
111
+ this.logger.info(`[ComplianceReporter] Injected ${allGuardRules.length} Enhancement Pack rules`);
112
+ }
113
+ this.engine.markEpInjected?.();
114
+ }
115
+ catch {
116
+ /* Enhancement registry not available — non-critical */
117
+ }
118
+ }
119
+ /**
120
+ * 确保 AST 语言插件已加载(Tree-sitter WASM)
121
+ * 未加载时 _runAstLayer2Checks 会静默跳过,导致 AST 类违规无法检测
122
+ */
123
+ async #ensureAstPlugins() {
124
+ try {
125
+ const { loadPlugins } = await import('../../core/ast/index.js');
126
+ await loadPlugins();
127
+ }
128
+ catch {
129
+ /* AST not available — graceful degradation */
130
+ }
131
+ }
85
132
  /**
86
133
  * 生成全项目合规报告
87
134
  * @param projectRoot 项目根目录
@@ -91,6 +138,10 @@ export class ComplianceReporter {
91
138
  async generate(projectRoot, options = {}) {
92
139
  const thresholds = { ...this.qualityGateConfig, ...(options.qualityGate || {}) };
93
140
  const maxFiles = options.maxFiles || 500;
141
+ // 0. 确保 Enhancement Pack 规则已注入(与 MCP guard handler 保持一致)
142
+ await this.#ensureEnhancementPackRules();
143
+ // 0b. 确保 AST 语言插件已加载(Tree-sitter WASM)
144
+ await this.#ensureAstPlugins();
94
145
  // 1. 收集源文件
95
146
  const files = await collectSourceFilesWithContent(projectRoot, { maxFiles });
96
147
  this.logger.info(`[ComplianceReporter] Collected ${files.length} source files`);
@@ -678,13 +678,14 @@ export class GuardCheckEngine {
678
678
  }
679
679
  // 如果有 scope,按层级过滤:project ⊇ target ⊇ file
680
680
  // project 范围包含所有维度的规则;target 包含 file+target;file 仅匹配 file
681
+ // 'universal' 维度在所有 scope 下都生效
681
682
  if (scope) {
682
683
  const SCOPE_HIERARCHY = {
683
- project: ['file', 'target', 'project'],
684
- target: ['file', 'target'],
685
- file: ['file'],
684
+ project: ['file', 'target', 'project', 'universal'],
685
+ target: ['file', 'target', 'universal'],
686
+ file: ['file', 'universal'],
686
687
  };
687
- const allowedDimensions = SCOPE_HIERARCHY[scope] || [scope];
688
+ const allowedDimensions = SCOPE_HIERARCHY[scope] || [scope, 'universal'];
688
689
  rules = rules.filter((r) => !r.dimension || allowedDimensions.includes(r.dimension));
689
690
  }
690
691
  const lines = (code || '').split(/\r?\n/);
@@ -42,6 +42,8 @@ export function runCrossFileChecks(files, options = {}) {
42
42
  const violations = [];
43
43
  const disabledSet = new Set(options.disabledRules || []);
44
44
  const isDisabled = (ruleId) => disabledSet.has(ruleId);
45
+ // 过滤掉 content 为空的条目,防止下游 split 崩溃
46
+ files = files.filter((f) => typeof f.content === 'string');
45
47
  // ── ObjC Category 跨文件重名检查 ──
46
48
  if (!isDisabled('objc-cross-file-duplicate-category')) {
47
49
  const categoryMap = new Map();
@@ -18,7 +18,7 @@ interface DatabaseLike {
18
18
  get(...params: unknown[]): Record<string, unknown> | undefined;
19
19
  };
20
20
  }
21
- export type DriftType = 'symbol_missing' | 'match_rate_drop' | 'api_deprecated' | 'zero_match';
21
+ export type DriftType = 'symbol_missing' | 'match_rate_drop' | 'api_deprecated' | 'zero_match' | 'source_ref_stale';
22
22
  export type DriftSeverity = 'high' | 'medium' | 'low';
23
23
  export interface PatternDriftSignal {
24
24
  type: DriftType;
@@ -59,9 +59,11 @@ export class ReverseGuard {
59
59
  if (recipe.guard_pattern) {
60
60
  signals.push(...this.#checkPatternMatchRate(recipe.id, recipe.guard_pattern, projectFiles));
61
61
  }
62
- // 3. 综合判定
62
+ // 3. 检查 sourceRef 路径是否失效(与 SourceRefReconciler 数据交叉验证)
63
+ signals.push(...this.#checkSourceRefStaleness(recipe.id));
64
+ // 4. 综合判定
63
65
  const recommendation = this.#computeRecommendation(signals);
64
- // 4. 发射信号
66
+ // 5. 发射信号
65
67
  if (this.#signalBus && signals.length > 0) {
66
68
  const severity = recommendation === 'decay' ? 1 : recommendation === 'investigate' ? 0.5 : 0;
67
69
  this.#signalBus.send('quality', 'ReverseGuard', severity, {
@@ -205,6 +207,34 @@ export class ReverseGuard {
205
207
  }
206
208
  return signals;
207
209
  }
210
+ /**
211
+ * 检查 recipe_source_refs 中是否有 stale 条目(与 SourceRefReconciler 数据交叉验证)
212
+ */
213
+ #checkSourceRefStaleness(recipeId) {
214
+ try {
215
+ const rows = this.#db
216
+ .prepare(`SELECT source_path FROM recipe_source_refs WHERE recipe_id = ? AND status = 'stale'`)
217
+ .all(recipeId);
218
+ if (rows.length === 0) {
219
+ return [];
220
+ }
221
+ return [
222
+ {
223
+ type: 'source_ref_stale',
224
+ detail: `${rows.length} source file(s) no longer exist: ${rows
225
+ .slice(0, 3)
226
+ .map((r) => r.source_path)
227
+ .join(', ')}${rows.length > 3 ? ` (+${rows.length - 3} more)` : ''}`,
228
+ severity: rows.length >= 3 ? 'high' : 'medium',
229
+ evidence: {},
230
+ },
231
+ ];
232
+ }
233
+ catch {
234
+ // recipe_source_refs 表可能不存在
235
+ return [];
236
+ }
237
+ }
208
238
  #extractSymbols(coreCode) {
209
239
  const symbols = new Set();
210
240
  for (const pattern of SYMBOL_PATTERNS) {
@@ -20,7 +20,7 @@ const DEFAULT_CONFIG = {
20
20
  /** 自动通过要求 reasoning.isValid() */
21
21
  requireReasoning: true,
22
22
  /** 来源白名单(这些来源可以适用更宽松的阈值) */
23
- trustedSources: ['bootstrap', 'cursor-scan'],
23
+ trustedSources: ['bootstrap', 'cursor-scan', 'mcp'],
24
24
  /** 可信来源的自动通过阈值 */
25
25
  trustedAutoApproveThreshold: 0.7,
26
26
  /** 极高置信度阈值 (≥0.90 → 24h Grace) */
@@ -105,8 +105,16 @@ export declare class KnowledgeService {
105
105
  _triggerCursorDeliveryAsync(): void;
106
106
  /** 弃用 (pending|active → deprecated) */
107
107
  deprecate(id: string, reason: string, context: ServiceContext): Promise<KnowledgeEntry>;
108
- /** 重新激活 (deprecated → pending) */
108
+ /** 重新激活 (deprecated|staging → pending) */
109
109
  reactivate(id: string, context: ServiceContext): Promise<KnowledgeEntry>;
110
+ /** 进入暂存期 (pending → staging) */
111
+ stage(id: string, context: ServiceContext): Promise<KnowledgeEntry>;
112
+ /** 进入进化态 (active → evolving) */
113
+ evolve(id: string, context: ServiceContext): Promise<KnowledgeEntry>;
114
+ /** 进入衰退观察 (active|evolving → decaying) */
115
+ decay(id: string, context: ServiceContext): Promise<KnowledgeEntry>;
116
+ /** 恢复为已发布 (decaying|evolving → active) */
117
+ restore(id: string, context: ServiceContext): Promise<KnowledgeEntry>;
110
118
  /** @deprecated 简化后所有条目直接进 pending */
111
119
  submit(id: string, _context: ServiceContext): Promise<KnowledgeEntry>;
112
120
  /** @deprecated 简化后 approve = publish */
@@ -171,6 +179,8 @@ export declare class KnowledgeService {
171
179
  _syncRelationsToGraph(id: string, relations: unknown): void;
172
180
  /** 删除所有关联边 */
173
181
  _removeAllEdges(id: string): void;
182
+ /** 删除关联的 evolution_proposals(target_recipe_id 无 CASCADE) */
183
+ _removeRelatedProposals(id: string): void;
174
184
  /** 落盘到 .md 文件 + 回写 sourceFile */
175
185
  _persistToFile(entry: KnowledgeEntry): void;
176
186
  /** 删除 .md 文件 */
@@ -49,6 +49,13 @@ export class KnowledgeService {
49
49
  async create(data, context) {
50
50
  try {
51
51
  this._validateCreateInput(data);
52
+ // ── 标题去重:防止跨维度/跨调用创建同名条目 ──
53
+ if (data.title) {
54
+ const existing = await this.repository.findByTitle(data.title);
55
+ if (existing) {
56
+ throw new ConflictError(`Knowledge entry with title "${data.title}" already exists (id: ${existing.id})`, { existingId: existing.id, title: data.title });
57
+ }
58
+ }
52
59
  const entry = KnowledgeEntry.fromJSON({
53
60
  ...data,
54
61
  lifecycle: Lifecycle.PENDING,
@@ -280,6 +287,8 @@ export class KnowledgeService {
280
287
  this._removeFile(entry);
281
288
  // 清除 knowledge_edges
282
289
  this._removeAllEdges(id);
290
+ // 清除 evolution_proposals(无 ON DELETE CASCADE,需手动删除)
291
+ this._removeRelatedProposals(id);
283
292
  await this.repository.delete(id);
284
293
  await this._audit('delete_knowledge', id, context.userId, {
285
294
  title: entry.title,
@@ -340,10 +349,26 @@ export class KnowledgeService {
340
349
  entityArgs: [reason],
341
350
  });
342
351
  }
343
- /** 重新激活 (deprecated → pending) */
352
+ /** 重新激活 (deprecated|staging → pending) */
344
353
  async reactivate(id, context) {
345
354
  return this._lifecycleTransition(id, 'reactivate', context);
346
355
  }
356
+ /** 进入暂存期 (pending → staging) */
357
+ async stage(id, context) {
358
+ return this._lifecycleTransition(id, 'stage', context);
359
+ }
360
+ /** 进入进化态 (active → evolving) */
361
+ async evolve(id, context) {
362
+ return this._lifecycleTransition(id, 'evolve', context);
363
+ }
364
+ /** 进入衰退观察 (active|evolving → decaying) */
365
+ async decay(id, context) {
366
+ return this._lifecycleTransition(id, 'decay', context);
367
+ }
368
+ /** 恢复为已发布 (decaying|evolving → active) */
369
+ async restore(id, context) {
370
+ return this._lifecycleTransition(id, 'restore', context);
371
+ }
347
372
  // ── 向后兼容别名 ──
348
373
  /** @deprecated 简化后所有条目直接进 pending */
349
374
  async submit(id, _context) {
@@ -555,9 +580,8 @@ export class KnowledgeService {
555
580
  if (entry.reviewedAt) {
556
581
  dbUpdates.reviewedAt = entry.reviewedAt;
557
582
  }
558
- if (entry.rejectionReason !== null) {
559
- dbUpdates.rejectionReason = entry.rejectionReason;
560
- }
583
+ // 驳回原因(含清除:reactivate 后 rejectionReason = null 需写入 DB)
584
+ dbUpdates.rejectionReason = entry.rejectionReason;
561
585
  // 发布字段
562
586
  if (entry.publishedAt) {
563
587
  dbUpdates.publishedAt = entry.publishedAt;
@@ -781,6 +805,22 @@ export class KnowledgeService {
781
805
  });
782
806
  }
783
807
  }
808
+ /** 删除关联的 evolution_proposals(target_recipe_id 无 CASCADE) */
809
+ _removeRelatedProposals(id) {
810
+ const gs = this._knowledgeGraphService;
811
+ if (!gs) {
812
+ return;
813
+ }
814
+ try {
815
+ gs.db.prepare(`DELETE FROM evolution_proposals WHERE target_recipe_id = ?`).run(id);
816
+ }
817
+ catch (err) {
818
+ this.logger.warn('Failed to remove related proposals', {
819
+ id,
820
+ error: err instanceof Error ? err.message : String(err),
821
+ });
822
+ }
823
+ }
784
824
  /* ═══ 文件落盘 ═════════════════════════════════ */
785
825
  /** 落盘到 .md 文件 + 回写 sourceFile */
786
826
  _persistToFile(entry) {
@@ -0,0 +1,225 @@
1
+ /**
2
+ * RecipeProductionGateway — 统一 Recipe 生产入口
3
+ *
4
+ * 所有 Recipe 创建(Agent Tool / MCP / IDE Agent / Batch Import)
5
+ * 通过此 Gateway 的统一管道,保证前置校验一致:
6
+ *
7
+ * 1. Schema Validation (UnifiedValidator)
8
+ * 2. Similarity Check — 去重检测(可选跳过)
9
+ * 3. Consolidation Scan — 融合/重组建议(可选)
10
+ * 4. KnowledgeService.create() — 包含 ConfidenceRouter → staging / pending
11
+ * 5. Quality Scoring — 质量评分
12
+ * 6. Supersede Proposal — 创建替代提案
13
+ * 7. Audit — 统一审计
14
+ *
15
+ * @see docs/copilot/recipe-lifecycle-management.md §6
16
+ */
17
+ /** Lightweight log interface — avoids importing static-only Logger class. */
18
+ interface GatewayLogger {
19
+ info(msg: string): void;
20
+ warn(msg: string): void;
21
+ }
22
+ export type GatewaySource = 'agent-tool' | 'mcp-external' | 'ide-agent' | 'batch-import';
23
+ export interface CreateRecipeItem {
24
+ title?: string;
25
+ description?: string;
26
+ content?: {
27
+ markdown?: string;
28
+ pattern?: string;
29
+ rationale?: string;
30
+ [key: string]: unknown;
31
+ };
32
+ trigger?: string;
33
+ kind?: string;
34
+ topicHint?: string;
35
+ whenClause?: string;
36
+ doClause?: string;
37
+ dontClause?: string;
38
+ coreCode?: string;
39
+ sourceRefs?: string[];
40
+ tags?: string[];
41
+ reasoning?: {
42
+ whyStandard?: string;
43
+ sources?: string[];
44
+ confidence?: number;
45
+ };
46
+ headers?: string[];
47
+ usageGuide?: string;
48
+ scope?: string;
49
+ complexity?: string;
50
+ sourceFile?: string;
51
+ knowledgeType?: string;
52
+ language?: string;
53
+ category?: string;
54
+ source?: string;
55
+ [key: string]: unknown;
56
+ }
57
+ export interface CreateRecipeRequest {
58
+ source: GatewaySource;
59
+ items: CreateRecipeItem[];
60
+ options?: {
61
+ /** 跳过相似度检测(仅 batch-import 可用) */
62
+ skipSimilarityCheck?: boolean;
63
+ /** 跳过 ConsolidationAdvisor 分析 */
64
+ skipConsolidation?: boolean;
65
+ /** 被替代的旧 Recipe ID */
66
+ supersedes?: string;
67
+ /** 相似度阈值,默认 0.7 */
68
+ similarityThreshold?: number;
69
+ /** 已提交标题集(批量去重用) */
70
+ existingTitles?: Set<string>;
71
+ /** 已提交指纹集(批量去重用) */
72
+ existingFingerprints?: Set<string>;
73
+ /** UnifiedValidator 跳过系统注入字段列表 */
74
+ systemInjectedFields?: string[];
75
+ /** 跳过唯一性校验 */
76
+ skipUniqueness?: boolean;
77
+ /** 操作用户 ID */
78
+ userId?: string;
79
+ };
80
+ }
81
+ export interface CreatedRecipeInfo {
82
+ id: string;
83
+ title: string;
84
+ lifecycle: string;
85
+ /** Raw saved entry from KnowledgeService.create() */
86
+ raw: Record<string, unknown>;
87
+ }
88
+ export interface RejectedRecipeInfo {
89
+ index: number;
90
+ title: string;
91
+ reason: string;
92
+ errors: string[];
93
+ warnings: string[];
94
+ }
95
+ export interface MergedRecipeInfo {
96
+ index: number;
97
+ proposalId: string;
98
+ type: string;
99
+ targetRecipeId: string;
100
+ targetTitle: string;
101
+ status: string;
102
+ expiresAt: number;
103
+ message: string;
104
+ }
105
+ export interface BlockedRecipeInfo {
106
+ index: number;
107
+ title: string;
108
+ consolidation: unknown;
109
+ }
110
+ export interface SimilarRecipeInfo {
111
+ index: number;
112
+ title: string;
113
+ similarTo: {
114
+ file: string;
115
+ title: string;
116
+ similarity: number;
117
+ }[];
118
+ }
119
+ export interface CreateRecipeResult {
120
+ created: CreatedRecipeInfo[];
121
+ rejected: RejectedRecipeInfo[];
122
+ merged: MergedRecipeInfo[];
123
+ blocked: BlockedRecipeInfo[];
124
+ duplicates: SimilarRecipeInfo[];
125
+ supersedeProposal: {
126
+ proposalId: string;
127
+ } | null;
128
+ }
129
+ interface GatewayKnowledgeService {
130
+ create(data: Record<string, unknown>, context: {
131
+ userId: string;
132
+ }): Promise<{
133
+ id: string;
134
+ title: string;
135
+ lifecycle: string;
136
+ kind?: string;
137
+ [key: string]: unknown;
138
+ }>;
139
+ updateQuality(id: string, context: {
140
+ userId: string;
141
+ }): Promise<unknown>;
142
+ }
143
+ interface GatewayConsolidationAdvisor {
144
+ analyzeBatch(candidates: Array<{
145
+ title: string;
146
+ category?: string;
147
+ [key: string]: unknown;
148
+ }>): {
149
+ items: Array<{
150
+ index: number;
151
+ advice: {
152
+ action: string;
153
+ confidence: number;
154
+ reason: string;
155
+ targetRecipe?: {
156
+ id: string;
157
+ title: string;
158
+ similarity: number;
159
+ };
160
+ reorganizeTargets?: {
161
+ id: string;
162
+ title: string;
163
+ similarity: number;
164
+ }[];
165
+ coveredBy?: {
166
+ id: string;
167
+ title: string;
168
+ similarity: number;
169
+ }[];
170
+ mergeDirection?: {
171
+ addedDimensions: string[];
172
+ summary: string;
173
+ };
174
+ };
175
+ }>;
176
+ };
177
+ }
178
+ interface GatewayProposalRepository {
179
+ create(data: Record<string, unknown>): {
180
+ id: string;
181
+ status: string;
182
+ expiresAt: number;
183
+ [key: string]: unknown;
184
+ } | null;
185
+ }
186
+ type GatewaySimilarityFn = (projectRoot: string, candidate: {
187
+ title: string;
188
+ summary: string;
189
+ code: string;
190
+ }, opts: {
191
+ threshold: number;
192
+ topK: number;
193
+ }) => {
194
+ file: string;
195
+ title: string;
196
+ similarity: number;
197
+ }[];
198
+ export interface GatewayDeps {
199
+ knowledgeService: GatewayKnowledgeService;
200
+ projectRoot: string;
201
+ logger?: GatewayLogger;
202
+ /** ConsolidationAdvisor(可选 — MCP 路径使用) */
203
+ consolidationAdvisor?: GatewayConsolidationAdvisor | null;
204
+ /** ProposalRepository(可选 — supersede 提案需要) */
205
+ proposalRepository?: GatewayProposalRepository | null;
206
+ /** 相似度检测函数(可选 — 默认导入 SimilarityService) */
207
+ findSimilarRecipes?: GatewaySimilarityFn | null;
208
+ }
209
+ export declare class RecipeProductionGateway {
210
+ #private;
211
+ constructor(deps: GatewayDeps);
212
+ /**
213
+ * 统一创建入口
214
+ *
215
+ * Pipeline:
216
+ * 1. Schema Validation (UnifiedValidator)
217
+ * 2. Similarity Check (除非 skipSimilarityCheck)
218
+ * 3. Consolidation Scan (除非 skipConsolidation)
219
+ * 4. KnowledgeService.create() — ConfidenceRouter → staging / pending
220
+ * 5. Quality Scoring
221
+ * 6. Supersede Proposal 创建 (if supersedes)
222
+ */
223
+ create(request: CreateRecipeRequest): Promise<CreateRecipeResult>;
224
+ }
225
+ export {};