@dedesfr/prompter 0.8.0 → 0.8.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.
- package/CHANGELOG.md +29 -0
- package/dist/cli/index.js +1 -1
- package/package.json +1 -1
- package/skills/agents-md-generator/SKILL.md +238 -0
- package/skills/agents-md-generator/assets/agents-md-template.md +81 -0
- package/skills/agents-md-generator/references/best-practices.md +215 -0
- package/skills/code-review/SKILL.md +373 -0
- package/skills/code-review/assets/report-template-agent.md +212 -0
- package/skills/code-review/assets/report-template-compact.md +81 -0
- package/skills/code-review/assets/report-template-full.md +264 -0
- package/skills/code-review/assets/report-template-human.md +168 -0
- package/skills/code-review/references/universal-patterns.md +495 -0
- package/skills/meeting-notes/SKILL.md +159 -0
- package/skills/meeting-notes/evals/evals.json +23 -0
- package/skills/project-orchestrator/SKILL.md +394 -0
- package/skills/project-orchestrator/assets/plan-summary-template.md +123 -0
- package/skills/prompter-specs/SKILL.md +115 -0
- package/skills/ui-ux-pro/SKILL.md +348 -0
- package/skills/ui-ux-pro/assets/design-spec-template.md +173 -0
- package/skills/ui-ux-pro/references/component-patterns.md +255 -0
- package/skills/ui-ux-pro/references/design-principles.md +167 -0
- package/src/cli/index.ts +1 -1
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
````markdown
|
|
2
|
+
# Universal Code Review Detection Patterns
|
|
3
|
+
|
|
4
|
+
Cross-language patterns for identifying common issues. Organized by category with language-specific examples.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Security Issues
|
|
9
|
+
|
|
10
|
+
### Injection Flaws
|
|
11
|
+
|
|
12
|
+
**SQL Injection:**
|
|
13
|
+
```python
|
|
14
|
+
# ❌ Bad: String concatenation in query
|
|
15
|
+
cursor.execute("SELECT * FROM users WHERE id = " + user_id)
|
|
16
|
+
|
|
17
|
+
# ✅ Good: Parameterized query
|
|
18
|
+
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
// ❌ Bad: Template literal in query
|
|
23
|
+
db.query(`SELECT * FROM users WHERE id = ${userId}`);
|
|
24
|
+
|
|
25
|
+
// ✅ Good: Parameterized query
|
|
26
|
+
db.query("SELECT * FROM users WHERE id = $1", [userId]);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```go
|
|
30
|
+
// ❌ Bad: String formatting in query
|
|
31
|
+
db.Query(fmt.Sprintf("SELECT * FROM users WHERE id = %s", id))
|
|
32
|
+
|
|
33
|
+
// ✅ Good: Parameterized query
|
|
34
|
+
db.Query("SELECT * FROM users WHERE id = $1", id)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Command Injection:**
|
|
38
|
+
```python
|
|
39
|
+
# ❌ Bad: User input in shell command
|
|
40
|
+
os.system("ls " + user_input)
|
|
41
|
+
subprocess.run(f"grep {pattern} file.txt", shell=True)
|
|
42
|
+
|
|
43
|
+
# ✅ Good: Use list form, avoid shell=True
|
|
44
|
+
subprocess.run(["grep", pattern, "file.txt"])
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// ❌ Bad: User input in exec
|
|
49
|
+
const { exec } = require("child_process");
|
|
50
|
+
exec("ls " + userInput);
|
|
51
|
+
|
|
52
|
+
// ✅ Good: Use execFile with arguments
|
|
53
|
+
const { execFile } = require("child_process");
|
|
54
|
+
execFile("ls", [userInput]);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Hardcoded Secrets
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
# ❌ Bad: Hardcoded credentials
|
|
61
|
+
API_KEY = "sk-1234567890abcdef"
|
|
62
|
+
db_password = "supersecret123"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
// ❌ Bad: Secrets in source code
|
|
67
|
+
const stripe = require("stripe")("sk_live_xxx");
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```go
|
|
71
|
+
// ❌ Bad: Embedded credentials
|
|
72
|
+
const apiKey = "AIzaSy..."
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Detection patterns (all languages):**
|
|
76
|
+
- Strings matching: `password`, `secret`, `api_key`, `token`, `credential`
|
|
77
|
+
- Base64-encoded strings assigned to auth variables
|
|
78
|
+
- Connection strings with embedded passwords
|
|
79
|
+
- Private keys or certificates in source
|
|
80
|
+
|
|
81
|
+
**✅ Good: Use environment variables or secret managers**
|
|
82
|
+
|
|
83
|
+
### XSS (Cross-Site Scripting)
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// ❌ Bad: innerHTML with user data
|
|
87
|
+
element.innerHTML = userInput;
|
|
88
|
+
|
|
89
|
+
// ✅ Good: Use textContent or sanitize
|
|
90
|
+
element.textContent = userInput;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# ❌ Bad: Jinja2 with |safe on user input
|
|
95
|
+
{{ user_comment|safe }}
|
|
96
|
+
|
|
97
|
+
# ✅ Good: Auto-escaped (default)
|
|
98
|
+
{{ user_comment }}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Mass Assignment / Over-posting
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# ❌ Bad: Using all request data to create object
|
|
105
|
+
user = User(**request.data)
|
|
106
|
+
|
|
107
|
+
# ✅ Good: Whitelist fields
|
|
108
|
+
user = User(name=data["name"], email=data["email"])
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
// ❌ Bad: Spreading request body into model
|
|
113
|
+
const user = await User.create(req.body);
|
|
114
|
+
|
|
115
|
+
// ✅ Good: Pick specific fields
|
|
116
|
+
const { name, email } = req.body;
|
|
117
|
+
const user = await User.create({ name, email });
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```csharp
|
|
121
|
+
// ❌ Bad: Binding all properties
|
|
122
|
+
public IActionResult Create([FromBody] User user)
|
|
123
|
+
|
|
124
|
+
// ✅ Good: Use DTO or [Bind] attribute
|
|
125
|
+
public IActionResult Create([Bind("Name,Email")] User user)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Performance Anti-patterns
|
|
131
|
+
|
|
132
|
+
### N+1 Query Problem
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# ❌ Bad: N+1 in Django
|
|
136
|
+
posts = Post.objects.all()
|
|
137
|
+
for post in posts:
|
|
138
|
+
print(post.author.name) # Query per post!
|
|
139
|
+
|
|
140
|
+
# ✅ Good: select_related / prefetch_related
|
|
141
|
+
posts = Post.objects.select_related("author").all()
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```ruby
|
|
145
|
+
# ❌ Bad: N+1 in Rails
|
|
146
|
+
@posts = Post.all
|
|
147
|
+
@posts.each { |p| p.author.name } # N+1!
|
|
148
|
+
|
|
149
|
+
# ✅ Good: Eager loading
|
|
150
|
+
@posts = Post.includes(:author).all
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
// ❌ Bad: N+1 in Sequelize
|
|
155
|
+
const posts = await Post.findAll();
|
|
156
|
+
for (const post of posts) {
|
|
157
|
+
const author = await post.getAuthor(); // N+1!
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ✅ Good: Include association
|
|
161
|
+
const posts = await Post.findAll({ include: "author" });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```go
|
|
165
|
+
// ❌ Bad: N+1 in GORM
|
|
166
|
+
var posts []Post
|
|
167
|
+
db.Find(&posts)
|
|
168
|
+
for _, post := range posts {
|
|
169
|
+
db.First(&post.Author, post.AuthorID) // N+1!
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ✅ Good: Preload
|
|
173
|
+
db.Preload("Author").Find(&posts)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Blocking Operations in Async Context
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// ❌ Bad: Synchronous file read in async server
|
|
180
|
+
const data = fs.readFileSync("/large/file.json");
|
|
181
|
+
|
|
182
|
+
// ✅ Good: Async version
|
|
183
|
+
const data = await fs.promises.readFile("/large/file.json");
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
# ❌ Bad: Blocking call in async function
|
|
188
|
+
async def handler():
|
|
189
|
+
data = requests.get(url) # Blocks event loop!
|
|
190
|
+
|
|
191
|
+
# ✅ Good: Use async HTTP client
|
|
192
|
+
async def handler():
|
|
193
|
+
async with aiohttp.ClientSession() as session:
|
|
194
|
+
data = await session.get(url)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Inefficient Algorithms
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
# ❌ Bad: O(n²) lookup
|
|
201
|
+
for item in items:
|
|
202
|
+
if item in large_list: # O(n) per check
|
|
203
|
+
process(item)
|
|
204
|
+
|
|
205
|
+
# ✅ Good: O(n) with set
|
|
206
|
+
large_set = set(large_list)
|
|
207
|
+
for item in items:
|
|
208
|
+
if item in large_set: # O(1) per check
|
|
209
|
+
process(item)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
// ❌ Bad: Repeated array.includes in loop (O(n²))
|
|
214
|
+
items.forEach((item) => {
|
|
215
|
+
if (largeArray.includes(item)) process(item);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// ✅ Good: Use Set (O(n))
|
|
219
|
+
const largeSet = new Set(largeArray);
|
|
220
|
+
items.forEach((item) => {
|
|
221
|
+
if (largeSet.has(item)) process(item);
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Missing Pagination
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
# ❌ Bad: Loading all records
|
|
229
|
+
users = User.objects.all()
|
|
230
|
+
|
|
231
|
+
# ✅ Good: Paginate
|
|
232
|
+
users = User.objects.all()[:25] # or use Paginator
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
// ❌ Bad: No limit
|
|
237
|
+
const users = await db.query("SELECT * FROM users");
|
|
238
|
+
|
|
239
|
+
// ✅ Good: Paginate
|
|
240
|
+
const users = await db.query("SELECT * FROM users LIMIT $1 OFFSET $2", [limit, offset]);
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Error Handling
|
|
246
|
+
|
|
247
|
+
### Swallowed Exceptions
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
# ❌ Bad: Silent catch
|
|
251
|
+
try:
|
|
252
|
+
process_data()
|
|
253
|
+
except Exception:
|
|
254
|
+
pass
|
|
255
|
+
|
|
256
|
+
# ✅ Good: Log or handle
|
|
257
|
+
try:
|
|
258
|
+
process_data()
|
|
259
|
+
except Exception as e:
|
|
260
|
+
logger.error("Processing failed", exc_info=e)
|
|
261
|
+
raise
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
```javascript
|
|
265
|
+
// ❌ Bad: Empty catch
|
|
266
|
+
try {
|
|
267
|
+
await processData();
|
|
268
|
+
} catch (e) {}
|
|
269
|
+
|
|
270
|
+
// ✅ Good: Handle the error
|
|
271
|
+
try {
|
|
272
|
+
await processData();
|
|
273
|
+
} catch (e) {
|
|
274
|
+
logger.error("Processing failed", e);
|
|
275
|
+
throw;
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
```go
|
|
280
|
+
// ❌ Bad: Ignoring error
|
|
281
|
+
result, _ := doSomething()
|
|
282
|
+
|
|
283
|
+
// ✅ Good: Handle the error
|
|
284
|
+
result, err := doSomething()
|
|
285
|
+
if err != nil {
|
|
286
|
+
return fmt.Errorf("doSomething failed: %w", err)
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Overly Broad Exception Catching
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
# ❌ Bad: Catching everything
|
|
294
|
+
except Exception:
|
|
295
|
+
except BaseException:
|
|
296
|
+
|
|
297
|
+
# ✅ Good: Specific exceptions
|
|
298
|
+
except (ValueError, KeyError) as e:
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
```java
|
|
302
|
+
// ❌ Bad: Catching generic Exception
|
|
303
|
+
catch (Exception e) { }
|
|
304
|
+
|
|
305
|
+
// ✅ Good: Specific exception types
|
|
306
|
+
catch (IOException | ParseException e) { }
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Missing Error Handling for I/O
|
|
310
|
+
|
|
311
|
+
```python
|
|
312
|
+
# ❌ Bad: No error handling for file I/O
|
|
313
|
+
data = open("config.json").read()
|
|
314
|
+
|
|
315
|
+
# ✅ Good: Handle potential errors
|
|
316
|
+
try:
|
|
317
|
+
with open("config.json") as f:
|
|
318
|
+
data = f.read()
|
|
319
|
+
except FileNotFoundError:
|
|
320
|
+
data = default_config
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Architecture Issues
|
|
326
|
+
|
|
327
|
+
### God Object / Fat Controller
|
|
328
|
+
|
|
329
|
+
**Detection:** Class or function with >200 lines, >10 methods, or >5 dependencies.
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
# ❌ Bad: Controller doing everything
|
|
333
|
+
class UserView(APIView):
|
|
334
|
+
def post(self, request):
|
|
335
|
+
# Validates, creates user, sends email, creates token,
|
|
336
|
+
# logs event, syncs to CRM... all in one method
|
|
337
|
+
|
|
338
|
+
# ✅ Good: Delegate to service layer
|
|
339
|
+
class UserView(APIView):
|
|
340
|
+
def post(self, request):
|
|
341
|
+
serializer = UserSerializer(data=request.data)
|
|
342
|
+
serializer.is_valid(raise_exception=True)
|
|
343
|
+
user = UserService.register(serializer.validated_data)
|
|
344
|
+
return Response(UserSerializer(user).data, status=201)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Business Logic in Wrong Layer
|
|
348
|
+
|
|
349
|
+
**Detection:** Database queries in views/templates, HTTP concerns in models/services.
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
// ❌ Bad: DB query in React component
|
|
353
|
+
function UserList() {
|
|
354
|
+
const users = await db.query("SELECT * FROM users"); // Wrong layer!
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// ✅ Good: API call from component, query in backend
|
|
358
|
+
function UserList() {
|
|
359
|
+
const users = await fetch("/api/users").then((r) => r.json());
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Circular Dependencies
|
|
364
|
+
|
|
365
|
+
**Detection:** Module A imports B, B imports A.
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
# ❌ Bad: Circular import
|
|
369
|
+
# file: models.py
|
|
370
|
+
from .services import UserService
|
|
371
|
+
|
|
372
|
+
# file: services.py
|
|
373
|
+
from .models import User # Circular!
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Fix:** Move shared types to a separate module, use dependency injection, or use lazy imports.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Code Quality
|
|
381
|
+
|
|
382
|
+
### Missing Type Annotations
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
# ❌ Bad: No types
|
|
386
|
+
def process(data, options):
|
|
387
|
+
return data
|
|
388
|
+
|
|
389
|
+
# ✅ Good: Type hints
|
|
390
|
+
def process(data: dict[str, Any], options: ProcessOptions) -> Result:
|
|
391
|
+
return Result(data)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
// TypeScript: ❌ Bad - any type
|
|
396
|
+
function process(data: any): any { }
|
|
397
|
+
|
|
398
|
+
// ✅ Good: Specific types
|
|
399
|
+
function process(data: Record<string, unknown>): Result { }
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Deprecated API Usage
|
|
403
|
+
|
|
404
|
+
**Detection patterns:**
|
|
405
|
+
- Functions/methods marked with `@deprecated` decorators
|
|
406
|
+
- Import of known deprecated modules
|
|
407
|
+
- Usage of APIs removed in newer language versions
|
|
408
|
+
- Compiler/linter warnings about deprecation
|
|
409
|
+
|
|
410
|
+
### Dead Code
|
|
411
|
+
|
|
412
|
+
**Detection patterns:**
|
|
413
|
+
- Functions never called (no references)
|
|
414
|
+
- Unreachable code after `return`, `throw`, `break`
|
|
415
|
+
- Commented-out code blocks (>5 lines)
|
|
416
|
+
- Unused imports/variables
|
|
417
|
+
- Feature flags always evaluating to same value
|
|
418
|
+
|
|
419
|
+
### Code Duplication
|
|
420
|
+
|
|
421
|
+
**Detection:**
|
|
422
|
+
- Identical or near-identical blocks (>10 lines) across files
|
|
423
|
+
- Repeated patterns that could be extracted into a shared utility
|
|
424
|
+
- Copy-pasted logic with minor variations
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Resource Management
|
|
429
|
+
|
|
430
|
+
### Resource Leaks
|
|
431
|
+
|
|
432
|
+
```python
|
|
433
|
+
# ❌ Bad: Unclosed file handle
|
|
434
|
+
f = open("data.txt")
|
|
435
|
+
data = f.read()
|
|
436
|
+
# f never closed if exception occurs
|
|
437
|
+
|
|
438
|
+
# ✅ Good: Context manager
|
|
439
|
+
with open("data.txt") as f:
|
|
440
|
+
data = f.read()
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
```go
|
|
444
|
+
// ❌ Bad: Unclosed response body
|
|
445
|
+
resp, _ := http.Get(url)
|
|
446
|
+
// resp.Body never closed
|
|
447
|
+
|
|
448
|
+
// ✅ Good: Defer close
|
|
449
|
+
resp, err := http.Get(url)
|
|
450
|
+
if err != nil { return err }
|
|
451
|
+
defer resp.Body.Close()
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
```java
|
|
455
|
+
// ❌ Bad: Unclosed connection
|
|
456
|
+
Connection conn = DriverManager.getConnection(url);
|
|
457
|
+
// conn never closed
|
|
458
|
+
|
|
459
|
+
// ✅ Good: Try-with-resources
|
|
460
|
+
try (Connection conn = DriverManager.getConnection(url)) {
|
|
461
|
+
// use connection
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Missing Connection Pooling
|
|
466
|
+
|
|
467
|
+
**Detection:** Database or HTTP connections created per request instead of shared pool.
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## Severity Classification
|
|
472
|
+
|
|
473
|
+
| Severity | Emoji | Universal Criteria |
|
|
474
|
+
| ------------ | ----- | ----------------------------------------------------------------- |
|
|
475
|
+
| Critical | 🔴 | Security vulnerabilities, data loss risks, crashes, auth bypasses |
|
|
476
|
+
| Warning | 🟠 | Performance issues, design flaws, error handling gaps |
|
|
477
|
+
| Optimization | 🟡 | Efficiency improvements, code duplication, missing caching |
|
|
478
|
+
| Quality | 🔵 | Best practices, conventions, modern syntax, documentation |
|
|
479
|
+
|
|
480
|
+
## Detection Priority by Language
|
|
481
|
+
|
|
482
|
+
| Language | Top Issues to Check |
|
|
483
|
+
| -------------- | -------------------------------------------------------------------- |
|
|
484
|
+
| Python | Type hints, injection, N+1 (Django/SQLAlchemy), async misuse |
|
|
485
|
+
| JavaScript/TS | XSS, any types, blocking event loop, missing await, memory leaks |
|
|
486
|
+
| PHP | SQL injection, XSS, mass assignment, type safety, deprecated APIs |
|
|
487
|
+
| Go | Ignored errors, goroutine leaks, unclosed readers, race conditions |
|
|
488
|
+
| Rust | Unsafe blocks, unwrap() abuse, clone() overhead, lifetime issues |
|
|
489
|
+
| Java | Resource leaks, broad catches, null safety, generics misuse |
|
|
490
|
+
| Ruby | N+1 (Rails), mass assignment, SQL injection, missing strong params |
|
|
491
|
+
| C# | Over-posting, async void, IDisposable leaks, null reference |
|
|
492
|
+
| Swift | Force unwrap abuse, retain cycles, main thread violations |
|
|
493
|
+
| Kotlin | Platform types, coroutine scope leaks, null safety bypass |
|
|
494
|
+
|
|
495
|
+
````
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: meeting-notes
|
|
3
|
+
description: Transform raw meeting notes, transcripts, or informal notes into a structured, actionable to-do list ready for AI agent execution. Automatically extracts tasks, categorizes by priority and context, and formats output for direct copy-paste into Claude or other AI agents. Use this skill whenever a user pastes meeting notes, a transcript, a brain dump, or unstructured notes and wants tasks extracted — even if they just say "here are my meeting notes" or "can you turn this into tasks". Also triggers when users want to organize action items from a meeting, sync-up, standup, retrospective, or planning session.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Meeting Notes → Structured To-Do List
|
|
7
|
+
|
|
8
|
+
Convert raw, informal meeting notes into a clean, actionable task list formatted for direct execution by an AI agent. Each output task is self-contained — the agent executing it should never need to reference the original notes.
|
|
9
|
+
|
|
10
|
+
## Step 1: Accept Input
|
|
11
|
+
|
|
12
|
+
Accept notes in any format:
|
|
13
|
+
- Pasted plain text or markdown
|
|
14
|
+
- A file path (read the file)
|
|
15
|
+
- A transcript with speaker labels
|
|
16
|
+
- Bullet-pointed jottings or a brain dump
|
|
17
|
+
|
|
18
|
+
If the user hasn't provided notes yet, ask: "Please paste your meeting notes or provide a file path."
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Step 2: Check for Project Context (If in a Repo)
|
|
23
|
+
|
|
24
|
+
Before extracting tasks, check whether you're inside a project repository. This context helps align output with the project's conventions.
|
|
25
|
+
|
|
26
|
+
1. Look for `CLAUDE.md` or `prompter/CLAUDE.md` — project guidelines, naming conventions, tech stack
|
|
27
|
+
2. Look for `AGENTS.md` — workflow context and existing structure
|
|
28
|
+
3. Check for existing task files: `TODO.md`, `tasks.md`, `.taskmaster/`, or similar
|
|
29
|
+
4. Run `git log --oneline -10` to understand current work in flight
|
|
30
|
+
|
|
31
|
+
Use this context to:
|
|
32
|
+
- Align task titles with project conventions (e.g., `feat(auth):` prefixes, snake_case names)
|
|
33
|
+
- Flag tasks that likely duplicate existing in-progress work
|
|
34
|
+
- Reference specific files or modules from the repo when the notes mention them
|
|
35
|
+
|
|
36
|
+
If no repo context is found, proceed with general formatting.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Step 3: Extract Tasks
|
|
41
|
+
|
|
42
|
+
Scan the notes for everything that implies work to be done.
|
|
43
|
+
|
|
44
|
+
**Extract these:**
|
|
45
|
+
- Explicit action items: "we need to…", "John will…", "TODO:", "action item:"
|
|
46
|
+
- Decisions requiring implementation: "we decided to X — someone needs to build it"
|
|
47
|
+
- Open questions needing resolution: "TBD", "to figure out", "need to check"
|
|
48
|
+
- Implicit commitments: "before the release", "I'll handle it", "by next week"
|
|
49
|
+
|
|
50
|
+
**Skip these:**
|
|
51
|
+
- Background context with no next step
|
|
52
|
+
- Already-completed work: "we shipped X last week"
|
|
53
|
+
- Opinions with no concrete follow-through
|
|
54
|
+
|
|
55
|
+
For each task, capture:
|
|
56
|
+
- **Title** — short imperative verb phrase: "Set up CI pipeline for mobile builds"
|
|
57
|
+
- **Description** — what needs to happen, with enough context for execution without the notes
|
|
58
|
+
- **Owner** — who's responsible (leave blank if not mentioned)
|
|
59
|
+
- **Priority** — see Priority Guide below
|
|
60
|
+
- **Category** — see Categories below
|
|
61
|
+
- **Due date** — only if explicitly mentioned
|
|
62
|
+
|
|
63
|
+
### Priority Guide
|
|
64
|
+
|
|
65
|
+
| Priority | Signals |
|
|
66
|
+
|----------|---------|
|
|
67
|
+
| **High** | "blocker", "urgent", "ASAP", "before launch", "critical", deadline within ~1 week |
|
|
68
|
+
| **Medium** | "should", "this sprint", "next week", general items with no urgency signal |
|
|
69
|
+
| **Low** | "nice to have", "eventually", "backlog", "when we get to it", open questions with no deadline |
|
|
70
|
+
|
|
71
|
+
### Categories
|
|
72
|
+
|
|
73
|
+
Choose the best fit:
|
|
74
|
+
- **Development** — coding, implementation, bug fixes
|
|
75
|
+
- **Design** — UI/UX, wireframes, visual assets
|
|
76
|
+
- **Research** — investigation, spikes, discovery
|
|
77
|
+
- **DevOps/Infra** — CI/CD, deployments, infrastructure
|
|
78
|
+
- **Product** — requirements, roadmap, stakeholder decisions
|
|
79
|
+
- **Testing/QA** — test writing, QA passes, review
|
|
80
|
+
- **Documentation** — docs, READMEs, guides
|
|
81
|
+
- **Communication** — follow-up emails, meetings to schedule
|
|
82
|
+
- **Admin/Other** — anything else
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Step 4: Format Output
|
|
87
|
+
|
|
88
|
+
Produce two blocks.
|
|
89
|
+
|
|
90
|
+
### Block 1: Summary Table
|
|
91
|
+
|
|
92
|
+
A markdown table for quick scanning:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
| # | Task | Owner | Priority | Category | Due |
|
|
96
|
+
|---|------|-------|----------|----------|-----|
|
|
97
|
+
| 1 | Set up CI pipeline for mobile builds | @alice | High | DevOps/Infra | Mar 22 |
|
|
98
|
+
| 2 | ... |
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Block 2: AI-Agent-Ready Task List
|
|
102
|
+
|
|
103
|
+
Each task as a standalone, copy-pasteable prompt block. The goal is that someone can paste any single block directly into an AI agent and it will know exactly what to do — no additional context needed.
|
|
104
|
+
|
|
105
|
+
Use this template for each task:
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
**TASK [N] · [Priority] · [Category]**
|
|
110
|
+
**[Title]**
|
|
111
|
+
|
|
112
|
+
> **Context:** [1–2 sentences explaining why this task exists and what decision or discussion led to it]
|
|
113
|
+
|
|
114
|
+
**What to do:**
|
|
115
|
+
- [Concrete imperative step 1]
|
|
116
|
+
- [Concrete imperative step 2]
|
|
117
|
+
- [Add more as needed]
|
|
118
|
+
|
|
119
|
+
**Assignee:** [owner or "Unassigned"]
|
|
120
|
+
**Due:** [date or "Not specified"]
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
**Writing good task blocks — the key principles:**
|
|
125
|
+
- The title is an imperative verb phrase, not a noun phrase ("Fix the auth bug" not "Auth bug fix")
|
|
126
|
+
- The Context block carries the *why*, so the agent understands the goal, not just the mechanics
|
|
127
|
+
- "What to do" steps are concrete and specific — name files, tools, systems, and outputs by name when the notes mention them
|
|
128
|
+
- Self-contained means: no pronouns without antecedents, no references to "the meeting", no unexplained abbreviations
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Step 5: Validate Against Project Context (If Applicable)
|
|
133
|
+
|
|
134
|
+
If you gathered project context in Step 2, do a final pass before printing output:
|
|
135
|
+
|
|
136
|
+
1. **Naming alignment** — rewrite task titles to match project conventions
|
|
137
|
+
2. **Duplicate detection** — if a task matches something in git history or existing task files, flag it: `⚠️ Possible duplicate: [reference]`
|
|
138
|
+
3. **File/module references** — replace vague references ("the auth module") with actual repo paths when you can identify them
|
|
139
|
+
4. **Missing context** — if a task needs project knowledge not present in the notes, flag it: `ℹ️ Context needed: [what's unclear]`
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Step 6: Present and Offer to Save
|
|
144
|
+
|
|
145
|
+
1. Print the Summary Table
|
|
146
|
+
2. Print the AI-Agent-Ready Task List
|
|
147
|
+
3. Offer to save to a file (default: `meeting-tasks-YYYY-MM-DD.md`)
|
|
148
|
+
|
|
149
|
+
If the user wants changes — reordering, reprioritization, a missing task, merging two tasks — iterate quickly.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Edge Cases
|
|
154
|
+
|
|
155
|
+
- **No clear tasks found** — Tell the user and ask whether to extract implicit decisions or discussion points that might need follow-up
|
|
156
|
+
- **Very long meeting (many items)** — Ask if they want to filter by owner, topic, or priority tier
|
|
157
|
+
- **Ambiguous owner** — Write "Unassigned"; never guess
|
|
158
|
+
- **Conflicting priority signals** — Use the most urgent signal
|
|
159
|
+
- **Non-English notes** — Process and output in the same language
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "meeting-notes-to-todo",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "hey can you turn these into a task list?\n\n---\nProduct sync – March 18 2026\nAttendees: Sarah (PM), Dev (backend), Mia (design), Tom (QA)\n\nWe talked about the upcoming v2.1 release. Launch is March 28.\n\n- Sarah said the onboarding flow redesign needs to be done before we release. Mia is handling the wireframes, needs to be done by March 21 so dev can implement.\n- Dev mentioned the payment webhook is still broken on sandbox. He'll fix it this week, it's a blocker.\n- Tom hasn't started regression testing yet – needs to start by March 24 at the latest or we'll miss the launch window.\n- We need to write release notes before launch. Sarah said she'll draft them but needs input from dev on what changed technically.\n- Someone (nobody claimed it) needs to update the docs for the new API endpoints. Mia suggested we do a quick loom video too.\n- The analytics dashboard is broken in Safari – not a launch blocker but should be fixed soon. Dev will look into it after the release.\n- Sarah wants a go/no-go meeting on March 26. She'll send the invite.\n---\n\ncan you make each task ready to paste into claude so it can do the work?",
|
|
7
|
+
"expected_output": "A summary table with all 7+ tasks, each with owner, priority, and due date where specified. Followed by individual AI-agent-ready task blocks — each self-contained with context, concrete steps, assignee, and due date. High priority on the payment webhook fix and Mia's wireframes due to blockers/deadline. Go/no-go meeting invite should be a Communication task.",
|
|
8
|
+
"files": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": 2,
|
|
12
|
+
"prompt": "here are my notes from today's backend team standup, can you extract the action items and make a proper todo list?\n\nStandup notes 3/18:\n- alice: finished auth refactor PR, waiting on review from bob. also discovered that the session token TTL logic has a bug where it doesn't handle timezone offsets correctly — filed issue #847\n- bob: reviewing alice's PR today. blocked on the redis cluster upgrade because ops team hasn't provisioned the new nodes yet. bob will ping ops (jake) about it\n- carol: working on the data export feature. the CSV generation is done, still need to wire up the S3 upload and add retry logic. estimates 2 more days\n- team decision: we're going to use structured logging (pino) across all new services starting now. carol will add it to the data export service as she finishes. alice will document the convention in the backend README\n- also need to add integration tests for the auth refactor before it can merge — bob mentioned this\n- reminder: sprint review is friday, everyone should have their items demoed or marked done",
|
|
13
|
+
"expected_output": "A clean task list covering: reviewing alice's PR (bob, high), pinging ops about redis nodes (bob, medium), finishing S3 upload + retry logic for data export (carol, medium), adding pino structured logging to data export service (carol, medium), documenting logging convention in README (alice, medium), adding integration tests for auth refactor (medium, before merge), preparing sprint review items (friday deadline). Summary table plus AI-agent-ready blocks with clear context.",
|
|
14
|
+
"files": []
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": 3,
|
|
18
|
+
"prompt": "I just got out of a long planning session, my brain is fried. here are my rough notes — lots of things mixed together, some things were just discussed but a few are actual todos. can you sort it all out and give me a clean task list formatted so I can paste each task into claude to work on?\n\n=== planning session notes ===\ntalked about Q2 roadmap. main themes: retention, performance, mobile parity\n\nretention:\n- churn is at 8% which is bad. need to understand why. -> spike: analyze churn data from mixpanel, look at cohorts from jan-mar. who's churning and at what point in lifecycle?\n- idea: add email drip campaign for users who haven't logged in for 7 days. not sure if this is the right move. needs product sign-off from lisa\n- subscription cancellation page — we should add a \"pause instead of cancel\" option. this one is approved and prioritized. design + dev work needed.\n\nperformance:\n- homepage loads in 4.2s on mobile, goal is sub-2s. jake looked at it and thinks it's the hero image and 3 blocking JS scripts. -> optimize hero image (webp, lazy load) and defer non-critical JS\n- database query for user feed is N+1, has been on the backlog forever. now it's causing timeouts on accounts with >1000 connections. urgent fix needed.\n- CDN caching headers are wrong, static assets are being re-fetched every request. quick fix, someone just needs to do it\n\nmobile:\n- ios app is missing the notifications tab that android has. 3 sprints of work estimated.\n- push notifications are broken on ios 17.4+ (regression from last month). super urgent, lots of user complaints\n- android: dark mode looks bad on samsung devices specifically (OLED screens). medium priority, aesthetic issue\n\nother:\n- we never documented the data retention policy after legal asked us to. someone needs to write that doc. probably high priority given compliance.\n- offsite planning in april, need to book venue\n===",
|
|
19
|
+
"expected_output": "Should separate actual tasks from pure discussion. High-priority items: fix N+1 query, fix iOS push notification regression, write data retention policy doc. Medium: optimize homepage performance, fix CDN caching, pause-vs-cancel feature (design + dev). Low/research: churn analysis spike, email drip campaign (needs sign-off), Samsung dark mode fix. Long-horizon: iOS notifications tab (3 sprints), book offsite venue. Each task should be clearly scoped as an AI-agent-ready block with context and concrete steps.",
|
|
20
|
+
"files": []
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|