agent-configs 1.0.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.
Files changed (85) hide show
  1. package/README.md +223 -0
  2. package/agents/architect.md +211 -0
  3. package/agents/code-reviewer.md +104 -0
  4. package/agents/planner.md +119 -0
  5. package/agents/refactor-cleaner.md +306 -0
  6. package/agents/security-reviewer.md +545 -0
  7. package/agents/tdd-guide.md +280 -0
  8. package/bundles/bk-chat-bundle/README.md +48 -0
  9. package/bundles/bk-chat-bundle/manifest.json +10 -0
  10. package/bundles/continuous-learning/.claude/commands/evolve.md +190 -0
  11. package/bundles/continuous-learning/.claude/commands/instinct-status.md +64 -0
  12. package/bundles/continuous-learning/.claude/commands/learn.md +83 -0
  13. package/bundles/continuous-learning/.claude/hooks/learning-end.js +85 -0
  14. package/bundles/continuous-learning/.claude/hooks/observe.js +131 -0
  15. package/bundles/continuous-learning/.claude/lib/learning.js +559 -0
  16. package/bundles/continuous-learning/.claude/lib/utils.js +312 -0
  17. package/bundles/continuous-learning/.claude/skills/continuous-learning/SKILL.md +200 -0
  18. package/bundles/continuous-learning/.cursor/hooks/learning-end.js +102 -0
  19. package/bundles/continuous-learning/.cursor/rules/continuous-learning.mdc +34 -0
  20. package/bundles/continuous-learning/.cursor/skills/continuous-learning/SKILL.md +77 -0
  21. package/bundles/continuous-learning/README.md +159 -0
  22. package/bundles/continuous-learning/manifest.json +51 -0
  23. package/bundles/planning-bundle/README.md +34 -0
  24. package/bundles/planning-bundle/manifest.json +10 -0
  25. package/bundles/review-bundle/README.md +43 -0
  26. package/bundles/review-bundle/manifest.json +11 -0
  27. package/bundles/shared-memory/.claude/commands/list-sessions.md +124 -0
  28. package/bundles/shared-memory/.claude/commands/load-session.md +169 -0
  29. package/bundles/shared-memory/.claude/commands/save-session.md +137 -0
  30. package/bundles/shared-memory/.claude/hooks/memory-compact.js +43 -0
  31. package/bundles/shared-memory/.claude/hooks/memory-end.js +42 -0
  32. package/bundles/shared-memory/.claude/hooks/memory-start.js +59 -0
  33. package/bundles/shared-memory/.claude/lib/memory.js +416 -0
  34. package/bundles/shared-memory/.claude/lib/utils.js +209 -0
  35. package/bundles/shared-memory/.claude/skills/shared-memory/SKILL.md +183 -0
  36. package/bundles/shared-memory/.cursor/hooks/memory-start.js +42 -0
  37. package/bundles/shared-memory/.cursor/rules/shared-memory.mdc +37 -0
  38. package/bundles/shared-memory/.cursor/skills/shared-memory/SKILL.md +183 -0
  39. package/bundles/tdd-bundle/README.md +33 -0
  40. package/bundles/tdd-bundle/manifest.json +10 -0
  41. package/cli.js +978 -0
  42. package/commands/build-fix.md +29 -0
  43. package/commands/code-review.md +40 -0
  44. package/commands/e2e.md +363 -0
  45. package/commands/learn.md +114 -0
  46. package/commands/plan.md +113 -0
  47. package/commands/refactor-clean.md +28 -0
  48. package/commands/tdd.md +326 -0
  49. package/commands/test-coverage.md +27 -0
  50. package/commands/update-codemaps.md +17 -0
  51. package/commands/update-docs.md +31 -0
  52. package/configs.json +158 -0
  53. package/hooks/hooks.json +101 -0
  54. package/package.json +58 -0
  55. package/rules/agents.md +49 -0
  56. package/rules/coding-style.md +70 -0
  57. package/rules/git-workflow.md +45 -0
  58. package/rules/hooks.md +46 -0
  59. package/rules/patterns.md +55 -0
  60. package/rules/performance.md +47 -0
  61. package/rules/security.md +36 -0
  62. package/rules/testing.md +30 -0
  63. package/skills/ai-config-architect/SKILL.md +59 -0
  64. package/skills/ai-config-architect/references/agents.md +77 -0
  65. package/skills/ai-config-architect/references/commands.md +66 -0
  66. package/skills/ai-config-architect/references/hooks.md +70 -0
  67. package/skills/ai-config-architect/references/patterns.md +66 -0
  68. package/skills/ai-config-architect/references/platforms.md +82 -0
  69. package/skills/ai-config-architect/references/rules.md +66 -0
  70. package/skills/ai-config-architect/references/skills.md +67 -0
  71. package/skills/bk-chat-helper/SKILL.md +398 -0
  72. package/skills/bk-chat-helper/references/api-reference.md +606 -0
  73. package/skills/bk-chat-helper/references/examples.md +789 -0
  74. package/skills/bk-chat-helper/references/integration-guide.md +583 -0
  75. package/skills/bk-chat-x/SKILL.md +400 -0
  76. package/skills/bk-chat-x/references/components-api.md +340 -0
  77. package/skills/bk-chat-x/references/examples.md +386 -0
  78. package/skills/bk-chat-x/references/shortcuts-guide.md +375 -0
  79. package/skills/coding-standards/SKILL.md +523 -0
  80. package/skills/security-review/SKILL.md +497 -0
  81. package/skills/security-review/references/cloud-infrastructure-security.md +361 -0
  82. package/skills/strategic-compact/SKILL.md +66 -0
  83. package/skills/strategic-compact/scripts/suggest-compact.sh +52 -0
  84. package/skills/tdd-workflow/SKILL.md +412 -0
  85. package/skills/verification-loop/SKILL.md +128 -0
