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
@@ -0,0 +1,324 @@
1
+ /**
2
+ * CleanupService — 统一数据清理策略
3
+ *
4
+ * 提供两种清理模式:
5
+ * - fullReset(): 全量清理(删除一切知识/缓存/衍生数据),用于 bootstrap 冷启动
6
+ * - rescanClean(): Rescan 清理(保留 Recipe,清除衍生缓存),用于增量知识更新
7
+ * - snapshotRecipes(): 快照当前活跃 Recipe 信息
8
+ *
9
+ * 设计原则:
10
+ * - 配置数据 (config.json, constitution.yaml, boxspec.json) 永不清理
11
+ * - IDE 集成配置 (.vscode/, .cursor/, .github/) 永不清理
12
+ * - 交付物 (.cursor/rules/autosnippet-*) 由 R4 重建,不在此清理
13
+ *
14
+ * @module service/cleanup/CleanupService
15
+ */
16
+ import fs from 'node:fs';
17
+ import path from 'node:path';
18
+ import { CANDIDATES_DIR } from '#infra/config/Defaults.js';
19
+ import { getContextIndexPath, getProjectKnowledgePath, getProjectRecipesPath, getProjectSkillsPath, } from '#infra/config/Paths.js';
20
+ // ── 常量 ────────────────────────────────────────────────────
21
+ /** fullReset 时清除的所有 DB 表(不含 schema_migrations) */
22
+ const ALL_DATA_TABLES = [
23
+ 'knowledge_entries',
24
+ 'knowledge_edges',
25
+ 'guard_violations',
26
+ 'audit_logs',
27
+ 'sessions',
28
+ 'token_usage',
29
+ 'semantic_memories',
30
+ 'bootstrap_snapshots',
31
+ 'bootstrap_dim_files',
32
+ 'code_entities',
33
+ 'remote_commands',
34
+ 'remote_state',
35
+ 'evolution_proposals',
36
+ 'recipe_source_refs',
37
+ ];
38
+ /** rescanClean 时清除的 DB 表(保留知识/进化相关表) */
39
+ const RESCAN_CLEAN_TABLES = [
40
+ 'code_entities',
41
+ 'guard_violations',
42
+ 'bootstrap_snapshots',
43
+ 'bootstrap_dim_files',
44
+ 'semantic_memories',
45
+ 'sessions',
46
+ 'audit_logs',
47
+ 'token_usage',
48
+ 'remote_commands',
49
+ 'remote_state',
50
+ 'recipe_source_refs',
51
+ ];
52
+ // ── CleanupService ──────────────────────────────────────────
53
+ export class CleanupService {
54
+ #projectRoot;
55
+ #logger;
56
+ #db;
57
+ constructor(opts) {
58
+ this.#projectRoot = opts.projectRoot;
59
+ this.#logger = opts.logger || { info() { }, warn() { } };
60
+ this.#db = opts.db
61
+ ? typeof opts.db?.getDb === 'function'
62
+ ? opts.db.getDb()
63
+ : opts.db
64
+ : null;
65
+ }
66
+ /** 更新 DB 引用(fullReset 后重连时调用) */
67
+ setDb(db) {
68
+ this.#db = db
69
+ ? typeof db?.getDb === 'function'
70
+ ? db.getDb()
71
+ : db
72
+ : null;
73
+ }
74
+ // ─── 需求 A:全量清理(删除一切) ─────────────────────
75
+ /**
76
+ * 全量清理 — 用于 bootstrap 冷启动
77
+ *
78
+ * 清除: DB 所有数据表、candidates/、recipes/、skills/、wiki/、
79
+ * 向量索引、bootstrap-report.json、logs/signals/
80
+ * 保留: config.json、constitution.yaml、boxspec.json、IDE 配置
81
+ */
82
+ async fullReset() {
83
+ const result = {
84
+ deletedFiles: 0,
85
+ clearedTables: [],
86
+ preservedRecipes: 0,
87
+ errors: [],
88
+ };
89
+ this.#logger.info('[CleanupService] Starting fullReset...');
90
+ // 1. 清除 DB 所有数据表
91
+ if (this.#db) {
92
+ for (const table of ALL_DATA_TABLES) {
93
+ try {
94
+ this.#db.exec(`DELETE FROM ${table}`);
95
+ result.clearedTables.push(table);
96
+ }
97
+ catch (err) {
98
+ const msg = err instanceof Error ? err.message : String(err);
99
+ // 表可能不存在(未 migrate),跳过
100
+ if (!msg.includes('no such table')) {
101
+ result.errors.push(`Failed to clear ${table}: ${msg}`);
102
+ }
103
+ }
104
+ }
105
+ // 也清除 tasks 相关表(来自 migration 002)
106
+ for (const table of ['tasks', 'task_dependencies', 'task_events']) {
107
+ try {
108
+ this.#db.exec(`DELETE FROM ${table}`);
109
+ result.clearedTables.push(table);
110
+ }
111
+ catch {
112
+ /* table may not exist */
113
+ }
114
+ }
115
+ }
116
+ // 2. 清空 candidates/ 目录
117
+ result.deletedFiles += this.#clearDirectory(path.join(this.#projectRoot, CANDIDATES_DIR));
118
+ // 3. 清空 recipes/ 目录
119
+ result.deletedFiles += this.#clearDirectory(getProjectRecipesPath(this.#projectRoot));
120
+ // 4. 清空 skills/ 目录
121
+ result.deletedFiles += this.#clearDirectory(getProjectSkillsPath(this.#projectRoot));
122
+ // 5. 清空 wiki/ 目录
123
+ result.deletedFiles += this.#clearDirectory(path.join(getProjectKnowledgePath(this.#projectRoot), 'wiki'));
124
+ // 6. 删除向量索引
125
+ result.deletedFiles += this.#clearDirectory(getContextIndexPath(this.#projectRoot));
126
+ // 7. 删除 bootstrap-report.json
127
+ result.deletedFiles += this.#deleteFile(path.join(getProjectKnowledgePath(this.#projectRoot), '.autosnippet', 'bootstrap-report.json'));
128
+ // 8. 清除 logs/signals/
129
+ result.deletedFiles += this.#clearDirectory(path.join(getProjectKnowledgePath(this.#projectRoot), '.autosnippet', 'logs', 'signals'));
130
+ this.#logger.info('[CleanupService] fullReset complete', {
131
+ tables: result.clearedTables.length,
132
+ files: result.deletedFiles,
133
+ errors: result.errors.length,
134
+ });
135
+ return result;
136
+ }
137
+ // ─── 需求 B:Rescan 清理(保留 Recipe) ───────────────
138
+ /**
139
+ * Rescan 清理 — 保留 Recipe,清除衍生缓存
140
+ *
141
+ * 清除: 衍生 DB 表、pending/rejected/deprecated 知识条目、
142
+ * candidates/、skills/、wiki/、向量索引、bootstrap-report
143
+ * 保留: recipes/、active/published/staging/evolving 知识条目、
144
+ * knowledge_edges、evolution_proposals
145
+ */
146
+ async rescanClean() {
147
+ const result = {
148
+ deletedFiles: 0,
149
+ clearedTables: [],
150
+ preservedRecipes: 0,
151
+ errors: [],
152
+ };
153
+ this.#logger.info('[CleanupService] Starting rescanClean...');
154
+ // 1. 清除衍生 DB 表
155
+ if (this.#db) {
156
+ for (const table of RESCAN_CLEAN_TABLES) {
157
+ try {
158
+ this.#db.exec(`DELETE FROM ${table}`);
159
+ result.clearedTables.push(table);
160
+ }
161
+ catch (err) {
162
+ const msg = err instanceof Error ? err.message : String(err);
163
+ if (!msg.includes('no such table')) {
164
+ result.errors.push(`Failed to clear ${table}: ${msg}`);
165
+ }
166
+ }
167
+ }
168
+ // 清除旧候选/废弃条目,保留活跃知识
169
+ try {
170
+ this.#db.exec(`DELETE FROM knowledge_entries WHERE lifecycle IN ('pending', 'rejected', 'deprecated')`);
171
+ result.clearedTables.push('knowledge_entries (pending/rejected/deprecated)');
172
+ }
173
+ catch (err) {
174
+ const msg = err instanceof Error ? err.message : String(err);
175
+ result.errors.push(`Failed to clean old entries: ${msg}`);
176
+ }
177
+ // 也清除 tasks 相关表
178
+ for (const table of ['tasks', 'task_dependencies', 'task_events']) {
179
+ try {
180
+ this.#db.exec(`DELETE FROM ${table}`);
181
+ result.clearedTables.push(table);
182
+ }
183
+ catch {
184
+ /* table may not exist */
185
+ }
186
+ }
187
+ }
188
+ // 2. 清空 candidates/ 目录
189
+ result.deletedFiles += this.#clearDirectory(path.join(this.#projectRoot, CANDIDATES_DIR));
190
+ // 3. 清空 skills/ 目录
191
+ result.deletedFiles += this.#clearDirectory(getProjectSkillsPath(this.#projectRoot));
192
+ // 4. 清空 wiki/ 目录
193
+ result.deletedFiles += this.#clearDirectory(path.join(getProjectKnowledgePath(this.#projectRoot), 'wiki'));
194
+ // 5. 删除向量索引
195
+ result.deletedFiles += this.#clearDirectory(getContextIndexPath(this.#projectRoot));
196
+ // 6. 删除 bootstrap-report.json
197
+ result.deletedFiles += this.#deleteFile(path.join(getProjectKnowledgePath(this.#projectRoot), '.autosnippet', 'bootstrap-report.json'));
198
+ this.#logger.info('[CleanupService] rescanClean complete', {
199
+ tables: result.clearedTables.length,
200
+ files: result.deletedFiles,
201
+ errors: result.errors.length,
202
+ });
203
+ return result;
204
+ }
205
+ // ─── 快照当前 Recipe ──────────────────────────────────
206
+ /**
207
+ * 快照当前活跃 Recipe 信息
208
+ * 用于 rescan 前记录保留的知识条目
209
+ */
210
+ async snapshotRecipes() {
211
+ if (!this.#db) {
212
+ return { count: 0, entries: [], coverageByDimension: {} };
213
+ }
214
+ try {
215
+ const rows = this.#db
216
+ .prepare(`SELECT id, title, trigger, category, knowledgeType, doClause,
217
+ sourceFile, lifecycle, content, json_extract(reasoning, '$.sources') AS sourceRefsJson
218
+ FROM knowledge_entries
219
+ WHERE lifecycle IN ('active', 'staging', 'evolving')`)
220
+ .all();
221
+ const entries = rows.map((r) => {
222
+ let parsedContent;
223
+ try {
224
+ parsedContent = r.content
225
+ ? JSON.parse(r.content)
226
+ : undefined;
227
+ }
228
+ catch {
229
+ parsedContent = undefined;
230
+ }
231
+ let parsedSourceRefs;
232
+ try {
233
+ parsedSourceRefs = r.sourceRefsJson
234
+ ? JSON.parse(r.sourceRefsJson)
235
+ : undefined;
236
+ }
237
+ catch {
238
+ parsedSourceRefs = undefined;
239
+ }
240
+ return {
241
+ id: r.id,
242
+ title: r.title || '',
243
+ trigger: r.trigger || '',
244
+ category: r.category || '',
245
+ knowledgeType: r.knowledgeType || 'code-pattern',
246
+ doClause: r.doClause || '',
247
+ sourceFile: r.sourceFile || undefined,
248
+ lifecycle: r.lifecycle,
249
+ content: parsedContent,
250
+ sourceRefs: parsedSourceRefs,
251
+ };
252
+ });
253
+ // 按维度统计覆盖度 (使用 knowledgeType = 维度 id)
254
+ const coverageByDimension = {};
255
+ for (const entry of entries) {
256
+ const dim = entry.knowledgeType || 'unknown';
257
+ coverageByDimension[dim] = (coverageByDimension[dim] || 0) + 1;
258
+ }
259
+ return {
260
+ count: entries.length,
261
+ entries,
262
+ coverageByDimension,
263
+ };
264
+ }
265
+ catch (err) {
266
+ const msg = err instanceof Error ? err.message : String(err);
267
+ this.#logger.warn(`[CleanupService] snapshotRecipes failed: ${msg}`);
268
+ return { count: 0, entries: [], coverageByDimension: {} };
269
+ }
270
+ }
271
+ // ─── 内部工具方法 ─────────────────────────────────────
272
+ /**
273
+ * 清空目录内容(保留目录本身)
274
+ * @returns 删除的文件数
275
+ */
276
+ #clearDirectory(dirPath) {
277
+ let count = 0;
278
+ try {
279
+ if (!fs.existsSync(dirPath)) {
280
+ return 0;
281
+ }
282
+ const entries = fs.readdirSync(dirPath);
283
+ for (const entry of entries) {
284
+ const fullPath = path.join(dirPath, entry);
285
+ try {
286
+ const stat = fs.statSync(fullPath);
287
+ if (stat.isDirectory()) {
288
+ fs.rmSync(fullPath, { recursive: true });
289
+ }
290
+ else {
291
+ fs.unlinkSync(fullPath);
292
+ }
293
+ count++;
294
+ }
295
+ catch (err) {
296
+ const msg = err instanceof Error ? err.message : String(err);
297
+ this.#logger.warn(`[CleanupService] Failed to delete ${entry}: ${msg}`);
298
+ }
299
+ }
300
+ }
301
+ catch (err) {
302
+ const msg = err instanceof Error ? err.message : String(err);
303
+ this.#logger.warn(`[CleanupService] clearDirectory failed for ${dirPath}: ${msg}`);
304
+ }
305
+ return count;
306
+ }
307
+ /**
308
+ * 删除单个文件
309
+ * @returns 1 if deleted, 0 otherwise
310
+ */
311
+ #deleteFile(filePath) {
312
+ try {
313
+ if (fs.existsSync(filePath)) {
314
+ fs.unlinkSync(filePath);
315
+ return 1;
316
+ }
317
+ }
318
+ catch (err) {
319
+ const msg = err instanceof Error ? err.message : String(err);
320
+ this.#logger.warn(`[CleanupService] Failed to delete file ${filePath}: ${msg}`);
321
+ }
322
+ return 0;
323
+ }
324
+ }
@@ -15,7 +15,7 @@
15
15
  import fs from 'node:fs';
