autosnippet 2.9.0 → 2.11.0
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/README.md +12 -12
- package/bin/cli.js +53 -40
- package/config/constitution.yaml +9 -2
- package/dashboard/dist/assets/{icons-CH-H9x0E.js → icons-D4IWpDIk.js} +105 -100
- package/dashboard/dist/assets/index-CWBNcF9z.css +1 -0
- package/dashboard/dist/assets/index-DHtzhbuG.js +120 -0
- package/dashboard/dist/index.html +3 -3
- package/lib/cli/AiScanService.js +35 -36
- package/lib/cli/KnowledgeSyncService.js +345 -0
- package/lib/cli/SetupService.js +8 -26
- package/lib/cli/UpgradeService.js +28 -0
- package/lib/core/gateway/GatewayActionRegistry.js +48 -58
- package/lib/domain/index.js +16 -11
- package/lib/domain/knowledge/KnowledgeEntry.js +289 -0
- package/lib/domain/knowledge/KnowledgeRepository.js +123 -0
- package/lib/domain/knowledge/Lifecycle.js +99 -0
- package/lib/domain/knowledge/index.js +27 -0
- package/lib/domain/knowledge/values/Constraints.js +128 -0
- package/lib/domain/knowledge/values/Content.js +69 -0
- package/lib/domain/knowledge/values/Quality.js +81 -0
- package/lib/domain/knowledge/values/Reasoning.js +70 -0
- package/lib/domain/knowledge/values/Relations.js +142 -0
- package/lib/domain/knowledge/values/Stats.js +72 -0
- package/lib/domain/knowledge/values/index.js +9 -0
- package/lib/external/ai/AiProvider.js +85 -11
- package/lib/external/mcp/McpServer.js +7 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +18 -2
- package/lib/external/mcp/handlers/bootstrap.js +116 -11
- package/lib/external/mcp/handlers/browse.js +76 -73
- package/lib/external/mcp/handlers/candidate.js +26 -275
- package/lib/external/mcp/handlers/guard.js +2 -0
- package/lib/external/mcp/handlers/knowledge.js +267 -0
- package/lib/external/mcp/handlers/structure.js +25 -23
- package/lib/external/mcp/handlers/system.js +10 -12
- package/lib/external/mcp/tools.js +134 -140
- package/lib/http/HttpServer.js +14 -8
- package/lib/http/routes/ai.js +4 -3
- package/lib/http/routes/extract.js +48 -4
- package/lib/http/routes/knowledge.js +246 -0
- package/lib/http/routes/search.js +12 -17
- package/lib/infrastructure/database/migrations/016_unified_knowledge_entries.js +395 -0
- package/lib/infrastructure/database/migrations/017_camelcase_knowledge_entries.js +107 -0
- package/lib/infrastructure/external/XcodeAutomation.js +187 -103
- package/lib/injection/ServiceContainer.js +69 -60
- package/lib/repository/knowledge/KnowledgeRepository.impl.js +338 -0
- package/lib/service/automation/DirectiveDetector.js +2 -3
- package/lib/service/automation/FileWatcher.js +59 -28
- package/lib/service/automation/XcodeIntegration.js +931 -156
- package/lib/service/automation/handlers/AlinkHandler.js +5 -4
- package/lib/service/automation/handlers/CreateHandler.js +53 -19
- package/lib/service/automation/handlers/DraftHandler.js +1 -1
- package/lib/service/automation/handlers/GuardHandler.js +183 -20
- package/lib/service/automation/handlers/SearchHandler.js +25 -22
- package/lib/service/candidate/SimilarityService.js +2 -2
- package/lib/service/chat/AnalystAgent.js +9 -0
- package/lib/service/chat/CandidateGuardrail.js +22 -11
- package/lib/service/chat/ChatAgent.js +132 -54
- package/lib/service/chat/ContextWindow.js +5 -5
- package/lib/service/chat/HandoffProtocol.js +1 -0
- package/lib/service/chat/ProducerAgent.js +40 -13
- package/lib/service/chat/ReasoningLayer.js +854 -0
- package/lib/service/chat/ReasoningTrace.js +329 -0
- package/lib/service/chat/tools.js +308 -205
- package/lib/service/cursor/CursorDeliveryPipeline.js +279 -0
- package/lib/service/cursor/KnowledgeCompressor.js +87 -0
- package/lib/service/cursor/RulesGenerator.js +168 -0
- package/lib/service/cursor/SkillsSyncer.js +268 -0
- package/lib/service/cursor/TokenBudget.js +58 -0
- package/lib/service/cursor/TopicClassifier.js +141 -0
- package/lib/service/guard/GuardCheckEngine.js +99 -10
- package/lib/service/guard/GuardService.js +57 -46
- package/lib/service/knowledge/ConfidenceRouter.js +159 -0
- package/lib/service/knowledge/KnowledgeFileWriter.js +595 -0
- package/lib/service/knowledge/KnowledgeService.js +802 -0
- package/lib/service/recipe/RecipeParser.js +3 -12
- package/lib/service/search/SearchEngine.js +67 -22
- package/lib/service/skills/SignalCollector.js +14 -9
- package/lib/service/skills/SkillAdvisor.js +13 -11
- package/lib/service/snippet/SnippetFactory.js +5 -5
- package/lib/service/spm/SpmService.js +15 -48
- package/lib/shared/RecipeReadinessChecker.js +6 -11
- package/package.json +1 -1
- package/scripts/install-cursor-skill.js +0 -6
- package/scripts/migrate-md-to-knowledge.mjs +364 -0
- package/skills/autosnippet-analysis/SKILL.md +15 -7
- package/skills/autosnippet-candidates/SKILL.md +8 -8
- package/skills/autosnippet-coldstart/SKILL.md +8 -4
- package/skills/autosnippet-concepts/SKILL.md +7 -6
- package/skills/autosnippet-create/SKILL.md +13 -13
- package/skills/autosnippet-intent/SKILL.md +3 -2
- package/skills/autosnippet-lifecycle/SKILL.md +5 -5
- package/skills/autosnippet-recipes/SKILL.md +18 -6
- package/templates/constitution.yaml +1 -1
- package/templates/copilot-instructions.md +6 -6
- package/templates/recipes-setup/README.md +3 -3
- package/dashboard/dist/assets/index-CqJRvYRL.js +0 -197
- package/dashboard/dist/assets/index-DICm9PNa.css +0 -1
- package/lib/cli/CandidateSyncService.js +0 -261
- package/lib/cli/SyncService.js +0 -356
- package/lib/domain/candidate/Candidate.js +0 -196
- package/lib/domain/candidate/CandidateRepository.js +0 -107
- package/lib/domain/candidate/Reasoning.js +0 -52
- package/lib/domain/recipe/Recipe.js +0 -421
- package/lib/domain/recipe/RecipeRepository.js +0 -54
- package/lib/domain/types/CandidateStatus.js +0 -52
- package/lib/http/routes/candidates.js +0 -559
- package/lib/http/routes/recipes.js +0 -397
- package/lib/repository/candidate/CandidateRepository.impl.js +0 -230
- package/lib/repository/recipe/RecipeRepository.impl.js +0 -498
- package/lib/service/candidate/CandidateAggregator.js +0 -52
- package/lib/service/candidate/CandidateFileWriter.js +0 -383
- package/lib/service/candidate/CandidateService.js +0 -1001
- package/lib/service/recipe/RecipeFileWriter.js +0 -514
- package/lib/service/recipe/RecipeService.js +0 -786
- package/lib/service/recipe/RecipeStatsTracker.js +0 -148
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* migrate-md-to-knowledge.mjs — 将旧格式 .md 文件迁移为统一 Knowledge 格式
|
|
4
|
+
*
|
|
5
|
+
* 扫描 AutoSnippet/candidates/ 和 AutoSnippet/recipes/ 下的旧格式 .md 文件,
|
|
6
|
+
* 用旧 parser 解析 → 转换为 KnowledgeEntry → 用 KnowledgeFileWriter 重新序列化。
|
|
7
|
+
*
|
|
8
|
+
* 旧文件会备份到 AutoSnippet/_backup/{candidates|recipes}/ 目录下。
|
|
9
|
+
*
|
|
10
|
+
* 用法:
|
|
11
|
+
* node scripts/migrate-md-to-knowledge.mjs [projectRoot]
|
|
12
|
+
*
|
|
13
|
+
* --dry-run 只报告,不写入
|
|
14
|
+
* --no-backup 不创建备份
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
|
|
21
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
|
|
23
|
+
// ── 解析命令行 ──
|
|
24
|
+
const args = process.argv.slice(2);
|
|
25
|
+
const dryRun = args.includes('--dry-run');
|
|
26
|
+
const noBackup = args.includes('--no-backup');
|
|
27
|
+
const projectRoot = args.find(a => !a.startsWith('--')) || process.cwd();
|
|
28
|
+
|
|
29
|
+
// ── 动态导入(兼容 ESM) ──
|
|
30
|
+
const { parseRecipeMarkdown } = await import('../lib/service/recipe/RecipeFileWriter.js');
|
|
31
|
+
const { parseCandidateMarkdown } = await import('../lib/service/candidate/CandidateFileWriter.js');
|
|
32
|
+
const { KnowledgeEntry } = await import('../lib/domain/knowledge/KnowledgeEntry.js');
|
|
33
|
+
const { KnowledgeFileWriter } = await import('../lib/service/knowledge/KnowledgeFileWriter.js');
|
|
34
|
+
const { Lifecycle } = await import('../lib/domain/knowledge/Lifecycle.js');
|
|
35
|
+
const { inferKind: inferKindV3 } = await import('../lib/domain/knowledge/Lifecycle.js');
|
|
36
|
+
|
|
37
|
+
const RECIPES_DIR = 'AutoSnippet/recipes';
|
|
38
|
+
const CANDIDATES_DIR = 'AutoSnippet/candidates';
|
|
39
|
+
const BACKUP_DIR = 'AutoSnippet/_backup';
|
|
40
|
+
|
|
41
|
+
const recipesDir = path.join(projectRoot, RECIPES_DIR);
|
|
42
|
+
const candidatesDir = path.join(projectRoot, CANDIDATES_DIR);
|
|
43
|
+
const backupDir = path.join(projectRoot, BACKUP_DIR);
|
|
44
|
+
|
|
45
|
+
const report = {
|
|
46
|
+
recipes: { total: 0, migrated: 0, skipped: 0, errors: [] },
|
|
47
|
+
candidates: { total: 0, migrated: 0, skipped: 0, errors: [] },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// ── 工具函数 ──
|
|
51
|
+
|
|
52
|
+
function collectMdFiles(dir) {
|
|
53
|
+
if (!fs.existsSync(dir)) return [];
|
|
54
|
+
const results = [];
|
|
55
|
+
const walk = (curDir, base) => {
|
|
56
|
+
for (const entry of fs.readdirSync(curDir, { withFileTypes: true })) {
|
|
57
|
+
const full = path.join(curDir, entry.name);
|
|
58
|
+
const rel = base ? `${base}/${entry.name}` : entry.name;
|
|
59
|
+
if (entry.isDirectory()) {
|
|
60
|
+
walk(full, rel);
|
|
61
|
+
} else if (entry.name.endsWith('.md') && !entry.name.startsWith('_')) {
|
|
62
|
+
results.push({ absPath: full, relPath: rel });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
walk(dir, '');
|
|
67
|
+
return results;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function backupFile(absPath, type) {
|
|
71
|
+
if (noBackup || dryRun) return;
|
|
72
|
+
const rel = path.relative(
|
|
73
|
+
type === 'recipe' ? recipesDir : candidatesDir,
|
|
74
|
+
absPath
|
|
75
|
+
);
|
|
76
|
+
const dest = path.join(backupDir, type === 'recipe' ? 'recipes' : 'candidates', rel);
|
|
77
|
+
const destDir = path.dirname(dest);
|
|
78
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
79
|
+
fs.copyFileSync(absPath, dest);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 判断文件是否已经是新格式(包含 lifecycle 和 _content 字段)
|
|
84
|
+
*/
|
|
85
|
+
function isAlreadyNewFormat(content) {
|
|
86
|
+
const fm = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
|
|
87
|
+
if (!fm) return false;
|
|
88
|
+
return fm[1].includes('lifecycle:') && fm[1].includes('_content:');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ═══ Recipe 迁移 ═══
|
|
92
|
+
|
|
93
|
+
function migrateRecipe(absPath, relPath) {
|
|
94
|
+
const content = fs.readFileSync(absPath, 'utf8');
|
|
95
|
+
|
|
96
|
+
// 跳过已迁移的文件
|
|
97
|
+
if (isAlreadyNewFormat(content)) {
|
|
98
|
+
report.recipes.skipped++;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const parsed = parseRecipeMarkdown(content, relPath);
|
|
103
|
+
|
|
104
|
+
// 映射旧 Recipe 字段 → KnowledgeEntry wire format
|
|
105
|
+
const statusMap = {
|
|
106
|
+
active: Lifecycle.ACTIVE,
|
|
107
|
+
deprecated: Lifecycle.DEPRECATED,
|
|
108
|
+
draft: Lifecycle.DRAFT,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// 提取旧 dimensions
|
|
112
|
+
const quality = parsed.quality || {};
|
|
113
|
+
const stats = parsed.statistics || {};
|
|
114
|
+
|
|
115
|
+
const wireData = {
|
|
116
|
+
id: parsed.id,
|
|
117
|
+
title: parsed.title,
|
|
118
|
+
trigger: parsed.trigger || '',
|
|
119
|
+
description: parsed.summaryCn || parsed.summaryEn || '',
|
|
120
|
+
lifecycle: statusMap[parsed.status] || Lifecycle.ACTIVE,
|
|
121
|
+
lifecycle_history: [],
|
|
122
|
+
probation: false,
|
|
123
|
+
language: parsed.language || 'swift',
|
|
124
|
+
category: parsed.category || 'general',
|
|
125
|
+
kind: parsed.kind || inferKindV3(parsed.knowledgeType || 'code-pattern'),
|
|
126
|
+
knowledge_type: parsed.knowledgeType || 'code-pattern',
|
|
127
|
+
complexity: parsed.complexity || 'intermediate',
|
|
128
|
+
scope: parsed.scope || 'universal',
|
|
129
|
+
difficulty: parsed.difficulty || null,
|
|
130
|
+
tags: parsed.tags || [],
|
|
131
|
+
summary_cn: parsed.summaryCn || '',
|
|
132
|
+
summary_en: parsed.summaryEn || '',
|
|
133
|
+
usage_guide_cn: parsed.usageGuideCn || '',
|
|
134
|
+
usage_guide_en: parsed.usageGuideEn || '',
|
|
135
|
+
content: {
|
|
136
|
+
pattern: '',
|
|
137
|
+
markdown: '',
|
|
138
|
+
rationale: '',
|
|
139
|
+
steps: [],
|
|
140
|
+
code_changes: [],
|
|
141
|
+
verification: null,
|
|
142
|
+
},
|
|
143
|
+
relations: parsed.relations || {},
|
|
144
|
+
constraints: parsed.constraints || {},
|
|
145
|
+
reasoning: {},
|
|
146
|
+
quality: {
|
|
147
|
+
completeness: quality.codeCompleteness ?? quality.completeness ?? 0,
|
|
148
|
+
adaptation: quality.projectAdaptation ?? quality.adaptation ?? 0,
|
|
149
|
+
documentation: quality.documentationClarity ?? quality.documentation ?? 0,
|
|
150
|
+
overall: quality.overall ?? 0,
|
|
151
|
+
grade: quality.grade || 'F',
|
|
152
|
+
},
|
|
153
|
+
stats: {
|
|
154
|
+
views: stats.viewCount ?? stats.views ?? 0,
|
|
155
|
+
adoptions: stats.adoptionCount ?? stats.adoptions ?? 0,
|
|
156
|
+
applications: stats.applicationCount ?? stats.applications ?? 0,
|
|
157
|
+
guard_hits: stats.guardHitCount ?? stats.guard_hits ?? 0,
|
|
158
|
+
search_hits: stats.searchHits ?? stats.search_hits ?? 0,
|
|
159
|
+
authority: parsed.authority ?? stats.authority ?? 0,
|
|
160
|
+
},
|
|
161
|
+
headers: parsed.headers || [],
|
|
162
|
+
header_paths: [],
|
|
163
|
+
module_name: '',
|
|
164
|
+
include_headers: false,
|
|
165
|
+
agent_notes: null,
|
|
166
|
+
ai_insight: null,
|
|
167
|
+
reviewed_by: null,
|
|
168
|
+
reviewed_at: null,
|
|
169
|
+
rejection_reason: parsed.deprecationReason || null,
|
|
170
|
+
source: 'migration',
|
|
171
|
+
source_file: `${RECIPES_DIR}/${relPath}`,
|
|
172
|
+
source_candidate_id: parsed.sourceCandidate || null,
|
|
173
|
+
created_by: parsed.createdBy || 'system',
|
|
174
|
+
created_at: parsed.createdAt || Math.floor(Date.now() / 1000),
|
|
175
|
+
updated_at: parsed.updatedAt || Math.floor(Date.now() / 1000),
|
|
176
|
+
published_at: parsed.publishedAt || null,
|
|
177
|
+
published_by: parsed.publishedBy || null,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// 提取 body 内容到 content
|
|
181
|
+
const bodyMatch = content.match(/^---[\s\S]*?---\s*\r?\n([\s\S]*)$/);
|
|
182
|
+
if (bodyMatch) {
|
|
183
|
+
const body = bodyMatch[1].trim();
|
|
184
|
+
const codeMatch = body.match(/```\w*\n([\s\S]*?)```/);
|
|
185
|
+
if (codeMatch) {
|
|
186
|
+
wireData.content.pattern = codeMatch[1].trimEnd();
|
|
187
|
+
}
|
|
188
|
+
// 如果有完整 markdown 内容(项目特写)
|
|
189
|
+
if (body.includes('— 项目特写') || (body.length > 500 && body.startsWith('#'))) {
|
|
190
|
+
wireData.content.markdown = body;
|
|
191
|
+
wireData.content.pattern = '';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 构建实体并重新序列化
|
|
196
|
+
const entry = KnowledgeEntry.fromJSON(wireData);
|
|
197
|
+
const writer = new KnowledgeFileWriter(projectRoot);
|
|
198
|
+
const newMarkdown = writer.serialize(entry);
|
|
199
|
+
|
|
200
|
+
if (!dryRun) {
|
|
201
|
+
backupFile(absPath, 'recipe');
|
|
202
|
+
fs.writeFileSync(absPath, newMarkdown, 'utf8');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
report.recipes.migrated++;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ═══ Candidate 迁移 ═══
|
|
209
|
+
|
|
210
|
+
function migrateCandidate(absPath, relPath) {
|
|
211
|
+
const content = fs.readFileSync(absPath, 'utf8');
|
|
212
|
+
|
|
213
|
+
// 跳过已迁移的文件
|
|
214
|
+
if (isAlreadyNewFormat(content)) {
|
|
215
|
+
report.candidates.skipped++;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const parsed = parseCandidateMarkdown(content, relPath);
|
|
220
|
+
|
|
221
|
+
// 映射旧 Candidate 状态 → lifecycle
|
|
222
|
+
const statusMap = {
|
|
223
|
+
pending: Lifecycle.PENDING,
|
|
224
|
+
approved: Lifecycle.APPROVED,
|
|
225
|
+
rejected: Lifecycle.REJECTED,
|
|
226
|
+
applied: Lifecycle.ACTIVE,
|
|
227
|
+
draft: Lifecycle.DRAFT,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const meta = parsed._metadata || {};
|
|
231
|
+
const reasoning = parsed._reasoning || {};
|
|
232
|
+
const code = parsed._bodyCode || '';
|
|
233
|
+
|
|
234
|
+
// 判断内容类型
|
|
235
|
+
const isMarkdown = code && (
|
|
236
|
+
code.includes('— 项目特写') || /^#{1,3}\s/.test(code.trimStart())
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
const wireData = {
|
|
240
|
+
id: parsed.id,
|
|
241
|
+
title: meta.title || meta.description || (code ? code.substring(0, 60) : ''),
|
|
242
|
+
trigger: meta.trigger || '',
|
|
243
|
+
description: meta.description || '',
|
|
244
|
+
lifecycle: statusMap[parsed.status] || Lifecycle.PENDING,
|
|
245
|
+
lifecycle_history: parsed._statusHistory || [],
|
|
246
|
+
probation: false,
|
|
247
|
+
language: parsed.language || 'swift',
|
|
248
|
+
category: meta.category || parsed.category || 'general',
|
|
249
|
+
kind: inferKindV3(meta.knowledgeType || 'code-pattern'),
|
|
250
|
+
knowledge_type: meta.knowledgeType || 'code-pattern',
|
|
251
|
+
complexity: meta.complexity || 'intermediate',
|
|
252
|
+
scope: meta.scope || 'universal',
|
|
253
|
+
difficulty: meta.difficulty || null,
|
|
254
|
+
tags: meta.tags || [],
|
|
255
|
+
summary_cn: meta.summary || meta.summary_cn || '',
|
|
256
|
+
summary_en: meta.summary_en || '',
|
|
257
|
+
usage_guide_cn: meta.usageGuide || meta.usageGuide_cn || '',
|
|
258
|
+
usage_guide_en: meta.usageGuide_en || '',
|
|
259
|
+
content: {
|
|
260
|
+
pattern: isMarkdown ? '' : code,
|
|
261
|
+
markdown: isMarkdown ? code : '',
|
|
262
|
+
rationale: meta.rationale || (typeof reasoning === 'object' ? reasoning.whyStandard : '') || '',
|
|
263
|
+
steps: meta.steps || [],
|
|
264
|
+
code_changes: meta.codeChanges || [],
|
|
265
|
+
verification: meta.verification || null,
|
|
266
|
+
},
|
|
267
|
+
relations: Array.isArray(meta.relations)
|
|
268
|
+
? { related: meta.relations.map(r => typeof r === 'string' ? { target: r, description: '' } : r) }
|
|
269
|
+
: (meta.relations || {}),
|
|
270
|
+
constraints: meta.constraints || {},
|
|
271
|
+
reasoning: {
|
|
272
|
+
why_standard: (typeof reasoning === 'object' ? reasoning.whyStandard : '') || '',
|
|
273
|
+
sources: (typeof reasoning === 'object' ? reasoning.sources : []) || [],
|
|
274
|
+
confidence: (typeof reasoning === 'object' ? reasoning.confidence : 0.7) ?? 0.7,
|
|
275
|
+
quality_signals: (typeof reasoning === 'object' ? reasoning.qualitySignals : {}) || {},
|
|
276
|
+
alternatives: (typeof reasoning === 'object' ? reasoning.alternatives : []) || [],
|
|
277
|
+
},
|
|
278
|
+
quality: meta.quality || {},
|
|
279
|
+
stats: {},
|
|
280
|
+
headers: meta.headers || [],
|
|
281
|
+
header_paths: [],
|
|
282
|
+
module_name: '',
|
|
283
|
+
include_headers: false,
|
|
284
|
+
agent_notes: null,
|
|
285
|
+
ai_insight: null,
|
|
286
|
+
reviewed_by: parsed.approvedBy || parsed.rejectedBy || null,
|
|
287
|
+
reviewed_at: parsed.approvedAt || null,
|
|
288
|
+
rejection_reason: parsed.rejectionReason || null,
|
|
289
|
+
source: parsed.source || 'migration',
|
|
290
|
+
source_file: `${CANDIDATES_DIR}/${relPath}`,
|
|
291
|
+
source_candidate_id: null,
|
|
292
|
+
created_by: parsed.createdBy || 'system',
|
|
293
|
+
created_at: parsed.createdAt || Math.floor(Date.now() / 1000),
|
|
294
|
+
updated_at: parsed.updatedAt || Math.floor(Date.now() / 1000),
|
|
295
|
+
published_at: null,
|
|
296
|
+
published_by: null,
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// 构建实体并重新序列化
|
|
300
|
+
const entry = KnowledgeEntry.fromJSON(wireData);
|
|
301
|
+
const writer = new KnowledgeFileWriter(projectRoot);
|
|
302
|
+
const newMarkdown = writer.serialize(entry);
|
|
303
|
+
|
|
304
|
+
if (!dryRun) {
|
|
305
|
+
backupFile(absPath, 'candidate');
|
|
306
|
+
fs.writeFileSync(absPath, newMarkdown, 'utf8');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
report.candidates.migrated++;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ═══ 主流程 ═══
|
|
313
|
+
|
|
314
|
+
console.log(`\n🔄 Knowledge .md Migration`);
|
|
315
|
+
console.log(` Project: ${projectRoot}`);
|
|
316
|
+
console.log(` Mode: ${dryRun ? 'DRY RUN' : 'LIVE'}`);
|
|
317
|
+
console.log(` Backup: ${noBackup ? 'disabled' : 'enabled'}`);
|
|
318
|
+
console.log('');
|
|
319
|
+
|
|
320
|
+
// ── 迁移 Recipes ──
|
|
321
|
+
const recipeFiles = collectMdFiles(recipesDir);
|
|
322
|
+
report.recipes.total = recipeFiles.length;
|
|
323
|
+
console.log(`📦 Recipes: ${recipeFiles.length} files found`);
|
|
324
|
+
|
|
325
|
+
for (const { absPath, relPath } of recipeFiles) {
|
|
326
|
+
try {
|
|
327
|
+
migrateRecipe(absPath, relPath);
|
|
328
|
+
} catch (err) {
|
|
329
|
+
report.recipes.errors.push({ file: relPath, error: err.message });
|
|
330
|
+
console.error(` ❌ ${relPath}: ${err.message}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// ── 迁移 Candidates ──
|
|
335
|
+
const candidateFiles = collectMdFiles(candidatesDir);
|
|
336
|
+
report.candidates.total = candidateFiles.length;
|
|
337
|
+
console.log(`📦 Candidates: ${candidateFiles.length} files found`);
|
|
338
|
+
|
|
339
|
+
for (const { absPath, relPath } of candidateFiles) {
|
|
340
|
+
try {
|
|
341
|
+
migrateCandidate(absPath, relPath);
|
|
342
|
+
} catch (err) {
|
|
343
|
+
report.candidates.errors.push({ file: relPath, error: err.message });
|
|
344
|
+
console.error(` ❌ ${relPath}: ${err.message}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// ── 报告 ──
|
|
349
|
+
console.log('\n═══ Migration Report ═══');
|
|
350
|
+
console.log(` Recipes: ${report.recipes.migrated}/${report.recipes.total} migrated, ${report.recipes.skipped} already new format, ${report.recipes.errors.length} errors`);
|
|
351
|
+
console.log(` Candidates: ${report.candidates.migrated}/${report.candidates.total} migrated, ${report.candidates.skipped} already new format, ${report.candidates.errors.length} errors`);
|
|
352
|
+
|
|
353
|
+
if (!noBackup && !dryRun) {
|
|
354
|
+
console.log(`\n Backups saved to: ${backupDir}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (report.recipes.errors.length + report.candidates.errors.length > 0) {
|
|
358
|
+
console.log('\n Errors:');
|
|
359
|
+
for (const e of [...report.recipes.errors, ...report.candidates.errors]) {
|
|
360
|
+
console.log(` - ${e.file}: ${e.error}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
console.log('');
|
|
@@ -73,7 +73,7 @@ description: Deep project analysis — full scan + semantic field enrichment + g
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
Use `
|
|
76
|
+
Use `autosnippet_submit_knowledge_batch` for batch submission.
|
|
77
77
|
|
|
78
78
|
#### Phase 4: Guard Deep Audit (Optional)
|
|
79
79
|
对特定文件调用 `autosnippet_guard_audit_files` 做深度规范审计。
|
|
@@ -101,7 +101,7 @@ Use `autosnippet_submit_candidates` for batch submission.
|
|
|
101
101
|
### Workflow for Enrichment
|
|
102
102
|
|
|
103
103
|
**方式 A: 你(Agent)直接补全**
|
|
104
|
-
在分析代码时,直接填写所有 6 个语义字段到 `
|
|
104
|
+
在分析代码时,直接填写所有 6 个语义字段到 `autosnippet_submit_knowledge` 调用中。
|
|
105
105
|
|
|
106
106
|
**方式 B: 对已有候选调用 AI 补全**
|
|
107
107
|
```
|
|
@@ -109,6 +109,13 @@ autosnippet_enrich_candidates({ candidateIds: ["id1", "id2", ...] })
|
|
|
109
109
|
```
|
|
110
110
|
AI 会分析每条候选的代码,自动填充缺失字段(已有字段不会被覆盖)。
|
|
111
111
|
|
|
112
|
+
**方式 C: Bootstrap 候选 AI 润色**
|
|
113
|
+
```
|
|
114
|
+
autosnippet_bootstrap_refine({ candidateIds: ["id1", "id2", ...] })
|
|
115
|
+
```
|
|
116
|
+
使用 AI 对 Bootstrap 候选做内容润色(改善 summary、补充 insight、推断 relations、调整 confidence)。
|
|
117
|
+
必须在 `autosnippet_enrich_candidates` 之后调用(确保字段完整后再润色)。
|
|
118
|
+
|
|
112
119
|
---
|
|
113
120
|
|
|
114
121
|
## Capability 3: 候选 → Recipe 查漏补缺
|
|
@@ -119,11 +126,12 @@ AI 会分析每条候选的代码,自动填充缺失字段(已有字段不
|
|
|
119
126
|
|
|
120
127
|
### Workflow
|
|
121
128
|
|
|
122
|
-
1. 调用 `autosnippet_enrich_candidates`
|
|
123
|
-
2. 调用 `
|
|
124
|
-
3. 调用 `
|
|
125
|
-
4.
|
|
126
|
-
5.
|
|
129
|
+
1. 调用 `autosnippet_enrich_candidates` 对目标候选做结构补齐(诊断缺失字段)
|
|
130
|
+
2. 调用 `autosnippet_bootstrap_refine` 对候选做 AI 润色(summary/insight/relations)
|
|
131
|
+
3. 调用 `autosnippet_validate_candidate` 检查结构完整性
|
|
132
|
+
4. 调用 `autosnippet_check_duplicate` 检查重复
|
|
133
|
+
5. 报告补全情况 + 缺失字段 + 重复风险
|
|
134
|
+
6. 如缺失字段 AI 无法填充,提示用户手动补充
|
|
127
135
|
|
|
128
136
|
### Recipe 必备字段检查清单
|
|
129
137
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: autosnippet-candidates
|
|
3
|
-
description: Generate Recipe candidates with full
|
|
3
|
+
description: Generate Recipe candidates with full V3 structured information. Single file scan or batch Target scan. Agent extracts rich metadata matching the complete Recipe schema. Agent submits candidates only; Recipe creation/modification is human-only.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# AutoSnippet - Generate Candidates with Structured Content (v3.1)
|
|
@@ -65,7 +65,7 @@ Recipe creation, review, publish, update, deprecate, delete are **human-only via
|
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
-
##
|
|
68
|
+
## V3 Complete Candidate Field Model
|
|
69
69
|
|
|
70
70
|
Every candidate submitted via `submit_candidate` or `submit_candidates` supports the following fields. **The richer the information, the higher the quality of the resulting Recipe.**
|
|
71
71
|
|
|
@@ -221,18 +221,18 @@ Severity: `error` (must fix) | `warning` (should fix) | `info` (suggestion)
|
|
|
221
221
|
3. Call `autosnippet_context_search` to mark similarity and fill `relations`
|
|
222
222
|
4. (Optional) `autosnippet_validate_candidate` pre-validate
|
|
223
223
|
5. (Optional) `autosnippet_check_duplicate` dedup hint
|
|
224
|
-
6. `
|
|
224
|
+
6. `autosnippet_submit_knowledge` or `autosnippet_submit_knowledge_batch` to submit
|
|
225
225
|
|
|
226
226
|
## Batch Target Scan Flow
|
|
227
227
|
1. `autosnippet_get_targets` → select targetName
|
|
228
228
|
2. `autosnippet_get_target_files(targetName)`
|
|
229
229
|
3. Parallel scan → per-file checklist extraction → aggregate / dedup / score
|
|
230
|
-
4. `
|
|
230
|
+
4. `autosnippet_submit_knowledge_batch` batch submit — **all V3 fields are preserved**
|
|
231
231
|
|
|
232
232
|
## Draft File Flow (alternative)
|
|
233
233
|
1. Create draft folder (e.g. `.autosnippet-drafts/`) outside `AutoSnippet/`
|
|
234
234
|
2. Generate one .md per pattern in draft folder
|
|
235
|
-
3. Call `
|
|
235
|
+
3. Call `autosnippet_submit_knowledge_batch` with filePaths and `deleteAfterSubmit: true`
|
|
236
236
|
4. Delete draft folder after submit
|
|
237
237
|
|
|
238
238
|
---
|
|
@@ -247,9 +247,9 @@ Severity: `error` (must fix) | `warning` (should fix) | `info` (suggestion)
|
|
|
247
247
|
| `autosnippet_context_search` | Find similar existing Recipes → fill `relations` |
|
|
248
248
|
| `autosnippet_validate_candidate` | Pre-validate candidate fields |
|
|
249
249
|
| `autosnippet_check_duplicate` | Cosine similarity dedup check |
|
|
250
|
-
| `
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
250
|
+
| `autosnippet_submit_knowledge` | Submit single candidate (**all V3 fields**) |
|
|
251
|
+
| `autosnippet_submit_knowledge_batch` | Batch submit candidates (**all V3 fields preserved**) |
|
|
252
|
+
| `autosnippet_submit_knowledge_batch` | Submit .md draft files as candidates |
|
|
253
253
|
|
|
254
254
|
---
|
|
255
255
|
|
|
@@ -226,7 +226,7 @@ description: Cold-start knowledge base initialization. Full 9-dimension analysis
|
|
|
226
226
|
|
|
227
227
|
## Phase 5: 批量提交
|
|
228
228
|
|
|
229
|
-
将所有分析结果通过 `
|
|
229
|
+
将所有分析结果通过 `autosnippet_submit_knowledge_batch` 批量提交:
|
|
230
230
|
|
|
231
231
|
```json
|
|
232
232
|
{
|
|
@@ -448,17 +448,21 @@ description: Cold-start knowledge base initialization. Full 9-dimension analysis
|
|
|
448
448
|
| Tool | 用途 |
|
|
449
449
|
|------|------|
|
|
450
450
|
| `autosnippet_bootstrap_knowledge` | 启动冷启动扫描(本 Skill 核心工具) |
|
|
451
|
-
| `
|
|
452
|
-
| `
|
|
451
|
+
| `autosnippet_enrich_candidates` | ① 结构补齐:诊断候选字段缺失 |
|
|
452
|
+
| `autosnippet_bootstrap_refine` | ② 内容润色:AI 精炼候选质量(summary/insight/relations) |
|
|
453
|
+
| `autosnippet_submit_knowledge_batch` | 批量提交候选 |
|
|
454
|
+
| `autosnippet_submit_knowledge` | 提交单条候选 |
|
|
453
455
|
| `autosnippet_validate_candidate` | 校验候选字段 |
|
|
454
456
|
| `autosnippet_check_duplicate` | 去重检查 |
|
|
455
457
|
| `autosnippet_context_search` | 查找已有知识(避免重复) |
|
|
456
458
|
| `autosnippet_scan_project` | 轻量探查(不写库) |
|
|
459
|
+
| `autosnippet_list_skills` | 列出可用 Skill 列表 |
|
|
460
|
+
| `autosnippet_load_skill` | 加载指定 Skill 文档获取指引 |
|
|
457
461
|
|
|
458
462
|
## Related Skills
|
|
459
463
|
|
|
460
464
|
- **autosnippet-analysis**: 语义字段补全 + 深度分析(用于增量分析)
|
|
461
|
-
- **autosnippet-candidates**: 完整候选字段模型 +
|
|
465
|
+
- **autosnippet-candidates**: 完整候选字段模型 + V3 Schema
|
|
462
466
|
- **autosnippet-structure**: 项目结构发现 (targets / files / dependencies)
|
|
463
467
|
- **autosnippet-guard**: Guard 规则详情
|
|
464
468
|
- **autosnippet-reference-swift**: Swift 业界最佳实践参考(命名/并发/错误处理/内存/设计模式)
|
|
@@ -87,13 +87,14 @@ This is a conceptual map. Skills stay semantic; MCP provides capability.
|
|
|
87
87
|
| 知识图谱 | `autosnippet_graph_query`, `autosnippet_graph_impact`, `autosnippet_graph_path`, `autosnippet_graph_stats` |
|
|
88
88
|
| 候选预检 | `autosnippet_validate_candidate` |
|
|
89
89
|
| 去重建议 | `autosnippet_check_duplicate` |
|
|
90
|
-
| 候选提交 | `
|
|
90
|
+
| 候选提交 | `autosnippet_submit_knowledge`, `autosnippet_submit_knowledge_batch`, `autosnippet_submit_knowledge_batch` |
|
|
91
91
|
| AI 补全 | `autosnippet_enrich_candidates` |
|
|
92
92
|
| Guard 检查 | `autosnippet_guard_check`, `autosnippet_guard_audit_files` |
|
|
93
93
|
| 合规报告 | `autosnippet_compliance_report`, `autosnippet_recipe_insights` |
|
|
94
94
|
| 使用确认 | `autosnippet_confirm_usage` |
|
|
95
95
|
| 项目扫描 | `autosnippet_scan_project` |
|
|
96
|
-
| 冷启动 | `autosnippet_bootstrap_knowledge` |
|
|
96
|
+
| 冷启动 | `autosnippet_bootstrap_knowledge`, `autosnippet_bootstrap_refine` |
|
|
97
|
+
| Skills 管理 | `autosnippet_list_skills`, `autosnippet_load_skill`, `autosnippet_create_skill`, `autosnippet_update_skill`, `autosnippet_delete_skill`, `autosnippet_suggest_skills` |
|
|
97
98
|
| 自检/能力 | `autosnippet_health`, `autosnippet_capabilities` |
|
|
98
99
|
|
|
99
100
|
### Failure Handling (Examples)
|
|
@@ -336,7 +337,7 @@ When creating or extracting Recipes:
|
|
|
336
337
|
|
|
337
338
|
### Candidate-only Rule (重要)
|
|
338
339
|
|
|
339
|
-
- **If the user asks for candidates**: Extract structured items and submit via MCP **`
|
|
340
|
+
- **If the user asks for candidates**: Extract structured items and submit via MCP **`autosnippet_submit_knowledge_batch`**.
|
|
340
341
|
|
|
341
342
|
---
|
|
342
343
|
|
|
@@ -376,7 +377,7 @@ When `asd ui` is running in the project root, use the HTTP API for on-demand sem
|
|
|
376
377
|
| Capability | Description | Skill |
|
|
377
378
|
|------------|-------------|-------|
|
|
378
379
|
| **Recipe lookup** | Read `references/project-recipes-context.md` 轻量索引,需全文调 MCP `autosnippet_get_recipe(id)` / `autosnippet_context_search`. Recipe over source | autosnippet-recipes |
|
|
379
|
-
| **Create Recipe** | Dashboard New Recipe; or write to `_draft_recipe.md` and watch auto-adds; or MCP `
|
|
380
|
+
| **Create Recipe** | Dashboard New Recipe; or write to `_draft_recipe.md` and watch auto-adds; or MCP `autosnippet_submit_knowledge_batch` | autosnippet-create |
|
|
380
381
|
| **Search & insert** | `ass` shortcut or `// as:search`, `asd search`, Dashboard search | autosnippet-search |
|
|
381
382
|
| **Audit review** | `// as:audit`; watch runs AI review against knowledge base | autosnippet-guard |
|
|
382
383
|
| **Dependency graph** | `AutoSnippet/AutoSnippet.spmmap.json`; `asd spm-map` to update; MCP graph tools for querying | autosnippet-structure |
|
|
@@ -593,8 +594,8 @@ authority: 3
|
|
|
593
594
|
|
|
594
595
|
### How to add new knowledge
|
|
595
596
|
|
|
596
|
-
1. **Single code / single Recipe**: Copy to clipboard → open Dashboard (run `asd ui` if not running) → Use Copied Code, paste, review, save; or write `_draft_recipe.md` and let watch auto-add to Candidates. Or use `
|
|
597
|
-
2. **Multiple drafts (recommended)**: Create a **draft folder** (e.g. `.autosnippet-drafts`), **one .md file per Recipe**—do not put everything in one big file. Call MCP **`
|
|
597
|
+
1. **Single code / single Recipe**: Copy to clipboard → open Dashboard (run `asd ui` if not running) → Use Copied Code, paste, review, save; or write `_draft_recipe.md` and let watch auto-add to Candidates. Or use `autosnippet_submit_knowledge_batch` via MCP.
|
|
598
|
+
2. **Multiple drafts (recommended)**: Create a **draft folder** (e.g. `.autosnippet-drafts`), **one .md file per Recipe**—do not put everything in one big file. Call MCP **`autosnippet_submit_knowledge_batch`** with those file paths to submit to Candidates, then review in Dashboard **Candidates**. **After submit, delete the draft folder** (use `deleteAfterSubmit: true` or `rm -rf .autosnippet-drafts`).
|
|
598
599
|
3. **Intro-only docs**: Recipe candidates can be intro-only (frontmatter + usage guide, no code); after approval they become Recipes and **do not generate a Snippet**—used only for search and Guard context.
|
|
599
600
|
|
|
600
601
|
### How to use knowledge once it’s in the base
|
|
@@ -12,8 +12,8 @@ This skill tells the agent how to **submit module usage code** (that Cursor has
|
|
|
12
12
|
## Instructions for the agent (read this first)
|
|
13
13
|
|
|
14
14
|
1. **Goal**: When you (Cursor) have **finished writing or refining** module usage code, or the user says "把这段提交到 web / 加入知识库", guide them to **submit that code to the Dashboard** so it becomes a **Recipe** in `AutoSnippet/recipes/`.
|
|
15
|
-
2. **Draft workflow**: Prefer **creating a draft folder** (e.g. `.autosnippet-drafts`), **one .md file per Recipe**, multiple draft files—**do not use one big file**. Call MCP **`
|
|
16
|
-
3. **When user asks for "candidates"**: Use MCP **`
|
|
15
|
+
2. **Draft workflow**: Prefer **creating a draft folder** (e.g. `.autosnippet-drafts`), **one .md file per Recipe**, multiple draft files—**do not use one big file**. Call MCP **`autosnippet_submit_knowledge_batch`** with filePaths (the .md files in the draft folder) to submit to Candidates. **After submit, delete the draft folder** (use `deleteAfterSubmit: true` or run `rm -rf .autosnippet-drafts`). Single-item flow can use `_draft_recipe.md` and watch will auto-add to Candidates.
|
|
16
|
+
3. **When user asks for "candidates"**: Use MCP **`autosnippet_submit_knowledge_batch`** for structured items (title/summary/trigger/code/usageGuide); use **`autosnippet_submit_knowledge_batch`** for Markdown draft files (prefer draft folder + multiple files; delete draft folder after submit).
|
|
17
17
|
4. **One Recipe = one scenario**: If you are drafting content, **split** into multiple Recipes by scenario. Never combine multiple usage patterns into one Recipe file or one candidate.
|
|
18
18
|
5. **Recipe candidates can be intro-only**: Intro-only docs (no code block) can be submitted as candidates; after approval they become Recipes and **do not generate a Snippet**—used only for search and Guard context.
|
|
19
19
|
6. **MUST follow standard Recipe format**: Use the complete template from **autosnippet-concepts** skill. Include all required fields: frontmatter with `title`, `trigger`, `category` (one of 8 standard values), `language` (must be `swift` or `objectivec`), `summary_cn`, `summary_en`, `headers` (complete import statements), plus `## Snippet / Code Reference` and `## AI Context / Usage Guide` section.
|
|
@@ -51,11 +51,11 @@ This skill tells the agent how to **submit module usage code** (that Cursor has
|
|
|
51
51
|
```
|
|
52
52
|
- See [templates/recipes-setup/README.md](../../templates/recipes-setup/README.md) for detailed format guide & examples.
|
|
53
53
|
7. **Auto-fill headers from project context**: Before submitting, **check `references/project-recipes-context.md`** (轻量索引) to find similar Recipes by title/trigger/category, then call MCP **`autosnippet_get_recipe(id)`** to get full content including headers. Copy the exact import format for `headers` field. If needed, call MCP **`autosnippet_context_search`** with the module name to find similar Recipes and extract their header patterns. This ensures consistency and correctness.
|
|
54
|
-
8. **Primary flow (MCP preferred)**: Code is ready → Agent writes to `_draft_recipe.md` or calls `
|
|
54
|
+
8. **Primary flow (MCP preferred)**: Code is ready → Agent writes to `_draft_recipe.md` or calls `autosnippet_submit_knowledge_batch` / `autosnippet_submit_knowledge_batch` → candidates appear in Dashboard Candidates → user reviews and approves → Recipe is added to the knowledge base.
|
|
55
55
|
9. **Alternative (Dashboard browser)**: Code is ready → user opens Dashboard (`asd ui` running) → **New Recipe** → **Use Copied Code** (paste the code) → AI fills title/summary/trigger/headers → **user reviews and approves** → saved to knowledge base.
|
|
56
56
|
10. **Alternative (in editor)**: User adds **`// as:create`** in the source file, copies the code, saves → **watch** (from `asd watch` or `asd ui`) auto-adds to Candidates → user opens Dashboard **Candidates** to review and save.
|
|
57
57
|
9. **Draft & clipboard auto-add**: When you write to **`_draft_recipe.md`** (project root) or user uses **`// as:create`** with clipboard content, **watch** automatically reads the draft/clipboard, adds it to **Candidates** (target `_draft` or `_watch`), and shows a **friendly prompt** (e.g. "已创建候选「xxx」,请在 Candidates 页审核" in notification and console). User only needs to open Dashboard **Candidates** to review and save — no manual copy-paste required.
|
|
58
|
-
10. **Multiple recipes**: Prefer **one .md file per Recipe** in a draft folder (e.g. `.autosnippet-drafts/`), call **`
|
|
58
|
+
10. **Multiple recipes**: Prefer **one .md file per Recipe** in a draft folder (e.g. `.autosnippet-drafts/`), call **`autosnippet_submit_knowledge_batch`** with the list of file paths, then **delete the draft folder** after submit. Do not use one big file for many Recipes.
|
|
59
59
|
11. **Project root** = directory with `AutoSnippet/AutoSnippet.boxspec.json`. All commands run from the project root.
|
|
60
60
|
|
|
61
61
|
---
|
|
@@ -68,7 +68,7 @@ This skill tells the agent how to **submit module usage code** (that Cursor has
|
|
|
68
68
|
|
|
69
69
|
- **Code scenario**: Usage code is in current file or clipboard. If not copied, prompt user to copy the code block you provide.
|
|
70
70
|
...rated a full Recipe (frontmatter, Snippet, Usage Guide), **prefer writing to draft file** `_draft_recipe.md` at project root. On save, **watch automatically reads the draft**, adds it to **Candidates** (target `_draft`), and shows a **friendly prompt** ("已创建候选「xxx」,请在 Candidates 页审核"). User opens Dashboard **Candidates** to review and save — no manual copy needed. Or output in copyable format in chat and guide user to copy → Dashboard → Use Copied Code → paste → review → save. **Do not write to `AutoSnippet/recipes/` or `AutoSnippet/snippets/`.**
|
|
71
|
-
- **Candidate output rule**: When the user asks for candidates, **do not create files under `AutoSnippet/`**. Use **`
|
|
71
|
+
- **Candidate output rule**: When the user asks for candidates, **do not create files under `AutoSnippet/`**. Use **`autosnippet_submit_knowledge_batch`** for structured items; use **`autosnippet_submit_knowledge_batch`** for draft .md files (prefer draft folder + multiple files; delete draft folder after submit).
|
|
72
72
|
|
|
73
73
|
### Step 2: Open the web (Dashboard) in browser
|
|
74
74
|
|
|
@@ -78,7 +78,7 @@ This skill tells the agent how to **submit module usage code** (that Cursor has
|
|
|
78
78
|
### Step 3: Submit via Dashboard
|
|
79
79
|
|
|
80
80
|
1. **Browser**: Run terminal command `open "http://localhost:3000/?action=create&source=clipboard"` (macOS) to open the browser.
|
|
81
|
-
2. **Draft file (preferred for Agent)**: Write full Recipe MD to `_draft_recipe.md` at project root → watch auto-adds to Candidates. Or call MCP **`
|
|
81
|
+
2. **Draft file (preferred for Agent)**: Write full Recipe MD to `_draft_recipe.md` at project root → watch auto-adds to Candidates. Or call MCP **`autosnippet_submit_knowledge_batch`** with draft file paths.
|
|
82
82
|
3. **Manual fallback**: User opens **`http://localhost:3000`** in browser → **New Recipe** → **Use Copied Code** → paste.
|
|
83
83
|
3. Pasted code: **Full Recipe MD** (with `---` frontmatter, `## Snippet / Code Reference`, `## AI Context / Usage Guide`) is parsed directly, **no AI rewrite**. Plain code still goes through AI analysis and fill.
|
|
84
84
|
4. **User reviews and approves** — 人工审核 title/summary/category/trigger 及内容,确认无误后再保存。
|
|
@@ -92,7 +92,7 @@ This skill tells the agent how to **submit module usage code** (that Cursor has
|
|
|
92
92
|
|
|
93
93
|
## Alternative: Copy then jump to Web (Xcode and Cursor)
|
|
94
94
|
|
|
95
|
-
**Option A — MCP Submit (Cursor 首选)**: After user confirms code, Agent calls **`
|
|
95
|
+
**Option A — MCP Submit (Cursor 首选)**: After user confirms code, Agent calls **`autosnippet_submit_knowledge_batch`** (for .md drafts) or **`autosnippet_submit_knowledge_batch`** (for structured items) to submit directly to Candidates. User reviews in Dashboard.
|
|
96
96
|
|
|
97
97
|
**Option B — Browser (Dashboard)**: Run `open "http://localhost:3000/?action=create&source=clipboard"` to open Dashboard New Recipe page; page reads clipboard and fills.
|
|
98
98
|
|
|
@@ -148,9 +148,9 @@ Watch parses all such blocks and adds each as a separate candidate; prompt may s
|
|
|
148
148
|
|
|
149
149
|
| User / Cursor situation | Action |
|
|
150
150
|
|-------------------------|--------|
|
|
151
|
-
| "把这段提交到 web / 加入知识库" (code just written) | 1) 提示用户复制代码;2) 写入 `_draft_recipe.md` 或调用 **`
|
|
151
|
+
| "把这段提交到 web / 加入知识库" (code just written) | 1) 提示用户复制代码;2) 写入 `_draft_recipe.md` 或调用 **`autosnippet_submit_knowledge_batch`**;3) 若需 Dashboard,运行 `open "http://localhost:3000/?action=create&source=clipboard"`;4) 用户粘贴并保存。 |
|
|
152
152
|
| Agent 起草了 Recipe/Snippet 内容 | **Prefer**: Write to `_draft_recipe.md` (project root) → save → **watch 自动读取并加入候选池**,并给出友好提示 → 用户打开 Dashboard **Candidates** 审核并保存。无需手动复制。 |
|
|
153
|
-
| Code in current file, want to submit from editor | **MCP**:`
|
|
153
|
+
| Code in current file, want to submit from editor | **MCP**:`autosnippet_submit_knowledge_batch`(写草稿 .md 后提交)。或 Add **`// as:create`**, copy, save;确保 **`asd watch`** / **`asd ui`** 运行;有剪贴板时自动加入候选并友好提示。 |
|
|
154
154
|
| Code already in a file (path known) | 打开 **`http://localhost:3000`** → New Recipe → enter path → **Scan File** → review → save. |
|
|
155
155
|
| Agent 起草内容无法完整复制 | Write to `_draft_recipe.md` → save → **watch 自动读取草稿、加入候选并友好提示** → 用户打开 **Candidates** 审核保存。 |
|
|
156
156
|
| Batch from Target | **`asd ais <Target>`** → 打开 **`http://localhost:3000`** → **Candidates** → approve. |
|
|
@@ -162,13 +162,13 @@ Watch parses all such blocks and adds each as a separate candidate; prompt may s
|
|
|
162
162
|
| Tool | Use |
|
|
163
163
|
|------|-----|
|
|
164
164
|
| `autosnippet_context_search` | On-demand semantic search of knowledge base; pass `query`, `limit?` |
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
165
|
+
| `autosnippet_submit_knowledge_batch` | Submit draft .md as candidates: prefer draft folder + multiple files (not one big file); supports intro-only docs (no code—no Snippet). Pass `filePaths`, optional `targetName`, `deleteAfterSubmit`. **Delete the draft folder after submit** (e.g. `deleteAfterSubmit: true` or `rm -rf .autosnippet-drafts`). |
|
|
166
|
+
| `autosnippet_submit_knowledge_batch` | Submit structured items (title, summary, trigger, language, code, usageGuide) for batch scan, etc. |
|
|
167
|
+
| `autosnippet_submit_knowledge` | Submit single structured candidate with full V3 fields. |
|
|
168
168
|
| `autosnippet_validate_candidate` | Pre-validate candidate quality before submission. |
|
|
169
169
|
| `autosnippet_check_duplicate` | Check for duplicate Recipes before submission. |
|
|
170
170
|
|
|
171
|
-
**Fallback when Dashboard not open**: Agent can always use `
|
|
171
|
+
**Fallback when Dashboard not open**: Agent can always use `autosnippet_submit_knowledge_batch` or `autosnippet_submit_knowledge_batch` directly via MCP — no browser needed.
|
|
172
172
|
|
|
173
173
|
---
|
|
174
174
|
|
|
@@ -42,10 +42,11 @@ Use this skill when the user's intent is unclear or overlaps multiple capabiliti
|
|
|
42
42
|
- Insights: `autosnippet_recipe_insights`, `autosnippet_compliance_report`
|
|
43
43
|
- Graph: `autosnippet_graph_query`, `autosnippet_graph_impact`, `autosnippet_graph_path`, `autosnippet_graph_stats`
|
|
44
44
|
- Structure: `autosnippet_get_targets`, `autosnippet_get_target_files`, `autosnippet_get_target_metadata`
|
|
45
|
-
- Candidates: `autosnippet_validate_candidate`, `autosnippet_check_duplicate`, `
|
|
45
|
+
- Candidates: `autosnippet_validate_candidate`, `autosnippet_check_duplicate`, `autosnippet_submit_knowledge`, `autosnippet_submit_knowledge_batch`, `autosnippet_submit_knowledge_batch`, `autosnippet_enrich_candidates`
|
|
46
46
|
- Guard: `autosnippet_guard_check`, `autosnippet_guard_audit_files`, `autosnippet_scan_project`
|
|
47
47
|
- Telemetry: `autosnippet_confirm_usage`
|
|
48
|
-
- Bootstrap: `autosnippet_bootstrap_knowledge`
|
|
48
|
+
- Bootstrap: `autosnippet_bootstrap_knowledge`, `autosnippet_bootstrap_refine`
|
|
49
|
+
- Skills: `autosnippet_list_skills`, `autosnippet_load_skill`, `autosnippet_create_skill`, `autosnippet_update_skill`, `autosnippet_delete_skill`, `autosnippet_suggest_skills`
|
|
49
50
|
|
|
50
51
|
This skill is a router only; it does not perform actions itself.
|
|
51
52
|
|