sumulige-claude 1.0.11 → 1.1.1

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 (40) hide show
  1. package/.claude/commands/todos.md +41 -6
  2. package/.claude/hooks/pre-commit.cjs +86 -0
  3. package/.claude/hooks/pre-push.cjs +103 -0
  4. package/.claude/hooks/session-restore.cjs +102 -0
  5. package/.claude/hooks/session-save.cjs +164 -0
  6. package/.claude/hooks/todo-manager.cjs +262 -141
  7. package/.claude/quality-gate.json +61 -0
  8. package/.claude/settings.local.json +12 -1
  9. package/.claude/skills/api-tester/SKILL.md +52 -23
  10. package/.claude/skills/test-workflow/SKILL.md +191 -0
  11. package/.claude/templates/tasks/develop.md +69 -0
  12. package/.claude/templates/tasks/research.md +64 -0
  13. package/.claude/templates/tasks/test.md +96 -0
  14. package/.claude-plugin/marketplace.json +2 -2
  15. package/.versionrc +25 -0
  16. package/AGENTS.md +7 -1
  17. package/CHANGELOG.md +83 -4
  18. package/PROJECT_STRUCTURE.md +40 -3
  19. package/Q&A.md +184 -0
  20. package/README.md +52 -2
  21. package/cli.js +102 -5
  22. package/config/official-skills.json +183 -0
  23. package/config/quality-gate.json +61 -0
  24. package/development/todos/.state.json +4 -0
  25. package/development/todos/INDEX.md +64 -38
  26. package/docs/RELEASE.md +93 -0
  27. package/lib/commands.js +1865 -39
  28. package/lib/config-manager.js +441 -0
  29. package/lib/config-schema.js +408 -0
  30. package/lib/config-validator.js +330 -0
  31. package/lib/config.js +52 -1
  32. package/lib/errors.js +305 -0
  33. package/lib/quality-gate.js +431 -0
  34. package/lib/quality-rules.js +373 -0
  35. package/lib/utils.js +102 -14
  36. package/lib/version-check.js +169 -0
  37. package/package.json +11 -2
  38. package/template/.claude/hooks/project-kickoff.cjs +190 -1
  39. package/template/.claude/hooks/session-restore.cjs +102 -0
  40. package/template/.claude/hooks/session-save.cjs +164 -0
@@ -1,20 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * TODO Manager - AI 自动任务管理系统
3
+ * TODO Manager - AI 自动任务管理系统 (v2.0)
4
4
  *
5
5
  * 功能:
6
- * - 自动追踪项目任务
7
- * - 生成可点击的任务索引
6
+ * - 支持 Research → Develop → Test 生命周期
7
+ * - 自动任务状态流转
8
+ * - 智能任务创建建议
8
9
  * - 维护任务状态流转
9
- * - 静默运行,不打扰工作流
10
10
  *
11
- * 目录结构:
12
- * development/todos/
13
- * ├── INDEX.md # 任务总览
14
- * ├── active/ # 进行中的任务
15
- * ├── completed/ # 已完成的任务
16
- * ├── backlog/ # 待办任务
17
- * └── archived/ # 已归档任务
11
+ * 生命周期:
12
+ * Research (研究) → Develop (开发) → Test (测试) → Done (完成)
18
13
  */
19
14
 
20
15
  const fs = require('fs');
@@ -25,55 +20,81 @@ const TODOS_DIR = path.join(PROJECT_DIR, 'development', 'todos');
25
20
  const INDEX_FILE = path.join(TODOS_DIR, 'INDEX.md');
26
21
  const STATE_FILE = path.join(TODOS_DIR, '.state.json');
27
22
 