16
16
  import path from 'node:path';
17
17
  import { TEMPLATES_DIR } from '../../shared/package-root.js';
18
- import { checkWriteSafety, safeWriteFile } from './FileProtection.js';
18
+ import { mergeSection } from './FileProtection.js';
19
19
  import { estimateTokens } from './TokenBudget.js';
20
20
  /**
21
21
  * Agent 指令文件 token 预算
@@ -49,6 +49,14 @@ const MCP_TOOLS_SUMMARY = [
49
49
  { name: 'autosnippet_graph', desc: 'Knowledge graph query (query/impact/path/stats)' },
50
50
  { name: 'autosnippet_skill', desc: 'Skill management (list/load/create/update/delete)' },
51
51
  { name: 'autosnippet_bootstrap', desc: 'Project cold-start & scan' },
52
+ {
53
+ name: 'autosnippet_rescan',
54
+ desc: 'Incremental rescan: preserves Recipes, cleans caches, re-analyzes project, runs relevance audit',
55
+ },
56
+ {
57
+ name: 'autosnippet_evolve',
58
+ desc: 'Batch Recipe evolution decisions (propose_evolution/confirm_deprecation/skip), used per-dimension during rescan or standalone',
59
+ },
52
60
  {
53
61
  name: 'autosnippet_panorama',
54
62
  desc: 'Project panorama (operation: overview/module/gaps/health)',
@@ -95,8 +103,8 @@ export class AgentInstructionsGenerator {
95
103
  const filesWritten = allResults.filter((r) => !r.skipped).length;
96
104
  const skippedFiles = allResults.filter((r) => r.skipped);
97
105
  if (skippedFiles.length > 0) {
98
- this.logger.info?.(`[AgentInstructions] Skipped ${skippedFiles.length} file(s) ` +
99
- `user-owned files will not be overwritten: ${skippedFiles.map((f) => f.filePath).join(', ')}`);
106
+ this.logger.info?.(`[AgentInstructions] Skipped ${skippedFiles.length} file(s): ` +
107
+ skippedFiles.map((f) => f.filePath).join(', '));
100
108
  }
101
109
  this.logger.info?.(`[AgentInstructions] Generated ${filesWritten} files in ${duration}ms — ` +
102
110
  `AGENTS.md: ${agents.tokensUsed}t, CLAUDE.md: ${claude.tokensUsed}t, ` +
@@ -159,7 +167,8 @@ export class AgentInstructionsGenerator {
159
167
  }
160
168
  // ─── AGENTS.md ─────────────────────────────────────
161
169
  _writeAgentsMd(sections) {
162
- const lines = [
170
+ // 文件头部(仅用于新建/旧版重写场景)
171
+ const header = [
163
172
  `# ${this.projectName} — Agent Instructions`,
164
173
  '',
165
174
  '> Auto-generated by [AutoSnippet](https://github.com/GxFn/AutoSnippet). Do not edit manually.',
@@ -167,31 +176,28 @@ export class AgentInstructionsGenerator {
167
176
  'This project uses **AutoSnippet** for knowledge management.',
168
177
  'Access the knowledge base through MCP tools.',
169
178
  '',
170
- ];
171
- // Coding Standards
179
+ ].join('\n');
180
+ // 动态区段内容(始终在 markers 内管理)
181
+ const sectionLines = [];
172
182
  if (sections.ruleLines.length > 0) {
173
- lines.push('## Coding Standards', '', ...sections.ruleLines, '');
183
+ sectionLines.push('## Coding Standards', '', ...sections.ruleLines, '');
174
184
  }
175
- // Architecture Patterns
176
185
  if (sections.patternRows.length > 0) {
177
- lines.push('## Architecture Patterns', '', '| Trigger | When | Do |', '|---------|------|----|', ...sections.patternRows, '');
186
+ sectionLines.push('## Architecture Patterns', '', '| Trigger | When | Do |', '|---------|------|----|', ...sections.patternRows, '');
178
187
  }
179
- // MCP Tools
180
- lines.push('## MCP Tools', '', ...sections.toolLines, '');
181
- // Skills
188
+ sectionLines.push('## MCP Tools', '', ...sections.toolLines, '');
182
189
  if (sections.skillLines.length > 0) {
183
- lines.push('## Skills', '', 'Load with `autosnippet_skill({ operation: "load", name: "<skill>" })`:', '', ...sections.skillLines, '');
190
+ sectionLines.push('## Skills', '', 'Load with `autosnippet_skill({ operation: "load", name: "<skill>" })`:', '', ...sections.skillLines, '');
184
191
  }
185
- // Constraints
186
- lines.push('## Constraints', '', '1. Do NOT modify knowledge base files directly (`AutoSnippet/recipes/`, `.autosnippet/`).', '2. Prefer Recipes as project standards; source code is supplementary.', '3. Create or update knowledge only through MCP tools.', '');
187
- const content = `${lines.join('\n')}\n`;
192
+ sectionLines.push('## Constraints', '', '1. Do NOT modify knowledge base files directly (`AutoSnippet/recipes/`, `.autosnippet/`).', '2. Prefer Recipes as project standards; source code is supplementary.', '3. Create or update knowledge only through MCP tools.', '');
193
+ const sectionContent = sectionLines.join('\n');
188
194
  const filePath = path.join(this.projectRoot, 'AGENTS.md');
189
- const result = safeWriteFile(filePath, content, { logger: this.logger });
190
- return { filePath, tokensUsed: estimateTokens(content), skipped: !result.written };
195
+ const result = mergeSection(filePath, sectionContent, { header, logger: this.logger });
196
+ return { filePath, tokensUsed: estimateTokens(sectionContent), skipped: !result.written };
191
197
  }
192
198
  // ─── CLAUDE.md ─────────────────────────────────────
193
199
  _writeClaudeMd(sections) {
194
- const lines = [
200
+ const header = [
195
201
  `# ${this.projectName} — Claude Code Instructions`,
196
202
  '',
197
203
  '> Auto-generated by AutoSnippet. Regenerated when knowledge base changes.',
@@ -199,27 +205,23 @@ export class AgentInstructionsGenerator {
199
205
  'This project uses **AutoSnippet** for knowledge management.',
200
206
  'Access the knowledge base through MCP tools.',
201
207
  '',
202
- ];
203
- // Coding Standards
208
+ ].join('\n');
209
+ const sectionLines = [];
204
210
  if (sections.ruleLines.length > 0) {
205
- lines.push('## Coding Standards', '', ...sections.ruleLines, '');
211
+ sectionLines.push('## Coding Standards', '', ...sections.ruleLines, '');
206
212
  }
207
- // Patterns
208
213
  if (sections.patternRows.length > 0) {
209
- lines.push('## Key Patterns', '', '| Trigger | When | Do |', '|---------|------|----|', ...sections.patternRows, '');
214
+ sectionLines.push('## Key Patterns', '', '| Trigger | When | Do |', '|---------|------|----|', ...sections.patternRows, '');
210
215
  }
211
- // MCP Claude Code natively supports MCP
212
- lines.push('## MCP Tools', '', ...sections.toolLines, '');
213
- // Skills
216
+ sectionLines.push('## MCP Tools', '', ...sections.toolLines, '');
214
217
  if (sections.skillLines.length > 0) {
215
- lines.push('## Skills', '', ...sections.skillLines, '');
218
+ sectionLines.push('## Skills', '', ...sections.skillLines, '');
216
219
  }
217
- // Constraints
218
- lines.push('', '## Constraints', '', '1. Do NOT modify knowledge base files directly (`AutoSnippet/recipes/`, `.autosnippet/`).', '2. Prefer Recipes as project standards; source code is supplementary.', '3. Create or update knowledge only through MCP tools.', '');
219
- const content = `${lines.join('\n')}\n`;
220
+ sectionLines.push('', '## Constraints', '', '1. Do NOT modify knowledge base files directly (`AutoSnippet/recipes/`, `.autosnippet/`).', '2. Prefer Recipes as project standards; source code is supplementary.', '3. Create or update knowledge only through MCP tools.', '');
221
+ const sectionContent = sectionLines.join('\n');
220
222
  const filePath = path.join(this.projectRoot, 'CLAUDE.md');
221
- const result = safeWriteFile(filePath, content, { logger: this.logger });
222
- return { filePath, tokensUsed: estimateTokens(content), skipped: !result.written };
223
+ const result = mergeSection(filePath, sectionContent, { header, logger: this.logger });
224
+ return { filePath, tokensUsed: estimateTokens(sectionContent), skipped: !result.written };
223
225
  }
224
226
  // ─── copilot-instructions.md ───────────────────────
225
227
  /**
@@ -228,7 +230,7 @@ export class AgentInstructionsGenerator {
228
230
  */
