sumulige-claude 1.0.6 → 1.0.8

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 (53) hide show
  1. package/.claude/.kickoff-hint.txt +51 -0
  2. package/.claude/ANCHORS.md +40 -0
  3. package/.claude/MEMORY.md +34 -0
  4. package/.claude/PROJECT_LOG.md +101 -0
  5. package/.claude/THINKING_CHAIN_GUIDE.md +287 -0
  6. package/.claude/commands/commit-push-pr.md +59 -0
  7. package/.claude/commands/commit.md +53 -0
  8. package/.claude/commands/pr.md +76 -0
  9. package/.claude/commands/review.md +61 -0
  10. package/.claude/commands/sessions.md +62 -0
  11. package/.claude/commands/skill-create.md +131 -0
  12. package/.claude/commands/test.md +56 -0
  13. package/.claude/commands/todos.md +99 -0
  14. package/.claude/commands/verify-work.md +63 -0
  15. package/.claude/hooks/code-formatter.cjs +187 -0
  16. package/.claude/hooks/code-tracer.cjs +331 -0
  17. package/.claude/hooks/conversation-recorder.cjs +340 -0
  18. package/.claude/hooks/decision-tracker.cjs +398 -0
  19. package/.claude/hooks/export.cjs +329 -0
  20. package/.claude/hooks/multi-session.cjs +181 -0
  21. package/.claude/hooks/privacy-filter.js +224 -0
  22. package/.claude/hooks/project-kickoff.cjs +114 -0
  23. package/.claude/hooks/rag-skill-loader.cjs +159 -0
  24. package/.claude/hooks/session-end.sh +61 -0
  25. package/.claude/hooks/sync-to-log.sh +83 -0
  26. package/.claude/hooks/thinking-silent.cjs +145 -0
  27. package/.claude/hooks/tl-summary.sh +54 -0
  28. package/.claude/hooks/todo-manager.cjs +248 -0
  29. package/.claude/hooks/verify-work.cjs +134 -0
  30. package/.claude/sessions/active-sessions.json +359 -0
  31. package/.claude/settings.local.json +43 -2
  32. package/.claude/thinking-routes/.last-sync +1 -0
  33. package/.claude/thinking-routes/QUICKREF.md +98 -0
  34. package/.claude-plugin/marketplace.json +71 -0
  35. package/.github/workflows/sync-skills.yml +74 -0
  36. package/AGENTS.md +81 -22
  37. package/DEV_TOOLS_GUIDE.md +190 -0
  38. package/PROJECT_STRUCTURE.md +10 -1
  39. package/README.md +142 -708
  40. package/cli.js +116 -822
  41. package/config/defaults.json +34 -0
  42. package/config/skill-categories.json +40 -0
  43. package/development/todos/INDEX.md +14 -58
  44. package/docs/DEVELOPMENT.md +423 -0
  45. package/docs/MARKETPLACE.md +352 -0
  46. package/lib/commands.js +698 -0
  47. package/lib/config.js +71 -0
  48. package/lib/marketplace.js +486 -0
  49. package/lib/utils.js +62 -0
  50. package/package.json +11 -5
  51. package/scripts/sync-external.mjs +298 -0
  52. package/scripts/update-registry.mjs +325 -0
  53. package/sources.yaml +83 -0