@@ -0,0 +1,559 @@
1
+ /**
2
+ * Continuous Learning - 核心学习模块
3
+ *
4
+ * 提供 patterns/skills/instincts 的存储、检索、管理功能
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const {
10
+ ensureDir,
11
+ findFiles,
12
+ readFile,
13
+ writeFile,
14
+ appendJsonl,
15
+ readJsonl,
16
+ getFileSizeMB,
17
+ getDateString,
18
+ getTimestamp,
19
+ getWorkspaceRoot,
20
+ getHomeDir,
21
+ expandPath,
22
+ toSafeFilename
23
+ } = require('./utils');
24
+
25
+ // ============== 默认配置 ==============
26
+
27
+ const DEFAULT_CONFIG = {
28
+ // v1 配置 - 简单版 (Stop hook)
29
+ v1: {
30
+ min_session_length: 10,
31
+ extraction_threshold: 'medium',
32
+ auto_approve: false,
33
+ learned_skills_path: '~/.claude/skills/learned/',
34
+ patterns_to_detect: [
35
+ 'error_resolution',
36
+ 'user_corrections',
37
+ 'workarounds',
38
+ 'debugging_techniques',
39
+ 'project_specific'
40
+ ],
41
+ ignore_patterns: [
42
+ 'simple_typos',
43
+ 'one_time_fixes',
44
+ 'external_api_issues'
45
+ ]
46
+ },
47
+
48
+ // v2 配置 - 高级版 (PreToolUse/PostToolUse hooks)
49
+ v2: {
50
+ observation: {
51
+ enabled: true,
52
+ store_path: '~/.claude/homunculus/observations.jsonl',
53
+ max_file_size_mb: 10,
54
+ archive_after_days: 7,
55
+ capture_tools: ['Edit', 'Write', 'Bash', 'Read', 'Grep', 'Glob'],
56
+ ignore_tools: ['TodoWrite']
57
+ },
58
+ instincts: {
59
+ personal_path: '~/.claude/homunculus/instincts/personal/',
60
+ inherited_path: '~/.claude/homunculus/instincts/inherited/',
61
+ min_confidence: 0.3,
62
+ auto_approve_threshold: 0.7,
63
+ confidence_decay_rate: 0.02,
64
+ max_instincts: 100
65
+ },
66
+ evolution: {
67
+ cluster_threshold: 3,
68
+ evolved_path: '~/.claude/homunculus/evolved/',
69
+ auto_evolve: false
70
+ }
71
+ }
72
+ };
73
+
74
+ // ============== 路径管理 ==============
75
+
76
+ /**
77
+ * 获取 learned skills 目录
78
+ */
79
+ function getLearnedSkillsDir(config = DEFAULT_CONFIG.v1) {
80
+ return expandPath(config.learned_skills_path);
81
+ }
82
+
83
+ /**
84
+ * 获取 homunculus 根目录 (v2)
85
+ */
86
+ function getHomunculusDir() {
87
+ return expandPath('~/.claude/homunculus');
88
+ }
89
+
90
+ /**
91
+ * 获取 observations 文件路径 (v2)
92
+ */
93
+ function getObservationsPath(config = DEFAULT_CONFIG.v2) {
94
+ return expandPath(config.observation.store_path);
95
+ }
96
+
97
+ /**
98
+ * 获取 instincts 目录 (v2)
99
+ */
100
+ function getInstinctsDir(type = 'personal', config = DEFAULT_CONFIG.v2) {
101
+ if (type === 'inherited') {
102
+ return expandPath(config.instincts.inherited_path);
103
+ }
104
+ return expandPath(config.instincts.personal_path);
105
+ }
106
+
107
+ /**
108
+ * 获取 evolved 目录 (v2)
109
+ */
110
+ function getEvolvedDir(type, config = DEFAULT_CONFIG.v2) {
111
+ const base = expandPath(config.evolution.evolved_path);
112
+ if (type) {
113
+ return path.join(base, type);
114
+ }
115
+ return base;
116
+ }
117
+
118
+ /**
119
+ * 确保所有学习目录存在
120
+ */
121
+ function ensureLearningDirs(config = DEFAULT_CONFIG) {
122
+ // v1 目录
123
+ ensureDir(getLearnedSkillsDir(config.v1));
124
+
125
+ // v2 目录
126
+ ensureDir(getHomunculusDir());
127
+ ensureDir(getInstinctsDir('personal', config.v2));
128
+ ensureDir(getInstinctsDir('inherited', config.v2));
129
+ ensureDir(getEvolvedDir('skills', config.v2));
130
+ ensureDir(getEvolvedDir('commands', config.v2));
131
+ ensureDir(getEvolvedDir('agents', config.v2));
132
+ ensureDir(path.dirname(getObservationsPath(config.v2)));
133
+ }
134
+
135
+ // ============== Learned Skills (v1) ==============
136
+
137
+ /**
138
+ * 生成 learned skill 文件名
139
+ */
140
+ function generateSkillFilename(name) {
141
+ return `${toSafeFilename(name)}.md`;
142
+ }
143
+
144
+ /**
145
+ * 生成 learned skill 内容
146
+ */
147
+ function generateSkillContent(data) {
148
+ const {
149
+ name,
150
+ context = '',
151
+ problem = '',
152
+ solution = '',
153
+ example = '',
154
+ triggers = []
155
+ } = data;
156
+
157
+ const date = getDateString();
158
+
159
+ return `# ${name}
160
+
161
+ **Extracted:** ${date}
162
+ **Context:** ${context}
163
+
164
+ ## Problem
165
+ ${problem}
166
+
167
+ ## Solution
168
+ ${solution}
169
+
170
+ ## Example
171
+ ${example || '(No example provided)'}
172
+
173
+ ## When to Use
174
+ ${triggers.length > 0 ? triggers.map(t => `- ${t}`).join('\n') : '(Trigger conditions not specified)'}
175
+ `;
176
+ }
177
+
178
+ /**
179
+ * 保存 learned skill
180
+ */
181
+ function saveLearnedSkill(data, config = DEFAULT_CONFIG.v1) {
182
+ try {
183
+ const skillsDir = getLearnedSkillsDir(config);
184
+ ensureDir(skillsDir);
185
+
186
+ const filename = generateSkillFilename(data.name);
187
+ const filePath = path.join(skillsDir, filename);
188
+ const content = generateSkillContent(data);
189
+
190
+ writeFile(filePath, content);
191
+
192
+ return {
193
+ success: true,
194
+ path: filePath,
195
+ filename
196
+ };
197
+ } catch (err) {
198
+ return {
199
+ success: false,
200
+ error: err.message
201
+ };
202
+ }
203
+ }
204
+
205
+ /**
206
+ * 列出所有 learned skills
207
+ */
208
+ function listLearnedSkills(config = DEFAULT_CONFIG.v1) {
209
+ const skillsDir = getLearnedSkillsDir(config);
210
+ const files = findFiles(skillsDir, '*.md');
211
+
212
+ return files.map(file => {
213
+ const content = readFile(file.path);
214
+ const nameMatch = content?.match(/^#\s+(.+)$/m);
215
+ const contextMatch = content?.match(/\*\*Context:\*\*\s*(.+)$/m);
216
+
217
+ return {
218
+ path: file.path,
219
+ filename: path.basename(file.path),
220
+ name: nameMatch ? nameMatch[1] : path.basename(file.path, '.md'),
221
+ context: contextMatch ? contextMatch[1] : '',
222
+ mtime: file.mtime
223
+ };
224
+ });
225
+ }
226
+
227
+ // ============== Observations (v2) ==============
228
+
229
+ /**
230
+ * 记录观察
231
+ */
232
+ function recordObservation(data, config = DEFAULT_CONFIG.v2) {
233
+ const obsPath = getObservationsPath(config);
234
+
235
+ // 检查文件大小,必要时归档
236
+ const sizeMB = getFileSizeMB(obsPath);
237
+ if (sizeMB >= config.observation.max_file_size_mb) {
238
+ archiveObservations(config);
239
+ }
240
+
241
+ const observation = {
242
+ timestamp: getTimestamp(),
243
+ ...data
244
+ };
245
+
246
+ appendJsonl(obsPath, observation);
247
+ return observation;
248
+ }
249
+
250
+ /**
251
+ * 归档旧的 observations
252
+ */
253
+ function archiveObservations(config = DEFAULT_CONFIG.v2) {
254
+ const obsPath = getObservationsPath(config);
255
+ if (!fs.existsSync(obsPath)) return;
256
+
257
+ const archiveDir = path.join(getHomunculusDir(), 'observations.archive');
258
+ ensureDir(archiveDir);
259
+
260
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
261
+ const archivePath = path.join(archiveDir, `observations-${timestamp}.jsonl`);
262
+
263
+ fs.renameSync(obsPath, archivePath);
264
+ }
265
+
266
+ /**
267
+ * 读取近期 observations
268
+ */
269
+ function getRecentObservations(limit = 100, config = DEFAULT_CONFIG.v2) {
270
+ const obsPath = getObservationsPath(config);
271
+ const observations = readJsonl(obsPath);
272
+
273
+ return observations.slice(-limit);
274
+ }
275
+
276
+ // ============== Instincts (v2) ==============
277
+
278
+ /**
279
+ * 生成 instinct 文件名
280
+ */
281
+ function generateInstinctFilename(id) {
282
+ return `${toSafeFilename(id)}.md`;
283
+ }
284
+
285
+ /**
286
+ * 生成 instinct 内容
287
+ */
288
+ function generateInstinctContent(data) {
289
+ const {
290
+ id,
291
+ trigger = '',
292
+ confidence = 0.5,
293
+ domain = 'general',
294
+ source = 'session-observation',
295
+ action = '',
296
+ evidence = []
297
+ } = data;
298
+
299
+ return `---
300
+ id: ${id}
301
+ trigger: "${trigger}"
302
+ confidence: ${confidence}
303
+ domain: "${domain}"
304
+ source: "${source}"
305
+ ---
306
+
307
+ # ${id.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')}
308
+
309
+ ## Action
310
+ ${action}
311
+
312
+ ## Evidence
313
+ ${evidence.length > 0 ? evidence.map(e => `- ${e}`).join('\n') : '- Initial observation'}
314
+ `;
315
+ }
316
+
317
+ /**
318
+ * 保存 instinct
319
+ */
320
+ function saveInstinct(data, config = DEFAULT_CONFIG.v2) {
321
+ try {
322
+ const instinctsDir = getInstinctsDir('personal', config);
323
+ ensureDir(instinctsDir);
324
+
325
+ const filename = generateInstinctFilename(data.id);
326
+ const filePath = path.join(instinctsDir, filename);
327
+ const content = generateInstinctContent(data);
328
+
329
+ writeFile(filePath, content);
330
+
331
+ return {
332
+ success: true,
333
+ path: filePath,
334
+ filename
335
+ };
336
+ } catch (err) {
337
+ return {
338
+ success: false,
339
+ error: err.message
340
+ };
341
+ }
342
+ }
343
+
344
+ /**
345
+ * 解析 instinct 文件
346
+ */
347
+ function parseInstinctFile(filePath) {
348
+ const content = readFile(filePath);
349
+ if (!content) return null;
350
+
351
+ const instinct = {
352
+ path: filePath,
353
+ filename: path.basename(filePath)
354
+ };
355
+
356
+ // 解析 frontmatter
357
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
358
+ if (frontmatterMatch) {
359
+ const frontmatter = frontmatterMatch[1];
360
+
361
+ const idMatch = frontmatter.match(/^id:\s*(.+)$/m);
362
+ const triggerMatch = frontmatter.match(/^trigger:\s*"?(.+?)"?$/m);
363
+ const confidenceMatch = frontmatter.match(/^confidence:\s*(.+)$/m);
364
+ const domainMatch = frontmatter.match(/^domain:\s*"?(.+?)"?$/m);
365
+ const sourceMatch = frontmatter.match(/^source:\s*"?(.+?)"?$/m);
366
+
367
+ if (idMatch) instinct.id = idMatch[1];
368
+ if (triggerMatch) instinct.trigger = triggerMatch[1];
369
+ if (confidenceMatch) instinct.confidence = parseFloat(confidenceMatch[1]);
370
+ if (domainMatch) instinct.domain = domainMatch[1];
371
+ if (sourceMatch) instinct.source = sourceMatch[1];
372
+ }
373
+
374
+ // 解析 action
375
+ const actionMatch = content.match(/## Action\n([\s\S]*?)(?=\n## |$)/);
376
+ if (actionMatch) {
377
+ instinct.action = actionMatch[1].trim();
378
+ }
379
+
380
+ // 解析 evidence
381
+ const evidenceMatch = content.match(/## Evidence\n([\s\S]*?)(?=\n## |$)/);
382
+ if (evidenceMatch) {
383
+ instinct.evidence = evidenceMatch[1]
384
+ .split('\n')
385
+ .filter(l => l.startsWith('- '))
386
+ .map(l => l.slice(2).trim());
387
+ }
388
+
389
+ return instinct;
390
+ }
391
+
392
+ /**
393
+ * 列出所有 instincts
394
+ */
395
+ function listInstincts(config = DEFAULT_CONFIG.v2) {
396
+ const personalDir = getInstinctsDir('personal', config);
397
+ const inheritedDir = getInstinctsDir('inherited', config);
398
+
399
+ const personal = findFiles(personalDir, '*.md').map(f => ({
400
+ ...parseInstinctFile(f.path),
401
+ type: 'personal',
402
+ mtime: f.mtime
403
+ }));
404
+
405
+ const inherited = findFiles(inheritedDir, '*.md').map(f => ({
406
+ ...parseInstinctFile(f.path),
407
+ type: 'inherited',
408
+ mtime: f.mtime
409
+ }));
410
+
411
+ return [...personal, ...inherited].filter(Boolean);
412
+ }
413
+
414
+ /**
415
+ * 更新 instinct 置信度
416
+ */
417
+ function updateInstinctConfidence(id, delta, config = DEFAULT_CONFIG.v2) {
418
+ const instinctsDir = getInstinctsDir('personal', config);
419
+ const filePath = path.join(instinctsDir, generateInstinctFilename(id));
420
+
421
+ const instinct = parseInstinctFile(filePath);
422
+ if (!instinct) return null;
423
+
424
+ const newConfidence = Math.max(0, Math.min(1, instinct.confidence + delta));
425
+ instinct.confidence = newConfidence;
426
+
427
+ const content = generateInstinctContent(instinct);
428
+ writeFile(filePath, content);
429
+
430
+ return instinct;
431
+ }
432
+
433
+ // ============== Evolution (v2) ==============
434
+
435
+ /**
436
+ * 按 domain 分组 instincts
437
+ */
438
+ function groupInstinctsByDomain(instincts) {
439
+ const groups = {};
440
+
441
+ for (const instinct of instincts) {
442
+ const domain = instinct.domain || 'general';
443
+ if (!groups[domain]) {
444
+ groups[domain] = [];
445
+ }
446
+ groups[domain].push(instinct);
447
+ }
448
+
449
+ return groups;
450
+ }
451
+
452
+ /**
453
+ * 查找可进化的 instinct 集群
454
+ */
455
+ function findEvolvableClusters(instincts, config = DEFAULT_CONFIG.v2) {
456
+ const threshold = config.evolution.cluster_threshold;
457
+ const groups = groupInstinctsByDomain(instincts);
458
+ const clusters = [];
459
+
460
+ for (const [domain, domainInstincts] of Object.entries(groups)) {
461
+ if (domainInstincts.length >= threshold) {
462
+ // 计算平均置信度
463
+ const avgConfidence = domainInstincts.reduce((sum, i) => sum + (i.confidence || 0.5), 0) / domainInstincts.length;
464
+
465
+ // 确定进化类型
466
+ let evolutionType = 'skill';
467
+ const triggers = domainInstincts.map(i => i.trigger || '').join(' ');
468
+
469
+ if (triggers.includes('user asks') || triggers.includes('when creating')) {
470
+ evolutionType = 'command';
471
+ } else if (domainInstincts.length >= 4 && avgConfidence >= 0.7) {
472
+ evolutionType = 'agent';
473
+ }
474
+
475
+ clusters.push({
476
+ domain,
477
+ instincts: domainInstincts,
478
+ count: domainInstincts.length,
479
+ avgConfidence,
480
+ evolutionType,
481
+ suggestedName: `${domain}-${evolutionType}`
482
+ });
483
+ }
484
+ }
485
+
486
+ return clusters;
487
+ }
488
+
489
+ // ============== 会话评估 ==============
490
+
491
+ /**
492
+ * 检查会话是否值得评估
493
+ */
494
+ function shouldEvaluateSession(messageCount, config = DEFAULT_CONFIG.v1) {
495
+ return messageCount >= config.min_session_length;
496
+ }
497
+
498
+ /**
499
+ * 获取学习状态摘要
500
+ */
501
+ function getLearningStatus(config = DEFAULT_CONFIG) {
502
+ const learnedSkills = listLearnedSkills(config.v1);
503
+ const instincts = listInstincts(config.v2);
504
+ const observations = getRecentObservations(100, config.v2);
505
+ const clusters = findEvolvableClusters(instincts, config.v2);
506
+
507
+ return {
508
+ v1: {
509
+ learnedSkillsCount: learnedSkills.length,
510
+ skills: learnedSkills
511
+ },
512
+ v2: {
513
+ instinctsCount: instincts.length,
514
+ instincts,
515
+ recentObservationsCount: observations.length,
516
+ evolvableClusters: clusters
517
+ }
518
+ };
519
+ }
520
+
521
+ module.exports = {
522
+ // 配置
523
+ DEFAULT_CONFIG,
524
+
525
+ // 路径
526
+ getLearnedSkillsDir,
527
+ getHomunculusDir,
528
+ getObservationsPath,
529
+ getInstinctsDir,
530
+ getEvolvedDir,
531
+ ensureLearningDirs,
532
+
533
+ // Learned Skills (v1)
534
+ generateSkillFilename,
535
+ generateSkillContent,
536
+ saveLearnedSkill,
537
+ listLearnedSkills,
538
+
539
+ // Observations (v2)
540
+ recordObservation,
541
+ archiveObservations,
542
+ getRecentObservations,
543
+
544
+ // Instincts (v2)
545
+ generateInstinctFilename,
546
+ generateInstinctContent,
547
+ saveInstinct,
548
+ parseInstinctFile,
549
+ listInstincts,
550
+ updateInstinctConfidence,
551
+
552
+ // Evolution (v2)
553
+ groupInstinctsByDomain,
554
+ findEvolvableClusters,
555
+
556
+ // 评估
557
+ shouldEvaluateSession,
558
+ getLearningStatus
559
+ };