229
231
  _writeCopilotInstructions(_sections) {
230
232
  const body = this._loadConventionsTemplate();
231
- const content = [
233
+ const section = [
232
234
  '<!-- autosnippet:begin -->',
233
235
  '',
234
236
  '# AutoSnippet Conventions',
@@ -236,16 +238,10 @@ export class AgentInstructionsGenerator {
236
238
  body,
237
239
  '',
238
240
  '<!-- autosnippet:end -->',
239
- '',
240
241
  ].join('\n');
241
- const destDir = path.join(this.projectRoot, '.github');
242
- const filePath = path.join(destDir, 'copilot-instructions.md');
243
- const { canWrite } = checkWriteSafety(filePath);
244
- if (canWrite) {
245
- fs.mkdirSync(destDir, { recursive: true });
246
- }
247
- const result = safeWriteFile(filePath, content, { logger: this.logger });
248
- return { filePath, tokensUsed: estimateTokens(content), skipped: !result.written };
242
+ const filePath = path.join(this.projectRoot, '.github', 'copilot-instructions.md');
243
+ const result = mergeSection(filePath, section, { logger: this.logger });
244
+ return { filePath, tokensUsed: estimateTokens(section), skipped: !result.written };
249
245
  }
250
246
  // ─── 模板读取 ──────────────────────────────────────
251
247
  /**
@@ -61,3 +61,23 @@ export declare function safeCopyFile(srcPath: string, destPath: string, options?
61
61
  reason: string;
62
62
  filePath: string;
63
63
  };
64
+ export type MergeStrategy = 'create' | 'replace-section' | 'rewrite-legacy' | 'append-section';
65
+ /**
66
+ * 智能合并 AutoSnippet 管理区段到目标文件
67
+ *
68
+ * 四种场景:
69
+ * 1. 文件不存在 → 创建完整文件(header + markers)
70
+ * 2. 文件有 begin/end 标记 → 仅替换标记区段(增量更新)
71
+ * 3. 文件有旧版 AutoSnippet 签名但无标记 → 全量重写并加标记(旧版迁移)
72
+ * 4. 文件无签名无标记(用户文件)→ 追加标记区段到末尾(共存)
73
+ */
74
+ export declare function mergeSection(filePath: string, section: string, options?: {
75
+ header?: string;
76
+ logger?: {
77
+ info?: (...args: unknown[]) => void;
78
+ };
79
+ }): {
80
+ written: boolean;
81
+ strategy: MergeStrategy;
82
+ filePath: string;
83
+ };
@@ -12,6 +12,7 @@
12
12
  * - "auto-generated by autosnippet" (case-insensitive)
13
13
  */
14
14
  import fs from 'node:fs';
15
+ import path from 'node:path';
15
16
  /**
16
17
  * AutoSnippet 文件签名模式(case-insensitive)
17
18
  * 检查文件前 1024 字节即可——签名总在文件头部
@@ -96,3 +97,56 @@ export function safeCopyFile(srcPath, destPath, options = {}) {
96
97
  logger?.info?.(`[FileProtection] Skipped "${destPath}" — ${reason} (file exists and is not AutoSnippet-generated)`);
97
98
  return { written: false, reason, filePath: destPath };
98
99
  }
100
+ // ─── Section Merge ──────────────────────────────────
101
+ const SECTION_BEGIN = '<!-- autosnippet:begin -->';
102
+ const SECTION_END = '<!-- autosnippet:end -->';
103
+ const SECTION_PATTERN = /<!-- autosnippet:begin -->[\s\S]*?<!-- autosnippet:end -->/;
104
+ /**
105
+ * 智能合并 AutoSnippet 管理区段到目标文件
106
+ *
107
+ * 四种场景:
108
+ * 1. 文件不存在 → 创建完整文件(header + markers)
109
+ * 2. 文件有 begin/end 标记 → 仅替换标记区段(增量更新)
110
+ * 3. 文件有旧版 AutoSnippet 签名但无标记 → 全量重写并加标记(旧版迁移)
111
+ * 4. 文件无签名无标记(用户文件)→ 追加标记区段到末尾(共存)
112
+ */
113
+ export function mergeSection(filePath, section, options = {}) {
114
+ const { header = '', logger } = options;
115
+ const fileName = path.basename(filePath);
116
+ // 确保 section 包含 begin/end 标记
117
+ const wrappedSection = section.includes(SECTION_BEGIN)
118
+ ? section
119
+ : `${SECTION_BEGIN}\n\n${section}\n${SECTION_END}`;
120
+ // Case 1: 文件不存在 → 创建完整文件
121
+ if (!fs.existsSync(filePath)) {
122
+ const content = header ? `${header}\n${wrappedSection}\n` : `${wrappedSection}\n`;
123
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
124
+ fs.writeFileSync(filePath, content, 'utf8');
125
+ logger?.info?.(`[FileProtection] Created "${fileName}" (new file)`);
126
+ return { written: true, strategy: 'create', filePath };
127
+ }
128
+ const existing = fs.readFileSync(filePath, 'utf8');
129
+ // Case 2: 文件已有 begin/end 标记 → 仅替换标记区段
130
+ if (SECTION_PATTERN.test(existing)) {
131
+ const updated = existing.replace(SECTION_PATTERN, wrappedSection);
132
+ if (updated === existing) {
133
+ logger?.info?.(`[FileProtection] "${fileName}" — section unchanged, skipped write`);
134
+ return { written: false, strategy: 'replace-section', filePath };
135
+ }
136
+ fs.writeFileSync(filePath, updated, 'utf8');
137
+ logger?.info?.(`[FileProtection] Updated "${fileName}" (replaced marker section)`);
138
+ return { written: true, strategy: 'replace-section', filePath };
139
+ }
140
+ // Case 3: 文件有 AutoSnippet 签名但无标记 → 旧版格式,重写并加标记
141
+ if (SIGNATURE_PATTERN.test(existing.slice(0, 1024))) {
142
+ const content = header ? `${header}\n${wrappedSection}\n` : `${wrappedSection}\n`;
143
+ fs.writeFileSync(filePath, content, 'utf8');
144
+ logger?.info?.(`[FileProtection] Rewrote "${fileName}" (legacy → marker format)`);
145
+ return { written: true, strategy: 'rewrite-legacy', filePath };
146
+ }
147
+ // Case 4: 用户自有文件 → 追加标记区段到末尾
148
+ const separator = existing.endsWith('\n') ? '\n' : '\n\n';
149
+ fs.writeFileSync(filePath, `${existing}${separator}${wrappedSection}\n`, 'utf8');
150
+ logger?.info?.(`[FileProtection] Appended AutoSnippet section to "${fileName}" (user-owned file preserved)`);
151
+ return { written: true, strategy: 'append-section', filePath };
152
+ }
@@ -19,36 +19,31 @@ import { SKILLS_DIR as BUILTIN_SKILLS_DIR } from '../../shared/package-root.js';
19
19
  */
20
20
  const SKILL_NAME_MAP = {
21
21
  'project-architecture': 'autosnippet-architecture',
22
- 'project-code-standard': 'autosnippet-code-standard',
23
- 'project-profile': 'autosnippet-profile',
22
+ 'project-coding-standards': 'autosnippet-coding-standards',
24
23
  'project-agent-guidelines': 'autosnippet-guidelines',
25
- 'project-event-and-data-flow': 'autosnippet-data-flow',
26
- 'project-code-pattern': 'autosnippet-code-pattern',
27
- 'project-objc-deep-scan': 'autosnippet-objc-deep-scan',
28
- 'project-category-scan': 'autosnippet-category-scan',
29
- 'project-best-practice': 'autosnippet-best-practice',
30
- // 新语言维度
31
- 'project-module-exports': 'autosnippet-module-exports',
32
- 'project-framework-conventions': 'autosnippet-framework-conventions',
24
+ 'project-data-event-flow': 'autosnippet-data-flow',
25
+ 'project-design-patterns': 'autosnippet-design-patterns',
26
+ 'project-error-resilience': 'autosnippet-error-resilience',
27
+ 'project-swift-objc-idiom': 'autosnippet-swift-objc-idiom',
28
+ // 语言维度
29
+ 'project-ts-js-module': 'autosnippet-ts-js-module',
30
+ 'project-react-patterns': 'autosnippet-react-patterns',
33
31
  'project-python-structure': 'autosnippet-python-structure',
34
- 'project-jvm-annotations': 'autosnippet-jvm-annotations',
32
+ 'project-jvm-annotation': 'autosnippet-jvm-annotation',
35
33
  };
36
34
  /** 用途描述模板(英文,Cursor 优先) */
37
35
  const SKILL_DESC_MAP = {
38
36
  'autosnippet-architecture': 'Architecture patterns, module boundaries, and dependency rules for {project}. Use when creating new modules, reviewing architecture, or understanding dependencies.',
39
- 'autosnippet-code-standard': 'Coding standards and style conventions for {project}. Use when writing new code, reviewing formatting, or enforcing naming conventions.',
40
- 'autosnippet-profile': 'Project overview and profile for {project}. Use when needing background on the project, its tech stack, or structure.',
37
+ 'autosnippet-coding-standards': 'Coding standards and style conventions for {project}. Use when writing new code, reviewing formatting, or enforcing naming conventions.',
41
38
  'autosnippet-guidelines': 'Agent interaction guidelines for {project}. Use when understanding how to work with this specific project.',
42
39
  'autosnippet-data-flow': 'Event and data flow patterns for {project}. Use when working with events, state management, or data pipelines.',
43
- 'autosnippet-code-pattern': 'Common code patterns and idioms for {project}. Use when implementing features following project conventions.',
44
- 'autosnippet-objc-deep-scan': 'Objective-C deep scan results for {project}. Use when working with Objective-C code, method swizzling, or runtime features.',
45
- 'autosnippet-category-scan': 'Category and extension analysis for {project}. Use when working with categories or finding existing utility methods.',
46
- 'autosnippet-best-practice': 'Best practices and proven patterns for {project}. Use when making design decisions or code review.',
47
- // 新语言维度
48
- 'autosnippet-module-exports': 'Module export structure, barrel exports, and public API surface for {project}. Use when working with imports/exports or module boundaries.',
49
- 'autosnippet-framework-conventions': 'Framework-specific conventions (component structure, routing, state management) for {project}. Use when following framework patterns.',
40
+ 'autosnippet-design-patterns': 'Common code patterns and idioms for {project}. Use when implementing features following project conventions.',
41
+ 'autosnippet-error-resilience': 'Error handling, resilience patterns and defensive coding for {project}. Use when making design decisions or code review.',
42
+ 'autosnippet-swift-objc-idiom': 'Swift/ObjC idioms, categories, method swizzling and interop for {project}. Use when working with Swift or Objective-C code.',
43
+ 'autosnippet-ts-js-module': 'Module export structure, barrel exports, and public API surface for {project}. Use when working with imports/exports or module boundaries.',
44
+ 'autosnippet-react-patterns': 'React component patterns, state management conventions and routing for {project}. Use when following framework patterns.',
50
45
  'autosnippet-python-structure': 'Python package structure, __init__.py exports, import patterns and type hint coverage for {project}. Use when working with Python modules.',
51
- 'autosnippet-jvm-annotations': 'Annotation patterns (DI, ORM, API, custom) and meta-programming for {project}. Use when working with Spring, Jakarta, or framework annotations.',
46
+ 'autosnippet-jvm-annotation': 'Annotation patterns (DI, ORM, API, custom) and meta-programming for {project}. Use when working with Spring, Jakarta, or framework annotations.',
52
47
  };
53
48
  export class SkillsSyncer {
54
49
  knowledgeService;