28
- // 任务状态
29
- const STATUS = {
23
+ // 任务类型和状态
24
+ const TASK_TYPES = {
25
+ RESEARCH: 'research',
26
+ DEVELOP: 'develop',
27
+ TEST: 'test'
28
+ };
29
+
30
+ const TASK_STAGES = {
30
31
  ACTIVE: 'active',
31
32
  COMPLETED: 'completed',
32
33
  BACKLOG: 'backlog',
33
34
  ARCHIVED: 'archived'
34
35
  };
35
36
 
37
+ // 图标映射
38
+ const ICONS = {
39
+ research: '📊',
40
+ develop: '💻',
41
+ test: '🧪'
42
+ };
43
+
36
44
  // 确保目录存在
37
45
  function ensureDirectories() {
38
- [TODOS_DIR, STATUS.ACTIVE, STATUS.COMPLETED, STATUS.BACKLOG, STATUS.ARCHIVED].forEach(dir => {
39
- const fullPath = dir.startsWith('/') ? dir : path.join(TODOS_DIR, dir);
40
- try { fs.mkdirSync(fullPath, { recursive: true }); } catch (e) {}
46
+ const dirs = [TODOS_DIR];
47
+
48
+ // 为每个阶段创建类型子目录
49
+ for (const stage of Object.values(TASK_STAGES)) {
50
+ dirs.push(path.join(TODOS_DIR, stage));
51
+ for (const type of Object.values(TASK_TYPES)) {
52
+ dirs.push(path.join(TODOS_DIR, stage, type));
53
+ }
54
+ }
55
+
56
+ dirs.forEach(dir => {
57
+ try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}
41
58
  });
42
59
  }
43
60
 
44
61
  // 扫描任务文件
45
62
  function scanTasks() {
46
63
  const tasks = {
47
- active: [],
48
- completed: [],
49
- backlog: [],
50
- archived: []
64
+ active: { research: [], develop: [], test: [] },
65
+ completed: { research: [], develop: [], test: [] },
66
+ backlog: { research: [], develop: [], test: [] },
67
+ archived: { research: [], develop: [], test: [] }
51
68
  };
52
69
 
53
- for (const [key, dirName] of Object.entries(STATUS)) {
54
- const dir = path.join(TODOS_DIR, dirName);
55
- if (!fs.existsSync(dir)) continue;
56
-
57
- const files = fs.readdirSync(dir)
58
- .filter(f => f.endsWith('.md') && f !== '_README.md');
59
-
60
- tasks[dirName] = files.map(f => {
61
- const filePath = path.join(dir, f);
62
- const content = fs.readFileSync(filePath, 'utf-8');
63
- const titleMatch = content.match(/^#\s+(.+)$/m);
64
- const statusMatch = content.match(/\*\*状态\*\*:\s*([\u{1F300}-\u{1F9FF}\s]+)/u);
65
- const priorityMatch = content.match(/\*\*优先级\*\*:\s*(P[0-3])/);
66
- const branchMatch = content.match(/\*\*分支\*\*:\s*`([^`]+)`/);
67
-
68
- return {
69
- file: f,
70
- title: titleMatch ? titleMatch[1] : path.basename(f, '.md'),
71
- status: statusMatch ? statusMatch[1].trim() : '🚧 进行中',
72
- priority: priorityMatch ? priorityMatch[1] : 'P2',
73
- branch: branchMatch ? branchMatch[1] : null,
74
- path: `${dirName}/${f}`
75
- };
76
- });
70
+ for (const [stage, types] of Object.entries(tasks)) {
71
+ for (const [type, _] of Object.entries(types)) {
72
+ const dir = path.join(TODOS_DIR, stage, type);
73
+ if (!fs.existsSync(dir)) continue;
74
+
75
+ const files = fs.readdirSync(dir)
76
+ .filter(f => f.endsWith('.md') && f !== '_README.md');
77
+
78
+ tasks[stage][type] = files.map(f => {
79
+ const filePath = path.join(dir, f);
80
+ const content = fs.readFileSync(filePath, 'utf-8');
81
+ const titleMatch = content.match(/^#\s+(.+)$/m);
82
+ const statusMatch = content.match(/\*\*状态\*\*:\s*([✅🚧📋])/);
83
+ const priorityMatch = content.match(/\*\*优先级\*\*:\s*(P[0-3])/);
84
+ const typeMatch = content.match(/\*\*类型\*\*:\s*([📊💻🧪])\s*(\w+)/);
85
+
86
+ return {
87
+ file: f,
88
+ title: titleMatch ? titleMatch[1] : path.basename(f, '.md'),
89
+ status: statusMatch ? statusMatch[1] : '🚧',
90
+ priority: priorityMatch ? priorityMatch[1] : 'P2',
91
+ taskType: typeMatch ? typeMatch[1] : type,
92
+ icon: typeMatch ? typeMatch[2] : ICONS[type] || '📄',
93
+ path: `${stage}/${type}/${f}`,
94
+ stage: stage
95
+ };
96
+ });
97
+ }
77
98
  }
78
99
 
79
100
  return tasks;
@@ -83,138 +104,211 @@ function scanTasks() {
83
104
  function generateIndex(tasks) {
84
105
  const now = new Date().toISOString().split('T')[0];
85
106
 
107
+ // 计算总数
108
+ const activeCount = tasks.active.research.length + tasks.active.develop.length + tasks.active.test.length;
109
+ const completedCount = tasks.completed.research.length + tasks.completed.develop.length + tasks.completed.test.length;
110
+ const backlogCount = tasks.backlog.research.length + tasks.backlog.develop.length + tasks.backlog.test.length;
111
+
86
112
  let md = `# 项目任务追踪系统
87
113
 
88
- > 本目录由 AI 自动维护,记录项目开发任务和进度
114
+ > **统一管理**: 研究 → 开发 → 测试
115
+ > **最后更新**: ${now}
116
+
117
+ @version: 2.0.0
118
+
119
+ ---
120
+
121
+ ## 📊 项目进度
122
+
123
+ | 阶段 | 进度 | 状态 |
124
+ |------|------|------|
125
+ | Phase 1: MVP 智能监控 | 80% | 🚧 进行中 |
126
+ | Phase 2: V1.5 动态调整 | 0% | 📋 待规划 |
127
+ | Phase 3: V2.0 AI 教练 | 0% | 📋 待规划 |
128
+
129
+ ---
89
130
 
90
- **最后更新**: ${now}
131
+ ## 🔄 任务生命周期
91
132
 
92
- @version: 1.0.0
133
+ \`\`\`
134
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
135
+ │ RESEARCH │ → │ DEVELOP │ → │ TEST │
136
+ │ 📊 研究 │ │ 💻 开发 │ │ 🧪 测试 │
137
+ └─────────────┘ └─────────────┘ └─────────────┘
138
+ \`\`\`
93
139
 
94
- ## 目录结构
140
+ ---
141
+
142
+ ## 📁 目录结构
95
143
 
96
144
  \`\`\`
97
145
  development/todos/
98
146
  ├── INDEX.md # 本文件 - 任务总览
99
- ├── active/ # 进行中的任务 (${tasks.active.length})
100
- ├── completed/ # 已完成的任务 (${tasks.completed.length})
101
- ├── backlog/ # 待规划的任务 (${tasks.backlog.length})
102
- └── archived/ # 已归档的任务 (${tasks.archived.length})
147
+ ├── _templates/ # 任务模板
148
+ ├── active/ # 进行中的任务 (${activeCount})
149
+ ├── research/ # 📊 研究中 (${tasks.active.research.length})
150
+ │ ├── develop/ # 💻 开发中 (${tasks.active.develop.length})
151
+ │ └── test/ # 🧪 测试中 (${tasks.active.test.length})
152
+ ├── completed/ # 已完成的任务 (${completedCount})
153
+ │ ├── research/
154
+ │ ├── develop/
155
+ │ └── test/
156
+ ├── backlog/ # 待规划的任务 (${backlogCount})
157
+ └── archived/ # 已归档的任务
103
158
  \`\`\`
104
159
 
105
- ## 快速跳转
160
+ ---
161
+
162
+ ## 🚧 当前进行中的任务
106
163
 
164
+ ### 📊 研究任务
107
165
  `;
108
166
 
109
- // 进行中的任务
110
- md += `## 🚧 进行中的任务 (${tasks.active.length})\n\n`;
111
- if (tasks.active.length > 0) {
112
- tasks.active.forEach(t => {
113
- md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}${t.branch ? ` \`branch: ${t.branch}\`` : ''}\n`;
167
+ // 研究任务
168
+ if (tasks.active.research.length > 0) {
169
+ tasks.active.research.forEach(t => {
170
+ md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}\n`;
114
171
  });
115
172
  } else {
116
- md += `*暂无进行中的任务*\n`;
173
+ md += `暂无\n`;
117
174
  }
118
- md += `\n`;
119
-
120
- // 最近完成的任务(最多5个)
121
- md += `## 最近完成的任务\n\n`;
122
- const recentCompleted = tasks.completed.slice(0, 5);
123
- if (recentCompleted.length > 0) {
124
- recentCompleted.forEach(t => {
125
- md += `- [${t.title}](./${t.path})\n`;
175
+ md += `\n### 💻 开发任务\n`;
176
+
177
+ // 开发任务
178
+ if (tasks.active.develop.length > 0) {
179
+ tasks.active.develop.forEach(t => {
180
+ md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}\n`;
126
181
  });
127
- if (tasks.completed.length > 5) {
128
- md += `- ...还有 ${tasks.completed.length - 5} 个已完成任务\n`;
129
- }
130
182
  } else {
131
- md += `*暂无已完成的任务*\n`;
183
+ md += `暂无\n`;
132
184
  }
133
- md += `\n`;
185
+ md += `\n### 🧪 测试任务\n`;
134
186
 
135
- // 待办任务
136
- md += `## 📋 待办任务 (${tasks.backlog.length})\n\n`;
137
- if (tasks.backlog.length > 0) {
138
- tasks.backlog.slice(0, 10).forEach(t => {
139
- md += `- [${t.priority}] [${t.title}](./${t.path})\n`;
187
+ // 测试任务
188
+ if (tasks.active.test.length > 0) {
189
+ tasks.active.test.forEach(t => {
190
+ md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}\n`;
191
+ });
192
+ } else {
193
+ md += `暂无\n`;
194
+ }
195
+
196
+ md += `\n---\n\n## ✅ 最近完成的任务\n\n### 💻 开发任务\n`;
197
+
198
+ // 最近完成的开发任务
199
+ if (tasks.completed.develop.length > 0) {
200
+ tasks.completed.develop.slice(0, 5).forEach(t => {
201
+ md += `- [${t.title}](./${t.path}) ${t.status}\n`;
140
202
  });
141
- if (tasks.backlog.length > 10) {
142
- md += `- ...还有 ${tasks.backlog.length - 10} 个待办任务\n`;
143
- }
144
203
  } else {
145
- md += `*暂无待办任务*\n`;
204
+ md += `暂无\n`;
146
205
  }
147
- md += `\n`;
148
-
149
- // 全部目录链接
150
- md += `## 全部目录\n\n`;
151
- md += `- [🚧 所有进行中的任务](./active/) - 当前开发重点\n`;
152
- md += `- [✅ 所有已完成的任务](./completed/) - 完整历史\n`;
153
- md += `- [📋 所有待办任务](./backlog/) - 待规划\n`;
154
- md += `- [📦 所有已归档任务](./archived/) - 历史记录\n`;
155
- md += `\n`;
156
-
157
- // 使用说明
158
- md += `## 使用方式\n\n`;
159
- md += `### 查看任务\n`;
160
- md += `点击上方链接跳转到对应目录,或使用:\n`;
161
- md += `\`\`\`bash\n`;
162
- md += `# 查看进行中的任务\n`;
163
- md += `cat development/todos/active/*.md\n\n`;
164
- md += `# 查看特定任务\n`;
165
- md += `cat development/todos/active/feature-name.md\n`;
206
+
207
+ md += `\n### 🧪 测试任务\n`;
208
+
209
+ // 最近完成的测试任务
210
+ if (tasks.completed.test.length > 0) {
211
+ tasks.completed.test.slice(0, 3).forEach(t => {
212
+ md += `- [${t.title}](./${t.path}) ${t.status}\n`;
213
+ });
214
+ } else {
215
+ md += `暂无\n`;
216
+ }
217
+
218
+ md += `\n---\n\n## 📋 待办任务\n\n`;
219
+ md += `暂无\n`;
220
+
221
+ md += `\n---\n\n## 🎯 使用方式\n\n`;
222
+ md += `### 查看任务\n\`\`\`bash\n`;
223
+ md += `# 按类型查看\n`;
224
+ md += `ls development/todos/active/research/ # 研究任务\n`;
225
+ md += `ls development/todos/active/develop/ # 开发任务\n`;
226
+ md += `ls development/todos/active/test/ # 测试任务\n`;
166
227
  md += `\`\`\`\n\n`;
228
+
167
229
  md += `### 创建新任务\n`;
168
- md += `在 Claude Code 中:\n`;
169
- md += `\`\`\`\n`;
170
- md += `创建一个新任务:实现用户登录功能\n`;
171
- md += `\`\`\`\n\n`;
172
- md += `AI 会自动在 \`active/\` 目录创建对应的任务文件。\n\n`;
173
- md += `### 更新任务状态\n`;
174
- md += `\`\`\`\n`;
175
- md += `将 [任务名] 标记为完成\n`;
176
- md += `\`\`\`\n\n`;
177
- md += `AI 会自动将任务移动到 \`completed/\` 目录。\n\n`;
230
+ md += `在 Claude Code 中:\n\`\`\`\n`;
231
+ md += `创建一个新任务:\n`;
232
+ md += `- 类型:测试\n`;
233
+ md += `- 标题:Dashboard 功能测试\n\`\`\`\n\n`;
178
234
 
179
- md += `---\n\n`;
180
- md += `> **维护说明**: 本系统由 AI 自动维护,请勿手动编辑(除非你知道自己在做什么)\n`;
235
+ md += `### 更新任务状态\n\`\`\`\n`;
236
+ md += `将 [任务名] 标记为完成\n\`\`\`\n\n`;
237
+
238
+ md += `---\n\n> **维护说明**: 本系统由 AI 自动维护\n`;
181
239
 
182
240
  return md;
183
241
  }
184
242
 
243
+ // 加载和保存状态
244
+ function loadState() {
245
+ if (fs.existsSync(STATE_FILE)) {
246
+ try {
247
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
248
+ } catch (e) {
249
+ return { tasks: {}, transitions: [] };
250
+ }
251
+ }
252
+ return { tasks: {}, transitions: [] };
253
+ }
254
+
255
+ function saveState(state) {
256
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
257
+ }
258
+
259
+ // 检查是否需要自动流转
260
+ function checkAutoTransition(tasks, state) {
261
+ const suggestions = [];
262
+
263
+ // 检查刚完成的开发任务,建议创建测试任务
264
+ const completedDevelop = tasks.completed.develop.filter(t => {
265
+ const key = `completed_develop_${t.file}`;
266
+ return !state.tasks[key]; // 首次完成
267
+ });
268
+
269
+ completedDevelop.forEach(t => {
270
+ const testTaskName = t.file.replace('.md', '-test.md');
271
+ const testPath = path.join(TODOS_DIR, 'active', 'test', testTaskName);
272
+
273
+ if (!fs.existsSync(testPath)) {
274
+ suggestions.push({
275
+ type: 'create_test',
276
+ message: `💡 建议为 "${t.title}" 创建测试任务`,
277
+ developTask: t,
278
+ testTask: testTaskName,
279
+ template: `_templates/test.md`
280
+ });
281
+ }
282
+
283
+ // 标记已处理
284
+ const key = `completed_develop_${t.file}`;
285
+ state.tasks[key] = { completed: true, notified: true };
286
+ });
287
+
288
+ return { suggestions, state };
289
+ }
290
+
185
291
  // 更新索引
186
292
  function updateIndex() {
187
293
  try {
188
294
  ensureDirectories();
189
295
  const tasks = scanTasks();
190
- const index = generateIndex(tasks);
296
+ const state = loadState();
191
297
 
192
- // 检查是否需要更新 - 比较任务总数
193
- let needsUpdate = true;
194
- if (fs.existsSync(INDEX_FILE)) {
195
- const existing = fs.readFileSync(INDEX_FILE, 'utf-8');
196
- // 从现有索引中提取任务数量
197
- const activeMatch = existing.match(/## 🚧 进行中的任务 \((\d+)\)/);
198
- const completedMatch = existing.match(/## ✅ 最近完成的任务/);
199
- const existingActive = activeMatch ? parseInt(activeMatch[1], 10) : 0;
200
- const newActive = tasks.active.length;
201
-
202
- // 如果活跃任务数量相同且没有完成任务内容变化,则不更新
203
- if (existingActive === newActive && tasks.completed.length === 0) {
204
- // 检查现有索引是否已有完成任务
205
- const hasCompletedInExisting = existing.includes('[completed/') || existing.includes('./completed/');
206
- const hasCompletedNow = tasks.completed.length > 0;
207
- needsUpdate = hasCompletedInExisting !== hasCompletedNow;
208
- }
209
- }
298
+ // 检查自动流转
299
+ const { suggestions, state: newState } = checkAutoTransition(tasks, state);
210
300
 
211
- if (needsUpdate) {
212
- fs.writeFileSync(INDEX_FILE, index);
213
- }
301
+ // 生成索引
302
+ const index = generateIndex(tasks);
303
+ fs.writeFileSync(INDEX_FILE, index);
214
304
 
215
- return { tasks, updated: needsUpdate };
305
+ // 保存状态
306
+ saveState(newState);
307
+
308
+ return { tasks, suggestions, updated: true };
216
309
  } catch (e) {
217
- return { tasks: { active: [], completed: [], backlog: [], archived: [] }, updated: false };
310
+ console.error('[TODO Manager] Error:', e.message);
311
+ return { tasks: { active: { research: [], develop: [], test: [] }, completed: { research: [], develop: [], test: [] } }, suggestions: [], updated: false };
218
312
  }
219
313
  }
220
314
 
@@ -222,13 +316,28 @@ function updateIndex() {
222
316
  function main() {
223
317
  const result = updateIndex();
224
318
 
225
- // 在 AgentStop 或特定事件时输出摘要
319
+ // 输出建议
320
+ if (result.suggestions && result.suggestions.length > 0) {
321
+ console.log('\n📋 [任务流转] 检测到 ' + result.suggestions.length + ' 个自动流转建议:\n');
322
+ result.suggestions.forEach((s, i) => {
323
+ console.log(` ${i + 1}. ${s.message}`);
324
+ });
325
+ console.log('');
326
+ }
327
+
328
+ // 在 AgentStop 时输出摘要
226
329
  const eventType = process.env.CLAUDE_EVENT_TYPE || '';
227
330
  if (eventType === 'AgentStop') {
228
- const { active, completed } = result.tasks;
229
- if (active.length > 0) {
230
- console.log(`\n📋 [任务追踪] ${active.length} 个进行中, ${completed.length} 个已完成`);
231
- console.log(` 查看: development/todos/INDEX.md\n`);
331
+ const active = result.tasks.active;
332
+ const activeTotal = active.research.length + active.develop.length + active.test.length;
333
+ const completed = result.tasks.completed;
334
+ const completedTotal = completed.research.length + completed.develop.length + completed.test.length;
335
+
336
+ if (activeTotal > 0 || completedTotal > 0) {
337
+ console.log(`\n📋 [任务追踪]`);
338
+ console.log(` 进行中: ${activeTotal} 个 (📊 ${active.research.length} | 💻 ${active.develop.length} | 🧪 ${active.test.length})`);
339
+ console.log(` 已完成: ${completedTotal} 个`);
340
+ console.log(` 查看: ${path.relative(PROJECT_DIR, INDEX_FILE)}\n`);
232
341
  }
233
342
  }
234
343
 
@@ -240,6 +349,18 @@ if (require.main === module) {
240
349
  if (process.argv[2] === '--force') {
241
350
  updateIndex();
242
351
  console.log('✅ Task index updated');
352
+ } else if (process.argv[2] === '--suggest') {
353
+ const result = updateIndex();
354
+ if (result.suggestions.length > 0) {
355
+ console.log('\n💡 自动流转建议:\n');
356
+ result.suggestions.forEach((s, i) => {
357
+ console.log(`${i + 1}. ${s.message}`);
358
+ console.log(` 开发任务: ${s.developTask.file}`);
359
+ console.log(` 测试任务: ${s.testTask}`);
360
+ });
361
+ } else {
362
+ console.log('✅ 无待处理的流转建议');
363
+ }
243
364
  } else {
244
365
  main();
245
366
  }
@@ -0,0 +1,61 @@
1
+ {
2
+ "enabled": true,
3
+ "severity": "warn",
4
+ "rules": [
5
+ {
6
+ "id": "line-count-limit",
7
+ "enabled": true,
8
+ "severity": "error",
9
+ "config": {
10
+ "maxLines": 800
11
+ }
12
+ },
13
+ {
14
+ "id": "file-size-limit",
15
+ "enabled": true,
16
+ "severity": "warn",
17
+ "config": {
18
+ "maxSize": 819200
19
+ }
20
+ },
21
+ {
22
+ "id": "no-empty-files",
23
+ "enabled": true,
24
+ "severity": "warn"
25
+ },
26
+ {
27
+ "id": "no-trailing-whitespace",
28
+ "enabled": true,
29
+ "severity": "warn"
30
+ },
31
+ {
32
+ "id": "todo-comments",
33
+ "enabled": true,
34
+ "severity": "info"
35
+ },
36
+ {
37
+ "id": "directory-depth",
38
+ "enabled": false,
39
+ "severity": "warn"
40
+ },
41
+ {
42
+ "id": "no-console-logs",
43
+ "enabled": false,
44
+ "severity": "warn"
45
+ },
46
+ {
47
+ "id": "function-length",
48
+ "enabled": false,
49
+ "severity": "warn"
50
+ }
51
+ ],
52
+ "gates": {
53
+ "preCommit": true,
54
+ "prePush": true,
55
+ "onToolUse": false
56
+ },
57
+ "reporting": {
58
+ "format": "console",
59
+ "outputFile": null
60
+ }
61
+ }
@@ -77,7 +77,18 @@
77
77
  "Bash(pkill:*)",
78
78
  "Bash(pip install:*)",
79
79
  "Bash(timeout:*)",
80
- "Bash(python3:*)"
80
+ "Bash(python3:*)",
81
+ "Bash(npm test:*)",
82
+ "Bash(npx standard-version:*)",
83
+ "Bash(openskills list:*)",
84
+ "Bash(playwright install:*)",
85
+ "Bash(npm run release:minor:*)",
86
+ "Bash(npm init:*)",
87
+ "Bash(git init:*)",
88
+ "Bash(git branch:*)",
89
+ "Bash(gh repo create:*)",
90
+ "Bash(npm view:*)",
91
+ "Bash(npm update:*)"
81
92
  ]
82
93
  },
83
94
  "hooks": {