@@ -0,0 +1,398 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Decision Tracker - 决策识别与追踪
4
+ *
5
+ * 功能:
6
+ * - AI 自动识别对话中的决策
7
+ * - 记录到 DECISIONS.md
8
+ * - 按主题分类
9
+ * - 双向链接决策 ↔ 对话 ↔ 代码
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
16
+ const DECISIONS_DIR = path.join(PROJECT_DIR, '.claude', 'decisions');
17
+ const DECISIONS_FILE = path.join(DECISIONS_DIR, 'DECISIONS.md');
18
+ const TOPICS_DIR = path.join(DECISIONS_DIR, 'by-topic');
19
+ const TRANSCRIPTS_DIR = path.join(PROJECT_DIR, '.claude', 'transcripts');
20
+
21
+ // 决策关键词模式
22
+ const DECISION_KEYWORDS = [
23
+ // 中文关键词
24
+ '决定', '选择', '采用', '确定', '最终', '使用', '实现',
25
+ '设计', '架构', '方案', '策略', '计划', '优先级',
26
+ '不使用', '放弃', '排除', '拒绝',
27
+ // 英文关键词
28
+ 'decided', 'chose', 'selected', 'using', 'implementing',
29
+ 'design', 'architecture', 'approach', 'strategy',
30
+ 'not using', 'rejected', 'excluded'
31
+ ];
32
+
33
+ // 决策起始短语
34
+ const DECISION_PHRASES = [
35
+ /我决定/i, /我们决定/i, /最终决定/i, /经过考虑/i,
36
+ /let'?s use/i, /we will/i, /going to/i, /decided to/i,
37
+ /选择(?:了)?(?:使用|采用)?/i, /采用(?:了)?/i,
38
+ /将使用/i, /会使用/i, /计划使用/i
39
+ ];
40
+
41
+ /**
42
+ * 分析文本,提取可能的决策
43
+ */
44
+ function extractDecisions(text) {
45
+ const decisions = [];
46
+ const sentences = text.split(/[。!?.!?]+/).filter(s => s.trim().length > 10);
47
+
48
+ sentences.forEach(sentence => {
49
+ // 检查是否包含决策短语
50
+ let isDecision = false;
51
+ for (const phrase of DECISION_PHRASES) {
52
+ if (phrase.test(sentence)) {
53
+ isDecision = true;
54
+ break;
55
+ }
56
+ }
57
+
58
+ // 检查是否包含决策关键词
59
+ if (!isDecision) {
60
+ const keywordCount = DECISION_KEYWORDS.filter(kw => sentence.includes(kw)).length;
61
+ if (keywordCount >= 2) {
62
+ isDecision = true;
63
+ }
64
+ }
65
+
66
+ if (isDecision) {
67
+ decisions.push({
68
+ text: sentence.trim(),
69
+ confidence: 'medium'
70
+ });
71
+ }
72
+ });
73
+
74
+ return decisions;
75
+ }
76
+
77
+ /**
78
+ * 提取主题标签
79
+ */
80
+ function extractTopics(text) {
81
+ const topics = new Set();
82
+
83
+ // 技术主题
84
+ const techTopics = [
85
+ 'api', 'database', 'auth', 'frontend', 'backend',
86
+ 'architecture', 'design', 'security', 'performance',
87
+ 'testing', 'deployment', 'storage', 'cache',
88
+ 'api', 'database', 'auth', 'frontend', 'backend',
89
+ '架构', '数据库', '认证', '前端', '后端',
90
+ '设计', '安全', '性能', '测试', '部署',
91
+ '存储', '缓存', '网络', '日志'
92
+ ];
93
+
94
+ techTopics.forEach(topic => {
95
+ if (text.toLowerCase().includes(topic)) {
96
+ topics.add(topic);
97
+ }
98
+ });
99
+
100
+ return Array.from(topics);
101
+ }
102
+
103
+ /**
104
+ * 获取下一个决策 ID
105
+ */
106
+ function getNextDecisionId() {
107
+ try {
108
+ const content = fs.readFileSync(DECISIONS_FILE, 'utf-8');
109
+ const matches = content.match(/\[D(\d+)\]/g);
110
+ if (matches) {
111
+ const maxId = Math.max(...matches.map(m => parseInt(m.slice(2, -1))));
112
+ return `D${String(maxId + 1).padStart(3, '0')}`;
113
+ }
114
+ } catch (e) {}
115
+ return 'D001';
116
+ }
117
+
118
+ /**
119
+ * 获取时间戳
120
+ */
121
+ function getTimestamp() {
122
+ return new Date().toISOString().replace('T', ' ').substring(0, 16);
123
+ }
124
+
125
+ /**
126
+ * 获取今日 transcript 路径
127
+ */
128
+ function getTodayTranscriptPath() {
129
+ const now = new Date();
130
+ const year = now.getFullYear();
131
+ const month = String(now.getMonth() + 1).padStart(2, '0');
132
+ const day = String(now.getDate()).padStart(2, '0');
133
+ return path.join(TRANSCRIPTS_DIR, String(year), month, `${day}.md`);
134
+ }
135
+
136
+ /**
137
+ * 记录决策
138
+ */
139
+ function recordDecision(title, details) {
140
+ // 确保目录存在
141
+ try { fs.mkdirSync(DECISIONS_DIR, { recursive: true }); } catch (e) {}
142
+ try { fs.mkdirSync(TOPICS_DIR, { recursive: true }); } catch (e) {}
143
+
144
+ const decisionId = getNextDecisionId();
145
+ const timestamp = getTimestamp();
146
+ const todayPath = getTodayTranscriptPath();
147
+
148
+ let section = `\n## [${decisionId}] ${timestamp} - ${title}\n\n`;
149
+
150
+ if (details.reason) {
151
+ section += `### 💡 理由\n${details.reason}\n\n`;
152
+ }
153
+
154
+ if (details.content) {
155
+ section += `### 📌 决策内容\n${details.content}\n\n`;
156
+ }
157
+
158
+ if (details.links && Object.keys(details.links).length > 0) {
159
+ section += `### 🔗 关联\n`;
160
+ if (details.links.conversation) {
161
+ section += `- 对话: \`${details.links.conversation}\`\n`;
162
+ }
163
+ if (details.links.files && details.links.files.length > 0) {
164
+ section += `- 代码: ${details.links.files.map(f => `\`${f}\``).join(', ')}\n`;
165
+ }
166
+ if (details.links.commit) {
167
+ section += `- Commit: \`${details.links.commit}\`\n`;
168
+ }
169
+ section += '\n';
170
+ }
171
+
172
+ if (details.tags && details.tags.length > 0) {
173
+ section += `### 🏷️ 主题\n`;
174
+ details.tags.forEach(tag => {
175
+ section += `- \`${tag}\`\n`;
176
+ });
177
+ section += '\n';
178
+ }
179
+
180
+ // 追加到 DECISIONS.md
181
+ if (!fs.existsSync(DECISIONS_FILE)) {
182
+ fs.writeFileSync(DECISIONS_FILE, `# Decisions Log\n\n> 所有项目决策的完整记录\n\n`, 'utf-8');
183
+ }
184
+ fs.appendFileSync(DECISIONS_FILE, section, 'utf-8');
185
+
186
+ // 添加到主题文件
187
+ if (details.tags && details.tags.length > 0) {
188
+ details.tags.forEach(tag => {
189
+ const topicPath = path.join(TOPICS_DIR, `${tag}.md`);
190
+ const relativePath = path.relative(path.dirname(topicPath), DECISIONS_FILE);
191
+
192
+ if (!fs.existsSync(topicPath)) {
193
+ fs.writeFileSync(topicPath, `# ${tag}\n\n相关的决策记录\n\n`, 'utf-8');
194
+ }
195
+
196
+ const entry = `- [${timestamp}] [${decisionId}](${relativePath}#${decisionId}) - ${title}\n`;
197
+ fs.appendFileSync(topicPath, entry, 'utf-8');
198
+ });
199
+ }
200
+
201
+ return decisionId;
202
+ }
203
+
204
+ /**
205
+ * 从对话中自动提取并记录决策
206
+ */
207
+ function extractAndRecordDecisions(conversationText) {
208
+ const decisions = extractDecisions(conversationText);
209
+
210
+ if (decisions.length === 0) {
211
+ return [];
212
+ }
213
+
214
+ const recorded = [];
215
+ const topics = extractTopics(conversationText);
216
+
217
+ decisions.forEach((decision, index) => {
218
+ const title = decision.text.substring(0, 50) + (decision.text.length > 50 ? '...' : '');
219
+ const id = recordDecision(title, {
220
+ content: decision.text,
221
+ reason: '自动识别',
222
+ tags: topics,
223
+ links: {
224
+ conversation: getTodayTranscriptPath()
225
+ }
226
+ });
227
+ recorded.push({ id, title, confidence: decision.confidence });
228
+ });
229
+
230
+ return recorded;
231
+ }
232
+
233
+ /**
234
+ * 查看所有决策
235
+ */
236
+ function listDecisions(filter = null) {
237
+ if (!fs.existsSync(DECISIONS_FILE)) {
238
+ console.log('📭 暂无决策记录');
239
+ return [];
240
+ }
241
+
242
+ const content = fs.readFileSync(DECISIONS_FILE, 'utf-8');
243
+ const decisionBlocks = content.split(/^## /m).filter(s => s.trim());
244
+
245
+ if (filter) {
246
+ // 过滤决策
247
+ const filtered = decisionBlocks.filter(block =>
248
+ block.toLowerCase().includes(filter.toLowerCase())
249
+ );
250
+ console.log(`\n📋 找到 ${filtered.length} 个匹配 "${filter}" 的决策:\n`);
251
+ filtered.forEach(block => {
252
+ const lines = block.split('\n');
253
+ console.log(`\n${lines[0]}`);
254
+ });
255
+ return filtered;
256
+ } else {
257
+ console.log(`\n📋 所有决策 (${decisionBlocks.length} 个):\n`);
258
+ decisionBlocks.forEach(block => {
259
+ const lines = block.split('\n');
260
+ console.log(`${lines[0]}`);
261
+ });
262
+ return decisionBlocks;
263
+ }
264
+ }
265
+
266
+ /**
267
+ * 搜索决策
268
+ */
269
+ function searchDecisions(keyword) {
270
+ if (!fs.existsSync(DECISIONS_FILE)) {
271
+ console.log('📭 暂无决策记录');
272
+ return;
273
+ }
274
+
275
+ const content = fs.readFileSync(DECISIONS_FILE, 'utf-8');
276
+ const lines = content.split('\n');
277
+
278
+ console.log(`\n🔍 搜索 "${keyword}":\n`);
279
+
280
+ let found = false;
281
+ lines.forEach((line, index) => {
282
+ if (line.toLowerCase().includes(keyword.toLowerCase())) {
283
+ // 获取上下文
284
+ const start = Math.max(0, index - 2);
285
+ const end = Math.min(lines.length, index + 3);
286
+ const context = lines.slice(start, end).join('\n');
287
+ console.log(context);
288
+ console.log('---');
289
+ found = true;
290
+ }
291
+ });
292
+
293
+ if (!found) {
294
+ console.log('未找到匹配结果');
295
+ }
296
+ }
297
+
298
+ // CLI
299
+ function main() {
300
+ const args = process.argv.slice(2);
301
+ const command = args[0];
302
+
303
+ switch (command) {
304
+ case 'add': {
305
+ // 手动添加决策
306
+ // node decision-tracker.cjs add "标题" "内容" "tag1,tag2"
307
+ const title = args[1] || '';
308
+ const content = args[2] || '';
309
+ const tags = args[3] ? args[3].split(',') : [];
310
+
311
+ if (!title) {
312
+ console.error('用法: node decision-tracker.cjs add "标题" "内容" "tag1,tag2"');
313
+ process.exit(1);
314
+ }
315
+
316
+ const id = recordDecision(title, { content, tags });
317
+ console.log(`✅ 已记录决策 ${id}: ${title}`);
318
+ break;
319
+ }
320
+
321
+ case 'list': {
322
+ const filter = args[1];
323
+ listDecisions(filter);
324
+ break;
325
+ }
326
+
327
+ case 'search': {
328
+ const keyword = args[1];
329
+ if (!keyword) {
330
+ console.error('用法: node decision-tracker.cjs search "关键词"');
331
+ process.exit(1);
332
+ }
333
+ searchDecisions(keyword);
334
+ break;
335
+ }
336
+
337
+ case 'topics': {
338
+ // 列出所有主题
339
+ if (fs.existsSync(TOPICS_DIR)) {
340
+ const topics = fs.readdirSync(TOPICS_DIR).filter(f => f.endsWith('.md'));
341
+ console.log('\n🏷️ 主题分类:\n');
342
+ topics.forEach(t => {
343
+ const content = fs.readFileSync(path.join(TOPICS_DIR, t), 'utf-8');
344
+ const count = (content.match(/^- /gm) || []).length;
345
+ console.log(` - ${t.replace('.md', '')} (${count} 个决策)`);
346
+ });
347
+ } else {
348
+ console.log('📭 暂无主题分类');
349
+ }
350
+ break;
351
+ }
352
+
353
+ case 'extract': {
354
+ // 从文本中提取决策
355
+ const text = args.slice(1).join(' ') || '';
356
+ if (!text) {
357
+ console.error('用法: node decision-tracker.cjs extract "文本内容"');
358
+ process.exit(1);
359
+ }
360
+
361
+ const decisions = extractAndRecordDecisions(text);
362
+ console.log(`✅ 从文本中提取并记录了 ${decisions.length} 个决策`);
363
+ decisions.forEach(d => {
364
+ console.log(` - ${d.id}: ${d.title}`);
365
+ });
366
+ break;
367
+ }
368
+
369
+ default:
370
+ console.log(`
371
+ Decision Tracker - 决策追踪工具
372
+
373
+ 用法:
374
+ node decision-tracker.cjs add "标题" "内容" "tag1,tag2" 手动添加决策
375
+ node decision-tracker.cjs list [filter] 列出所有决策
376
+ node decision-tracker.cjs search "关键词" 搜索决策
377
+ node decision-tracker.cjs topics 列出所有主题
378
+ node decision-tracker.cjs extract "文本" 从文本中提取决策
379
+
380
+ 快捷命令:
381
+ alias dadd='node .claude/hooks/decision-tracker.cjs add'
382
+ alias dlist='node .claude/hooks/decision-tracker.cjs list'
383
+ alias dsearch='node .claude/hooks/decision-tracker.cjs search'
384
+ `);
385
+ }
386
+ }
387
+
388
+ module.exports = {
389
+ extractDecisions,
390
+ recordDecision,
391
+ extractAndRecordDecisions,
392
+ listDecisions,
393
+ searchDecisions
394
+ };
395
+
396
+ if (require.main === module) {
397
+ main();
398
+ }