@booklib/skills 1.5.2 → 1.6.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/CONTRIBUTING.md +23 -1
- package/README.md +55 -0
- package/benchmark/devto-post.md +178 -0
- package/benchmark/order-processing.original.js +158 -0
- package/benchmark/order-processing.pr-toolkit.js +181 -0
- package/benchmark/order-processing.skill-router.js +271 -0
- package/benchmark/review-report.md +129 -0
- package/bin/skills.js +327 -69
- package/commands/animation-at-work.md +10 -0
- package/commands/clean-code-reviewer.md +10 -0
- package/commands/data-intensive-patterns.md +10 -0
- package/commands/data-pipelines.md +10 -0
- package/commands/design-patterns.md +10 -0
- package/commands/domain-driven-design.md +10 -0
- package/commands/effective-java.md +10 -0
- package/commands/effective-kotlin.md +10 -0
- package/commands/effective-python.md +10 -0
- package/commands/effective-typescript.md +10 -0
- package/commands/kotlin-in-action.md +10 -0
- package/commands/lean-startup.md +10 -0
- package/commands/microservices-patterns.md +10 -0
- package/commands/programming-with-rust.md +10 -0
- package/commands/refactoring-ui.md +10 -0
- package/commands/rust-in-action.md +10 -0
- package/commands/skill-router.md +10 -0
- package/commands/spring-boot-in-action.md +10 -0
- package/commands/storytelling-with-data.md +10 -0
- package/commands/system-design-interview.md +10 -0
- package/commands/using-asyncio-python.md +10 -0
- package/commands/web-scraping-python.md +10 -0
- package/docs/index.html +62 -13
- package/package.json +4 -1
- package/scripts/gen-og.mjs +142 -0
- package/skills/skill-router/SKILL.md +23 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review microservice architecture using patterns from Chris Richardson. Usage: /microservices-patterns [file | path | description]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `microservices-patterns` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, run `git diff HEAD` and review those changes.
|
|
9
|
+
|
|
10
|
+
Focus on service decomposition, sagas, event sourcing, API gateways, and inter-service communication. Classify each finding as **HIGH** / **MEDIUM** / **LOW** and reference as `file:line`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review Rust code against Programming with Rust (Donis Marshall). Usage: /programming-with-rust [file | path]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `programming-with-rust` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, run `git diff HEAD` and review those changes.
|
|
9
|
+
|
|
10
|
+
Focus on ownership, borrowing, lifetimes, traits, and safe concurrency patterns. Classify each finding as **HIGH** / **MEDIUM** / **LOW** and reference as `file:line`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review UI design against Refactoring UI principles (Wathan & Schoger). Usage: /refactoring-ui [file | component | screenshot path]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `refactoring-ui` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, run `git diff HEAD` and review changed UI components.
|
|
9
|
+
|
|
10
|
+
Focus on visual hierarchy, spacing, typography, color, and component composition. Classify each finding as **HIGH** / **MEDIUM** / **LOW** and reference as `file:line`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review Rust code using Rust in Action patterns (Tim McNamara). Usage: /rust-in-action [file | path]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `rust-in-action` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, run `git diff HEAD` and review those changes.
|
|
9
|
+
|
|
10
|
+
Focus on systems programming idioms: memory layout, unsafe code, FFI, and OS interaction. Classify each finding as **HIGH** / **MEDIUM** / **LOW** and reference as `file:line`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Route your task to the most relevant @booklib/skills skill. Usage: /skill-router [file | task description]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `skill-router` skill to recommend the best @booklib skill for this task.
|
|
6
|
+
|
|
7
|
+
**Input:** $ARGUMENTS
|
|
8
|
+
If no input was given, use `git diff HEAD` as the scope.
|
|
9
|
+
|
|
10
|
+
Return a ranked recommendation with rationale and anti-triggers. Then ask if you should apply the recommended skill immediately.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review Spring Boot code using Spring Boot in Action patterns (Craig Walls). Usage: /spring-boot-in-action [file | path]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `spring-boot-in-action` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, run `git diff HEAD` and review those changes.
|
|
9
|
+
|
|
10
|
+
Focus on auto-configuration, dependency injection, REST endpoints, data access, and testing. Classify each finding as **HIGH** / **MEDIUM** / **LOW** and reference as `file:line`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review data visualizations and charts using Storytelling with Data (Cole Nussbaumer Knaflic). Usage: /storytelling-with-data [file | chart description]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `storytelling-with-data` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, describe the chart or run `git diff HEAD` to review changed visualization code.
|
|
9
|
+
|
|
10
|
+
Focus on chart type choice, data-ink ratio, clutter removal, audience, and narrative. Classify each finding as **HIGH** / **MEDIUM** / **LOW**.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review system design using Alex Xu's framework (scalability, estimation, trade-offs). Usage: /system-design-interview [description | file]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `system-design-interview` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, describe the system you want reviewed or run `git diff HEAD`.
|
|
9
|
+
|
|
10
|
+
Cover requirements clarification, capacity estimation, high-level design, component deep-dive, and trade-offs. Classify each finding as **HIGH** / **MEDIUM** / **LOW**.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review Python async/concurrent code using Using Asyncio in Python (Caleb Hattingh). Usage: /using-asyncio-python [file | path]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `using-asyncio-python` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, run `git diff HEAD` and review those changes.
|
|
9
|
+
|
|
10
|
+
Focus on event loop usage, coroutine patterns, task management, cancellation, and common asyncio pitfalls. Classify each finding as **HIGH** / **MEDIUM** / **LOW** and reference as `file:line`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review Python web scraping code using Web Scraping with Python (Ryan Mitchell). Usage: /web-scraping-python [file | path]
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the `web-scraping-python` skill.
|
|
6
|
+
|
|
7
|
+
**Target:** $ARGUMENTS
|
|
8
|
+
If no target was given, run `git diff HEAD` and review those changes.
|
|
9
|
+
|
|
10
|
+
Focus on selector robustness, rate limiting, error handling, anti-bot evasion, and data storage. Classify each finding as **HIGH** / **MEDIUM** / **LOW** and reference as `file:line`.
|
package/docs/index.html
CHANGED
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
<meta name="description" content="22 AI agent skills grounded in canonical programming books. Give your AI coding assistant expert knowledge from Clean Code, Effective Java, DDD, and more."/>
|
|
8
8
|
<meta property="og:title" content="booklib-ai/skills"/>
|
|
9
9
|
<meta property="og:description" content="Book-grounded AI agent skills for Claude Code, Cursor, Copilot, and Windsurf."/>
|
|
10
|
-
<meta property="og:image" content="https://booklib-ai.github.io/skills/
|
|
10
|
+
<meta property="og:image" content="https://booklib-ai.github.io/skills/og.png"/>
|
|
11
|
+
<meta property="og:image:width" content="1200"/>
|
|
12
|
+
<meta property="og:image:height" content="630"/>
|
|
13
|
+
<meta name="twitter:card" content="summary_large_image"/>
|
|
14
|
+
<meta name="twitter:image" content="https://booklib-ai.github.io/skills/og.png"/>
|
|
11
15
|
<style>
|
|
12
16
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
13
17
|
|
|
@@ -108,8 +112,8 @@
|
|
|
108
112
|
}
|
|
109
113
|
.skills-grid {
|
|
110
114
|
display: grid;
|
|
111
|
-
grid-template-columns: repeat(auto-fill, minmax(
|
|
112
|
-
gap:
|
|
115
|
+
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
|
|
116
|
+
gap: 14px;
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
/* Card */
|
|
@@ -153,6 +157,15 @@
|
|
|
153
157
|
object-fit: cover;
|
|
154
158
|
display: block;
|
|
155
159
|
}
|
|
160
|
+
.cover-wrap img.loading {
|
|
161
|
+
background: linear-gradient(90deg, #161625 25%, #1e1e38 50%, #161625 75%);
|
|
162
|
+
background-size: 200% 100%;
|
|
163
|
+
animation: shimmer 1.5s infinite linear;
|
|
164
|
+
}
|
|
165
|
+
@keyframes shimmer {
|
|
166
|
+
0% { background-position: 200% 0; }
|
|
167
|
+
100% { background-position: -200% 0; }
|
|
168
|
+
}
|
|
156
169
|
.cover-fallback {
|
|
157
170
|
width: 100%;
|
|
158
171
|
height: 100%;
|
|
@@ -178,35 +191,35 @@
|
|
|
178
191
|
|
|
179
192
|
/* Card body */
|
|
180
193
|
.card-body {
|
|
181
|
-
padding:
|
|
194
|
+
padding: 10px 12px 12px;
|
|
182
195
|
flex: 1;
|
|
183
196
|
display: flex;
|
|
184
197
|
flex-direction: column;
|
|
185
|
-
gap:
|
|
198
|
+
gap: 3px;
|
|
186
199
|
}
|
|
187
200
|
.card-body .skill-name {
|
|
188
|
-
font-size: 0.
|
|
201
|
+
font-size: 0.7rem;
|
|
189
202
|
font-weight: 700;
|
|
190
203
|
color: #a5b4fc;
|
|
191
204
|
font-family: "SF Mono", "Fira Code", monospace;
|
|
192
205
|
word-break: break-all;
|
|
193
206
|
}
|
|
194
207
|
.card-body .book-title {
|
|
195
|
-
font-size: 0.
|
|
208
|
+
font-size: 0.75rem;
|
|
196
209
|
font-weight: 600;
|
|
197
210
|
color: #e2e8f0;
|
|
198
211
|
line-height: 1.3;
|
|
199
212
|
margin-top: 2px;
|
|
200
213
|
}
|
|
201
214
|
.card-body .book-author {
|
|
202
|
-
font-size: 0.
|
|
215
|
+
font-size: 0.68rem;
|
|
203
216
|
color: #64748b;
|
|
204
217
|
}
|
|
205
218
|
.card-body .card-desc {
|
|
206
|
-
font-size: 0.
|
|
219
|
+
font-size: 0.68rem;
|
|
207
220
|
color: #475569;
|
|
208
|
-
line-height: 1.
|
|
209
|
-
margin-top:
|
|
221
|
+
line-height: 1.4;
|
|
222
|
+
margin-top: 4px;
|
|
210
223
|
}
|
|
211
224
|
|
|
212
225
|
/* Footer */
|
|
@@ -283,6 +296,40 @@
|
|
|
283
296
|
return name.split(/[\s-]+/).map(w => w[0]).join("").toUpperCase().slice(0, 3);
|
|
284
297
|
}
|
|
285
298
|
|
|
299
|
+
// Fetch cover URL from Google Books JSON API.
|
|
300
|
+
// Using the API (not direct hotlinking) avoids false-positive placeholder images
|
|
301
|
+
// ("No preview available" hatch / "image not available" text) that Google returns
|
|
302
|
+
// as HTTP 200 responses — the API simply omits imageLinks when no cover exists.
|
|
303
|
+
function showFb(img) {
|
|
304
|
+
img.style.display = "none";
|
|
305
|
+
const fb = img.nextElementSibling;
|
|
306
|
+
if (fb) fb.style.display = "flex";
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async function loadCover(img) {
|
|
310
|
+
const isbn = img.dataset.isbn;
|
|
311
|
+
try {
|
|
312
|
+
const url = `https://www.googleapis.com/books/v1/volumes?q=isbn:${isbn}&fields=items(volumeInfo(imageLinks))&maxResults=1`;
|
|
313
|
+
const d = await fetch(url).then(r => r.json());
|
|
314
|
+
const links = d.items?.[0]?.volumeInfo?.imageLinks;
|
|
315
|
+
// thumbnail/smallThumbnail are the only sizes returned by a search query.
|
|
316
|
+
// Replacing zoom=1 with zoom=0 fetches the largest available version of the same image.
|
|
317
|
+
const src = (links?.thumbnail || links?.smallThumbnail || "")
|
|
318
|
+
.replace(/^http:/, "https:")
|
|
319
|
+
.replace("zoom=1", "zoom=5")
|
|
320
|
+
.replace("&edge=curl", "");
|
|
321
|
+
if (src) {
|
|
322
|
+
img.onload = () => img.classList.remove("loading");
|
|
323
|
+
img.onerror = () => showFb(img);
|
|
324
|
+
img.src = src;
|
|
325
|
+
} else {
|
|
326
|
+
showFb(img);
|
|
327
|
+
}
|
|
328
|
+
} catch {
|
|
329
|
+
showFb(img);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
286
333
|
function buildCard(skill) {
|
|
287
334
|
const card = document.createElement("a");
|
|
288
335
|
card.className = "skill-card";
|
|
@@ -292,9 +339,9 @@
|
|
|
292
339
|
|
|
293
340
|
const coverHtml = skill.isbn
|
|
294
341
|
? `<img
|
|
295
|
-
|
|
342
|
+
class="loading"
|
|
343
|
+
data-isbn="${skill.isbn}"
|
|
296
344
|
alt="${skill.book} cover"
|
|
297
|
-
onerror="this.style.display='none';this.nextElementSibling.style.display='flex'"
|
|
298
345
|
/>
|
|
299
346
|
<div class="cover-fallback" style="display:none">
|
|
300
347
|
<div class="initials">${initials(skill.book)}</div>
|
|
@@ -356,6 +403,8 @@
|
|
|
356
403
|
// Build grid
|
|
357
404
|
const grid = document.getElementById("grid");
|
|
358
405
|
SKILLS.forEach(skill => grid.appendChild(buildCard(skill)));
|
|
406
|
+
// Kick off async cover loading after DOM is populated
|
|
407
|
+
document.querySelectorAll("img[data-isbn]").forEach(loadCover);
|
|
359
408
|
</script>
|
|
360
409
|
|
|
361
410
|
</body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@booklib/skills",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Book knowledge distilled into structured AI skills for Claude Code and other AI assistants",
|
|
5
5
|
"bin": {
|
|
6
6
|
"skills": "bin/skills.js"
|
|
@@ -20,5 +20,8 @@
|
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=16"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"puppeteer": "^24.39.1"
|
|
23
26
|
}
|
|
24
27
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* gen-og.mjs — generates docs/og.png (1200×630) for GitHub Pages OG preview.
|
|
4
|
+
* Usage: node scripts/gen-og.mjs
|
|
5
|
+
* Requires: npm install -g puppeteer OR npx puppeteer is available
|
|
6
|
+
*/
|
|
7
|
+
import { writeFileSync, mkdirSync } from "fs";
|
|
8
|
+
import { join, dirname } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const OUT = join(__dirname, "../docs/og.png");
|
|
13
|
+
|
|
14
|
+
const HTML = `<!DOCTYPE html>
|
|
15
|
+
<html>
|
|
16
|
+
<head>
|
|
17
|
+
<meta charset="UTF-8"/>
|
|
18
|
+
<style>
|
|
19
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
20
|
+
body {
|
|
21
|
+
width: 1200px; height: 630px; overflow: hidden;
|
|
22
|
+
background: #0d0d1a;
|
|
23
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
padding: 0 80px;
|
|
28
|
+
position: relative;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Left: text content */
|
|
32
|
+
.left { flex: 0 0 auto; max-width: 540px; z-index: 2; }
|
|
33
|
+
|
|
34
|
+
.org {
|
|
35
|
+
font-size: 22px; font-weight: 500; color: #6366f1;
|
|
36
|
+
letter-spacing: 0.04em; margin-bottom: 16px;
|
|
37
|
+
font-family: "SF Mono", "Fira Code", monospace;
|
|
38
|
+
}
|
|
39
|
+
h1 {
|
|
40
|
+
font-size: 72px; font-weight: 800; color: #f1f5f9;
|
|
41
|
+
line-height: 1; letter-spacing: -0.04em; margin-bottom: 20px;
|
|
42
|
+
}
|
|
43
|
+
.tagline {
|
|
44
|
+
font-size: 24px; color: #64748b; line-height: 1.4; margin-bottom: 40px;
|
|
45
|
+
max-width: 460px;
|
|
46
|
+
}
|
|
47
|
+
.pills { display: flex; gap: 12px; flex-wrap: wrap; }
|
|
48
|
+
.pill {
|
|
49
|
+
background: #161625; border: 1px solid #2d2d4a;
|
|
50
|
+
border-radius: 999px; padding: 8px 20px;
|
|
51
|
+
font-size: 15px; color: #a5b4fc; font-weight: 600;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Right: book grid */
|
|
55
|
+
.books {
|
|
56
|
+
display: grid;
|
|
57
|
+
grid-template-columns: repeat(5, 1fr);
|
|
58
|
+
gap: 8px;
|
|
59
|
+
width: 420px;
|
|
60
|
+
flex-shrink: 0;
|
|
61
|
+
opacity: 0.92;
|
|
62
|
+
}
|
|
63
|
+
.book {
|
|
64
|
+
aspect-ratio: 2/3;
|
|
65
|
+
border-radius: 5px;
|
|
66
|
+
background: var(--c);
|
|
67
|
+
position: relative;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
}
|
|
70
|
+
.book::after {
|
|
71
|
+
content: "";
|
|
72
|
+
position: absolute; inset: 0;
|
|
73
|
+
background: linear-gradient(135deg, rgba(255,255,255,0.08) 0%, transparent 60%);
|
|
74
|
+
}
|
|
75
|
+
/* Spine line */
|
|
76
|
+
.book::before {
|
|
77
|
+
content: "";
|
|
78
|
+
position: absolute; top: 0; bottom: 0; left: 8px;
|
|
79
|
+
width: 2px; background: rgba(0,0,0,0.2);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Fade edge on left side of book grid */
|
|
83
|
+
.books-wrap {
|
|
84
|
+
position: relative;
|
|
85
|
+
flex-shrink: 0;
|
|
86
|
+
}
|
|
87
|
+
.books-wrap::before {
|
|
88
|
+
content: "";
|
|
89
|
+
position: absolute; top: 0; bottom: 0; left: -60px;
|
|
90
|
+
width: 80px;
|
|
91
|
+
background: linear-gradient(to right, #0d0d1a, transparent);
|
|
92
|
+
z-index: 1;
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
96
|
+
</head>
|
|
97
|
+
<body>
|
|
98
|
+
<div class="left">
|
|
99
|
+
<div class="org">booklib-ai / skills</div>
|
|
100
|
+
<h1>Skills</h1>
|
|
101
|
+
<p class="tagline">Expert knowledge from 22 canonical programming books — packaged as AI agent skills.</p>
|
|
102
|
+
<div class="pills">
|
|
103
|
+
<span class="pill">22 skills</span>
|
|
104
|
+
<span class="pill">Claude Code</span>
|
|
105
|
+
<span class="pill">Cursor</span>
|
|
106
|
+
<span class="pill">Copilot</span>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="books-wrap">
|
|
111
|
+
<div class="books">
|
|
112
|
+
${[
|
|
113
|
+
"#1e3a5f","#5f1e1e","#1e5f2a","#5f4a1e","#2a1e5f",
|
|
114
|
+
"#1e4d5f","#5f1e4a","#3d5f1e","#5f3d1e","#1e5f5f",
|
|
115
|
+
"#4a1e5f","#1e5f3d","#5f5f1e","#1e2a5f","#5f1e2a",
|
|
116
|
+
"#2a5f1e","#5f2a1e","#1e5f4a","#4a5f1e","#1e4a5f",
|
|
117
|
+
"#5f1e5f","#3d1e5f","#1e5f1e","#5f3d3d","#1e3d5f",
|
|
118
|
+
"#5f4d1e","#1e4d3d","#4d1e1e","#1e1e4d","#3d5f3d",
|
|
119
|
+
].map(c => `<div class="book" style="--c:${c}"></div>`).join("")}
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</body>
|
|
123
|
+
</html>`;
|
|
124
|
+
|
|
125
|
+
let puppeteer;
|
|
126
|
+
try {
|
|
127
|
+
puppeteer = await import("puppeteer");
|
|
128
|
+
} catch {
|
|
129
|
+
// Try puppeteer-core as fallback
|
|
130
|
+
puppeteer = await import("puppeteer-core");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const browser = await puppeteer.default.launch({ headless: true });
|
|
134
|
+
const page = await browser.newPage();
|
|
135
|
+
await page.setViewport({ width: 1200, height: 630, deviceScaleFactor: 2 });
|
|
136
|
+
await page.setContent(HTML, { waitUntil: "networkidle0" });
|
|
137
|
+
const buf = await page.screenshot({ type: "png" });
|
|
138
|
+
await browser.close();
|
|
139
|
+
|
|
140
|
+
mkdirSync(dirname(OUT), { recursive: true });
|
|
141
|
+
writeFileSync(OUT, buf);
|
|
142
|
+
console.log(`Written: ${OUT} (${(buf.length / 1024).toFixed(0)} KB)`);
|
|
@@ -24,6 +24,14 @@ You are a skill selector for the `@booklib/skills` library — a collection of 1
|
|
|
24
24
|
|
|
25
25
|
## Routing Process
|
|
26
26
|
|
|
27
|
+
### Step 0 — Establish Input Scope
|
|
28
|
+
|
|
29
|
+
Before routing, pin what you're actually reviewing:
|
|
30
|
+
|
|
31
|
+
1. **Prefer `git diff` as default scope.** If the user asks to review code without specifying files, default to the current diff — not the entire codebase. Routing a skill against 10,000 lines of unchanged code wastes context and dilutes findings.
|
|
32
|
+
2. **Check for a CLAUDE.md.** If one exists, read it before routing. Project conventions (language standards, test requirements, banned patterns) affect which skill is most relevant and what the selected skill should prioritize.
|
|
33
|
+
3. **Identify the specific files or scope** from the user's message. If genuinely ambiguous, ask before routing.
|
|
34
|
+
|
|
27
35
|
### Step 1 — Classify the Work Type
|
|
28
36
|
|
|
29
37
|
Identify what the user is trying to do:
|
|
@@ -92,12 +100,18 @@ Some skill pairs can conflict. Resolve using these rules:
|
|
|
92
100
|
Format your output as:
|
|
93
101
|
|
|
94
102
|
```
|
|
103
|
+
**Scope:** [files or git diff being reviewed]
|
|
95
104
|
**Primary skill:** `skill-name`
|
|
96
105
|
**Why:** [1-2 sentence rationale tying the task to the skill's domain]
|
|
97
106
|
**Secondary (optional):** `skill-name` — [brief rationale] OR none
|
|
98
107
|
**Don't apply:** `skill-name` — [why it would produce irrelevant feedback]
|
|
99
108
|
```
|
|
100
109
|
|
|
110
|
+
When instructing the selected skill(s), tell them to:
|
|
111
|
+
- Classify each finding as **HIGH** (correctness/security/data loss), **MEDIUM** (design/maintainability), or **LOW** (style/naming)
|
|
112
|
+
- Reference findings as `file.ext:line` — not just "line 42" or "the function"
|
|
113
|
+
- Skip findings below the threshold for the work type: **review** → HIGH + MEDIUM; **migrate/design** → all tiers
|
|
114
|
+
|
|
101
115
|
If you're genuinely uncertain between two equally applicable skills, say so and recommend applying both in sequence, primary first.
|
|
102
116
|
|
|
103
117
|
---
|
|
@@ -118,28 +132,37 @@ Do NOT route to a skill if:
|
|
|
118
132
|
```
|
|
119
133
|
User: "Review my Python class for code quality"
|
|
120
134
|
|
|
135
|
+
Scope: orders/service.py (specified file)
|
|
121
136
|
Primary skill: clean-code-reviewer
|
|
122
137
|
Why: Language-agnostic code quality review is exactly Clean Code's domain — naming, functions, comments, classes.
|
|
123
138
|
Secondary: none
|
|
124
139
|
Don't apply: effective-python — Python-specific idioms are not the concern here; effective-python would focus on list comprehensions and context managers, not the general code quality issues Clean Code addresses.
|
|
140
|
+
|
|
141
|
+
→ Instruct clean-code-reviewer to classify findings as HIGH/MEDIUM/LOW and reference each as orders/service.py:line.
|
|
125
142
|
```
|
|
126
143
|
|
|
127
144
|
**Example 2 — Conflict case:**
|
|
128
145
|
```
|
|
129
146
|
User: "I'm building a new microservice for our e-commerce platform. Review the domain model."
|
|
130
147
|
|
|
148
|
+
Scope: git diff (new files in src/domain/)
|
|
131
149
|
Primary skill: domain-driven-design
|
|
132
150
|
Why: The request is about domain model design — Aggregates, Value Objects, Bounded Contexts. DDD is the authoritative source.
|
|
133
151
|
Secondary: microservices-patterns — apply after DDD review to check service boundaries, database ownership, and communication patterns.
|
|
134
152
|
Don't apply: clean-code-reviewer — code quality review is premature at the design stage; apply later when implementation code exists.
|
|
153
|
+
|
|
154
|
+
→ Instruct both skills to classify findings as HIGH/MEDIUM/LOW and reference each as file:line.
|
|
135
155
|
```
|
|
136
156
|
|
|
137
157
|
**Example 3 — Already routed (positive case):**
|
|
138
158
|
```
|
|
139
159
|
User: "Use the effective-java skill to review my builder pattern"
|
|
140
160
|
|
|
161
|
+
Scope: user specified — confirm with them if files aren't clear
|
|
141
162
|
Primary skill: effective-java (already specified by user — confirm and proceed)
|
|
142
163
|
Why: User correctly identified the skill. effective-java Item 2 covers the Builder pattern directly.
|
|
143
164
|
Secondary: none
|
|
144
165
|
Don't apply: design-patterns — GoF Builder pattern is covered, but Effective Java's opinionated take on Java-specific Builder is more directly applicable.
|
|
166
|
+
|
|
167
|
+
→ Instruct effective-java to classify findings as HIGH/MEDIUM/LOW and reference each as file:line.
|
|
145
168
|
```
|