@booklib/skills 1.2.0 → 1.3.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/CONTRIBUTING.md +122 -0
- package/README.md +20 -2
- package/ROADMAP.md +36 -0
- package/animation-at-work/evals/evals.json +44 -0
- package/animation-at-work/examples/after.md +64 -0
- package/animation-at-work/examples/before.md +35 -0
- package/animation-at-work/scripts/audit_animations.py +295 -0
- package/bin/skills.js +552 -42
- package/clean-code-reviewer/SKILL.md +109 -1
- package/clean-code-reviewer/evals/evals.json +121 -3
- package/clean-code-reviewer/examples/after.md +48 -0
- package/clean-code-reviewer/examples/before.md +33 -0
- package/clean-code-reviewer/references/api_reference.md +158 -0
- package/clean-code-reviewer/references/practices-catalog.md +282 -0
- package/clean-code-reviewer/references/review-checklist.md +254 -0
- package/clean-code-reviewer/scripts/pre-review.py +206 -0
- package/data-intensive-patterns/evals/evals.json +43 -0
- package/data-intensive-patterns/examples/after.md +61 -0
- package/data-intensive-patterns/examples/before.md +38 -0
- package/data-intensive-patterns/scripts/adr.py +213 -0
- package/data-pipelines/evals/evals.json +45 -0
- package/data-pipelines/examples/after.md +97 -0
- package/data-pipelines/examples/before.md +37 -0
- package/data-pipelines/scripts/new_pipeline.py +444 -0
- package/design-patterns/evals/evals.json +46 -0
- package/design-patterns/examples/after.md +52 -0
- package/design-patterns/examples/before.md +29 -0
- package/design-patterns/scripts/scaffold.py +807 -0
- package/domain-driven-design/SKILL.md +120 -0
- package/domain-driven-design/evals/evals.json +48 -0
- package/domain-driven-design/examples/after.md +80 -0
- package/domain-driven-design/examples/before.md +43 -0
- package/domain-driven-design/scripts/scaffold.py +421 -0
- package/effective-java/evals/evals.json +46 -0
- package/effective-java/examples/after.md +83 -0
- package/effective-java/examples/before.md +37 -0
- package/effective-java/scripts/checkstyle_setup.py +211 -0
- package/effective-kotlin/evals/evals.json +45 -0
- package/effective-kotlin/examples/after.md +36 -0
- package/effective-kotlin/examples/before.md +38 -0
- package/effective-python/evals/evals.json +44 -0
- package/effective-python/examples/after.md +56 -0
- package/effective-python/examples/before.md +40 -0
- package/effective-python/references/api_reference.md +218 -0
- package/effective-python/references/practices-catalog.md +483 -0
- package/effective-python/references/review-checklist.md +190 -0
- package/effective-python/scripts/lint.py +173 -0
- package/kotlin-in-action/evals/evals.json +43 -0
- package/kotlin-in-action/examples/after.md +53 -0
- package/kotlin-in-action/examples/before.md +39 -0
- package/kotlin-in-action/scripts/setup_detekt.py +224 -0
- package/lean-startup/evals/evals.json +43 -0
- package/lean-startup/examples/after.md +80 -0
- package/lean-startup/examples/before.md +34 -0
- package/lean-startup/scripts/new_experiment.py +286 -0
- package/microservices-patterns/SKILL.md +140 -0
- package/microservices-patterns/evals/evals.json +45 -0
- package/microservices-patterns/examples/after.md +69 -0
- package/microservices-patterns/examples/before.md +40 -0
- package/microservices-patterns/scripts/new_service.py +583 -0
- package/package.json +2 -8
- package/refactoring-ui/evals/evals.json +45 -0
- package/refactoring-ui/examples/after.md +85 -0
- package/refactoring-ui/examples/before.md +58 -0
- package/refactoring-ui/scripts/audit_css.py +250 -0
- package/skill-router/SKILL.md +142 -0
- package/skill-router/evals/evals.json +38 -0
- package/skill-router/examples/after.md +63 -0
- package/skill-router/examples/before.md +39 -0
- package/skill-router/references/api_reference.md +24 -0
- package/skill-router/references/routing-heuristics.md +89 -0
- package/skill-router/references/skill-catalog.md +156 -0
- package/skill-router/scripts/route.py +266 -0
- package/storytelling-with-data/evals/evals.json +47 -0
- package/storytelling-with-data/examples/after.md +50 -0
- package/storytelling-with-data/examples/before.md +33 -0
- package/storytelling-with-data/scripts/chart_review.py +301 -0
- package/system-design-interview/evals/evals.json +45 -0
- package/system-design-interview/examples/after.md +94 -0
- package/system-design-interview/examples/before.md +27 -0
- package/system-design-interview/scripts/new_design.py +421 -0
- package/using-asyncio-python/evals/evals.json +43 -0
- package/using-asyncio-python/examples/after.md +68 -0
- package/using-asyncio-python/examples/before.md +39 -0
- package/using-asyncio-python/scripts/check_blocking.py +270 -0
- package/web-scraping-python/evals/evals.json +46 -0
- package/web-scraping-python/examples/after.md +109 -0
- package/web-scraping-python/examples/before.md +40 -0
- package/web-scraping-python/scripts/new_scraper.py +231 -0
- /package/{effective-python-skill → effective-python}/SKILL.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-01-pythonic-thinking.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-02-lists-and-dicts.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-03-functions.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-04-comprehensions-generators.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-05-classes-interfaces.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-06-metaclasses-attributes.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-07-concurrency.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-08-robustness-performance.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-09-testing-debugging.md +0 -0
- /package/{effective-python-skill → effective-python}/ref-10-collaboration.md +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"evals": [
|
|
3
|
+
{
|
|
4
|
+
"id": "eval-01-poor-visual-hierarchy",
|
|
5
|
+
"prompt": "Review this CSS for a product card component:\n\n```css\n.product-card {\n padding: 20px;\n border: 1px solid #cccccc;\n border-radius: 4px;\n background: white;\n}\n\n.product-card .category-label {\n font-size: 16px;\n font-weight: 400;\n color: #333333;\n margin-bottom: 8px;\n}\n\n.product-card .product-name {\n font-size: 18px;\n font-weight: 400;\n color: #333333;\n margin-bottom: 8px;\n}\n\n.product-card .product-price {\n font-size: 16px;\n font-weight: 400;\n color: #333333;\n margin-bottom: 8px;\n}\n\n.product-card .product-description {\n font-size: 15px;\n font-weight: 400;\n color: #333333;\n margin-bottom: 12px;\n}\n\n.product-card .stock-status {\n font-size: 14px;\n font-weight: 400;\n color: #333333;\n}\n\n.product-card .add-to-cart-btn {\n font-size: 16px;\n font-weight: 400;\n background: #333333;\n color: white;\n padding: 10px 20px;\n border: none;\n border-radius: 4px;\n margin-top: 12px;\n}\n```",
|
|
6
|
+
"expectations": [
|
|
7
|
+
"Identifies the core problem: visual hierarchy is flat — nearly every element uses the same font-size (15-18px) and font-weight (400), making it impossible to identify what matters most at a glance",
|
|
8
|
+
"Flags that the product name should be the most visually prominent element — it should use a larger size (24-30px) and heavier weight (600-700) to create a clear entry point",
|
|
9
|
+
"Flags that the price is the second most important element — it should be visually distinct, not the same weight as the description",
|
|
10
|
+
"Points out that category-label should be de-emphasized (smaller, lighter color like hsl(0,0%,55%)) — it is supporting context, not primary information",
|
|
11
|
+
"Notes that relying on font-size alone for hierarchy is addressed in Chapter 2 of Refactoring UI: use weight and color as primary levers, size as secondary",
|
|
12
|
+
"Flags that all elements use the same color (#333333) — tertiary elements like category-label and stock-status should use a lighter grey to create visual separation",
|
|
13
|
+
"Notes the add-to-cart button has font-weight: 400 — a primary action button should use font-weight 500-600 for emphasis",
|
|
14
|
+
"Recommends a concrete hierarchy: product-name (24px, 700 weight, dark), price (20px, 600 weight, dark), description (15px, 400 weight, medium grey #6b7280), category-label (12px, 500 weight, uppercase, light grey)"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "eval-02-too-many-colors-no-spacing-system",
|
|
19
|
+
"prompt": "Review this CSS for a dashboard sidebar:\n\n```css\n.sidebar {\n background: #1a237e;\n padding: 15px;\n width: 240px;\n}\n\n.sidebar-header {\n color: #ffffff;\n font-size: 22px;\n margin-bottom: 7px;\n padding-bottom: 11px;\n border-bottom: 2px solid #3949ab;\n}\n\n.nav-item {\n color: #b0bec5;\n font-size: 14px;\n padding: 9px 13px;\n margin-bottom: 3px;\n border-radius: 6px;\n}\n\n.nav-item.active {\n background: #ff6f00;\n color: #ffffff;\n}\n\n.nav-item:hover {\n background: #283593;\n color: #e8eaf6;\n}\n\n.nav-section-label {\n color: #ffd54f;\n font-size: 11px;\n text-transform: uppercase;\n margin-top: 18px;\n margin-bottom: 6px;\n letter-spacing: 1px;\n}\n\n.badge {\n background: #e53935;\n color: white;\n font-size: 10px;\n padding: 2px 7px;\n border-radius: 10px;\n}\n\n.sidebar-footer {\n margin-top: 23px;\n padding-top: 14px;\n border-top: 1px solid #303f9f;\n color: #90a4ae;\n font-size: 13px;\n}\n```",
|
|
20
|
+
"expectations": [
|
|
21
|
+
"Identifies the color proliferation problem: #1a237e, #3949ab, #ff6f00, #b0bec5, #283593, #e8eaf6, #ffd54f, #e53935, #303f9f, #90a4ae — 10+ ad-hoc hex colors with no systematic relationship",
|
|
22
|
+
"Flags that the active state uses #ff6f00 (deep orange) which is unrelated to the #1a237e (indigo) background — the accent color should be a lighter tint of the primary palette or a purposeful brand color",
|
|
23
|
+
"Flags that nav-section-label uses #ffd54f (amber/yellow) as a color — this creates a third unrelated hue in the sidebar; section labels should use a desaturated light color consistent with the palette",
|
|
24
|
+
"Flags the arbitrary spacing values: 7px, 11px, 9px, 13px, 3px, 18px, 6px, 23px, 14px — none of these follow a spacing scale; Refactoring UI Ch 3 prescribes a constrained scale (4, 8, 12, 16, 24, 32px)",
|
|
25
|
+
"Notes that grey-on-deep-blue text (#b0bec5 on #1a237e) needs a contrast check — and recommends using a color that is hue-matched to the background rather than a neutral grey",
|
|
26
|
+
"Recommends defining a design token set: 2-3 shades of indigo for the sidebar tones, one accent color for the active state, one semantic red for the badge — not 10 unrelated hex values",
|
|
27
|
+
"Notes that the badge using an unrelated red (#e53935) is fine for semantic meaning but should be defined as a token (--color-danger) rather than a hard-coded hex"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "eval-03-clean-hierarchy-design",
|
|
32
|
+
"prompt": "Review this CSS for a pricing card component:\n\n```css\n:root {\n --space-1: 4px;\n --space-2: 8px;\n --space-3: 12px;\n --space-4: 16px;\n --space-6: 24px;\n --space-8: 32px;\n --space-12: 48px;\n\n --text-sm: 13px;\n --text-base: 16px;\n --text-lg: 18px;\n --text-xl: 20px;\n --text-3xl: 30px;\n\n --color-text-primary: hsl(222, 47%, 11%);\n --color-text-secondary: hsl(215, 20%, 40%);\n --color-text-tertiary: hsl(215, 16%, 60%);\n --color-accent: hsl(245, 75%, 60%);\n --color-accent-light: hsl(245, 75%, 96%);\n}\n\n.pricing-card {\n background: white;\n border-radius: 12px;\n padding: var(--space-8);\n box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);\n max-width: 320px;\n}\n\n.plan-name {\n font-size: var(--text-sm);\n font-weight: 600;\n color: var(--color-accent);\n text-transform: uppercase;\n letter-spacing: 0.08em;\n margin-bottom: var(--space-3);\n}\n\n.plan-price {\n font-size: var(--text-3xl);\n font-weight: 700;\n color: var(--color-text-primary);\n margin-bottom: var(--space-1);\n}\n\n.price-period {\n font-size: var(--text-sm);\n color: var(--color-text-tertiary);\n margin-bottom: var(--space-6);\n}\n\n.feature-list {\n list-style: none;\n padding: 0;\n margin: 0 0 var(--space-8) 0;\n}\n\n.feature-item {\n font-size: var(--text-base);\n color: var(--color-text-secondary);\n padding: var(--space-2) 0;\n display: flex;\n align-items: center;\n gap: var(--space-3);\n}\n\n.cta-button {\n display: block;\n width: 100%;\n padding: var(--space-3) var(--space-6);\n background: var(--color-accent);\n color: white;\n font-size: var(--text-base);\n font-weight: 600;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n text-align: center;\n}\n```",
|
|
33
|
+
"expectations": [
|
|
34
|
+
"Recognizes this as a well-designed component with proper design system foundations and says so explicitly",
|
|
35
|
+
"Praises the CSS custom property (design token) system: spacing scale (--space-1 through --space-12 in steps of 4px), type scale (--text-sm through --text-3xl), and color tokens all follow Refactoring UI principles",
|
|
36
|
+
"Praises the three-level color hierarchy for text: --color-text-primary (dark), --color-text-secondary (medium), --color-text-tertiary (light) — directly implementing the Refactoring UI color-as-hierarchy approach",
|
|
37
|
+
"Praises the visual hierarchy of the price card: plan name is small+uppercase+accent (supporting), price is 30px+700 weight (primary), period is small+tertiary (de-emphasized) — excellent three-tier hierarchy",
|
|
38
|
+
"Praises the shadow: uses a two-layer shadow (diffuse + tight) following the Refactoring UI recommendation for realistic depth",
|
|
39
|
+
"Praises that plan-name uses color (--color-accent) to create emphasis at a small size rather than making it large — using color+weight as levers, not font-size alone",
|
|
40
|
+
"Does NOT manufacture fake issues just to have something to say",
|
|
41
|
+
"May offer optional improvements (hover state for cta-button, dark mode token variants, focus ring for accessibility) but clearly frames them as enhancements"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# After
|
|
2
|
+
|
|
3
|
+
A pricing card with clear visual hierarchy achieved through size scale, weight contrast, and strategic color — the price is immediately scannable and the CTA stands out.
|
|
4
|
+
|
|
5
|
+
```css
|
|
6
|
+
/* Pricing card — clear hierarchy: plan name → price → description → features → CTA */
|
|
7
|
+
.pricing-card {
|
|
8
|
+
padding: 32px;
|
|
9
|
+
border-radius: 8px;
|
|
10
|
+
background: #ffffff;
|
|
11
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07), 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* Primary: the plan name — bold, medium size, dark */
|
|
15
|
+
.plan-name {
|
|
16
|
+
font-size: 14px;
|
|
17
|
+
font-weight: 600;
|
|
18
|
+
letter-spacing: 0.06em;
|
|
19
|
+
text-transform: uppercase;
|
|
20
|
+
color: hsl(217, 71%, 53%); /* brand accent — signals plan identity */
|
|
21
|
+
margin-bottom: 12px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Hero element: price — the largest, heaviest thing on the card */
|
|
25
|
+
.plan-price {
|
|
26
|
+
font-size: 48px;
|
|
27
|
+
font-weight: 700;
|
|
28
|
+
color: hsl(222, 47%, 11%); /* near-black — maximum contrast */
|
|
29
|
+
line-height: 1;
|
|
30
|
+
margin-bottom: 4px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.plan-billing-cycle {
|
|
34
|
+
font-size: 13px;
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
color: hsl(215, 16%, 57%); /* light grey — tertiary, supporting */
|
|
37
|
+
margin-bottom: 20px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Secondary: description — readable but not competing with price */
|
|
41
|
+
.plan-description {
|
|
42
|
+
font-size: 15px;
|
|
43
|
+
font-weight: 400;
|
|
44
|
+
color: hsl(215, 16%, 40%); /* medium grey */
|
|
45
|
+
line-height: 1.6;
|
|
46
|
+
margin-bottom: 24px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Tertiary: feature list — smallest, least emphasis */
|
|
50
|
+
.plan-feature {
|
|
51
|
+
font-size: 14px;
|
|
52
|
+
font-weight: 400;
|
|
53
|
+
color: hsl(215, 16%, 47%);
|
|
54
|
+
margin-bottom: 8px;
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
gap: 8px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* CTA: high contrast, full width, inviting */
|
|
61
|
+
.cta-button {
|
|
62
|
+
width: 100%;
|
|
63
|
+
padding: 14px;
|
|
64
|
+
font-size: 15px;
|
|
65
|
+
font-weight: 600;
|
|
66
|
+
background-color: hsl(217, 71%, 53%);
|
|
67
|
+
color: #ffffff;
|
|
68
|
+
border: none;
|
|
69
|
+
border-radius: 6px;
|
|
70
|
+
margin-top: 28px;
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.cta-button:hover {
|
|
75
|
+
background-color: hsl(217, 71%, 46%);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Key improvements:
|
|
80
|
+
- Three-tier hierarchy established using size (48px → 15px → 14px → 13px), weight (700 → 600 → 400), and color (near-black → medium grey → light grey) — no element competes with the price (Ch 2: Visual Hierarchy)
|
|
81
|
+
- HSL colors replace raw hex — the system is transparent and the grey scale is predictable (Ch 5: Build a color system with HSL)
|
|
82
|
+
- `box-shadow` with two layered shadows replaces the flat `border: 1px solid #ccc` — the card lifts off the page with realistic depth (Ch 6: Depth and shadow elevation)
|
|
83
|
+
- `.plan-name` uses uppercase + letter-spacing as a tertiary-element technique — it occupies a clear role without competing with the price despite appearing first (Ch 2: De-emphasize labels, emphasize values)
|
|
84
|
+
- Consistent spacing from the scale (12, 20, 24, 28px) replaces arbitrary margins — related elements are visually grouped (Ch 3: Spacing and layout)
|
|
85
|
+
- CTA `padding: 14px` and `font-weight: 600` make the button unmistakably actionable, distinct from all other text on the card (Ch 8: Finishing touches)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Before
|
|
2
|
+
|
|
3
|
+
A CSS card component where every text element is the same size and weight, creating no visual hierarchy and making it impossible to scan at a glance.
|
|
4
|
+
|
|
5
|
+
```css
|
|
6
|
+
/* Pricing card — everything looks equally important */
|
|
7
|
+
.pricing-card {
|
|
8
|
+
padding: 20px;
|
|
9
|
+
border: 1px solid #ccc;
|
|
10
|
+
border-radius: 4px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.plan-name {
|
|
14
|
+
font-size: 16px;
|
|
15
|
+
font-weight: 400;
|
|
16
|
+
color: #333;
|
|
17
|
+
margin-bottom: 8px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.plan-description {
|
|
21
|
+
font-size: 16px;
|
|
22
|
+
font-weight: 400;
|
|
23
|
+
color: #333;
|
|
24
|
+
margin-bottom: 8px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.plan-price {
|
|
28
|
+
font-size: 16px;
|
|
29
|
+
font-weight: 400;
|
|
30
|
+
color: #333;
|
|
31
|
+
margin-bottom: 8px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.plan-billing-cycle {
|
|
35
|
+
font-size: 16px;
|
|
36
|
+
font-weight: 400;
|
|
37
|
+
color: #333;
|
|
38
|
+
margin-bottom: 16px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.plan-feature {
|
|
42
|
+
font-size: 16px;
|
|
43
|
+
font-weight: 400;
|
|
44
|
+
color: #333;
|
|
45
|
+
margin-bottom: 4px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.cta-button {
|
|
49
|
+
width: 100%;
|
|
50
|
+
padding: 10px;
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
font-weight: 400;
|
|
53
|
+
background-color: #555;
|
|
54
|
+
color: white;
|
|
55
|
+
border: none;
|
|
56
|
+
border-radius: 4px;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
audit_css.py — Audit CSS/SCSS/HTML files for Refactoring UI anti-patterns.
|
|
4
|
+
Usage: python audit_css.py <file_or_directory>
|
|
5
|
+
|
|
6
|
+
Detects:
|
|
7
|
+
1. One-off hex colors (likely not from a design scale)
|
|
8
|
+
2. Arbitrary pixel values not on a standard spacing scale
|
|
9
|
+
3. Flat visual hierarchy (too many elements sharing the same font-size)
|
|
10
|
+
4. Inline styles in HTML (maintainability anti-pattern)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
import sys
|
|
15
|
+
from collections import defaultdict
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
# Configuration
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
SPACING_SCALE = {4, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 80, 96, 112, 128}
|
|
23
|
+
FLAT_HIERARCHY_THRESHOLD = 3 # more than N elements sharing same font-size
|
|
24
|
+
EXTENSIONS = {".css", ".scss", ".html", ".htm"}
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Regex patterns
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
RE_HEX_COLOR = re.compile(r"#([0-9a-fA-F]{3,8})\b")
|
|
31
|
+
RE_PX_VALUE = re.compile(r"\b(\d+)px\b")
|
|
32
|
+
RE_FONT_SIZE_PX = re.compile(r"font-size\s*:\s*(\d+)px", re.IGNORECASE)
|
|
33
|
+
RE_INLINE_STYLE = re.compile(r'\bstyle\s*=\s*["\'][^"\']*["\']', re.IGNORECASE)
|
|
34
|
+
RE_CSS_VAR = re.compile(r"var\(--[^)]+\)")
|
|
35
|
+
RE_SCSS_VAR = re.compile(r"\$[a-zA-Z_][\w-]*")
|
|
36
|
+
|
|
37
|
+
# Pixel properties where arbitrary values matter (spacing/sizing, not borders)
|
|
38
|
+
SPACING_PROPERTIES = re.compile(
|
|
39
|
+
r"(margin|padding|top|right|bottom|left|width|height|gap|"
|
|
40
|
+
r"border-radius|letter-spacing|line-height)\s*:",
|
|
41
|
+
re.IGNORECASE,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
# Helpers
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
Issue = dict # {"line": int, "col": int, "code": str, "message": str, "suggestion": str}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def read_lines(path: Path) -> list[str]:
|
|
52
|
+
try:
|
|
53
|
+
return path.read_text(encoding="utf-8", errors="replace").splitlines()
|
|
54
|
+
except OSError as exc:
|
|
55
|
+
print(f"Warning: cannot read {path}: {exc}")
|
|
56
|
+
return []
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def is_in_comment(line: str, col: int) -> bool:
|
|
60
|
+
"""Rough check: is the match inside a CSS/HTML comment on this line?"""
|
|
61
|
+
before = line[:col]
|
|
62
|
+
return "/*" in before or "<!--" in before or "//" in before
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ---------------------------------------------------------------------------
|
|
66
|
+
# Detectors
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
def detect_one_off_hex_colors(lines: list[str], filepath: Path) -> list[Issue]:
|
|
70
|
+
"""Flag hex colors that appear only once in the file — likely not from a scale."""
|
|
71
|
+
color_locations: dict[str, list[tuple[int, int]]] = defaultdict(list)
|
|
72
|
+
for lineno, line in enumerate(lines, 1):
|
|
73
|
+
for m in RE_HEX_COLOR.finditer(line):
|
|
74
|
+
# Skip if preceded by var( or $ (already a token)
|
|
75
|
+
prefix = line[max(0, m.start() - 10):m.start()]
|
|
76
|
+
if "var(" in prefix or "$" in prefix[-1:]:
|
|
77
|
+
continue
|
|
78
|
+
normalized = m.group(0).upper()
|
|
79
|
+
color_locations[normalized].append((lineno, m.start()))
|
|
80
|
+
|
|
81
|
+
issues = []
|
|
82
|
+
for color, locations in color_locations.items():
|
|
83
|
+
if len(locations) == 1:
|
|
84
|
+
lineno, col = locations[0]
|
|
85
|
+
issues.append({
|
|
86
|
+
"line": lineno, "col": col + 1,
|
|
87
|
+
"code": "RUI-C01",
|
|
88
|
+
"message": f"One-off color {color} — not reused anywhere in this file",
|
|
89
|
+
"suggestion": f"Extract to a CSS variable: --color-name: {color}; and reference via var(--color-name)",
|
|
90
|
+
})
|
|
91
|
+
return issues
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def detect_arbitrary_px_values(lines: list[str], filepath: Path) -> list[Issue]:
|
|
95
|
+
"""Flag pixel values on spacing properties that fall outside the spacing scale."""
|
|
96
|
+
issues = []
|
|
97
|
+
in_spacing_context = False
|
|
98
|
+
for lineno, line in enumerate(lines, 1):
|
|
99
|
+
stripped = line.strip()
|
|
100
|
+
if SPACING_PROPERTIES.search(stripped):
|
|
101
|
+
for m in RE_PX_VALUE.finditer(stripped):
|
|
102
|
+
value = int(m.group(1))
|
|
103
|
+
if value == 0 or value in SPACING_SCALE:
|
|
104
|
+
continue
|
|
105
|
+
if is_in_comment(line, m.start()):
|
|
106
|
+
continue
|
|
107
|
+
nearest = min(SPACING_SCALE, key=lambda s: abs(s - value))
|
|
108
|
+
issues.append({
|
|
109
|
+
"line": lineno, "col": m.start() + 1,
|
|
110
|
+
"code": "RUI-S01",
|
|
111
|
+
"message": f"Arbitrary pixel value {value}px not on spacing scale",
|
|
112
|
+
"suggestion": f"Nearest scale value: {nearest}px. Consider using a spacing token.",
|
|
113
|
+
})
|
|
114
|
+
return issues
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def detect_flat_hierarchy(lines: list[str], filepath: Path) -> list[Issue]:
|
|
118
|
+
"""Flag when many rules share the same font-size — suggests flat visual hierarchy."""
|
|
119
|
+
size_locations: dict[int, list[tuple[int, int]]] = defaultdict(list)
|
|
120
|
+
for lineno, line in enumerate(lines, 1):
|
|
121
|
+
for m in RE_FONT_SIZE_PX.finditer(line):
|
|
122
|
+
size = int(m.group(1))
|
|
123
|
+
size_locations[size].append((lineno, m.start()))
|
|
124
|
+
|
|
125
|
+
issues = []
|
|
126
|
+
for size, locations in size_locations.items():
|
|
127
|
+
if len(locations) > FLAT_HIERARCHY_THRESHOLD:
|
|
128
|
+
# Report at the first occurrence
|
|
129
|
+
lineno, col = locations[0]
|
|
130
|
+
issues.append({
|
|
131
|
+
"line": lineno, "col": col + 1,
|
|
132
|
+
"code": "RUI-H01",
|
|
133
|
+
"message": (
|
|
134
|
+
f"font-size: {size}px used {len(locations)} times — "
|
|
135
|
+
f"indicates flat visual hierarchy"
|
|
136
|
+
),
|
|
137
|
+
"suggestion": (
|
|
138
|
+
"Refactoring UI: vary font sizes more aggressively to create "
|
|
139
|
+
"clear hierarchy. Use a type scale (e.g. 12, 14, 16, 20, 24, 32, 48px)."
|
|
140
|
+
),
|
|
141
|
+
})
|
|
142
|
+
return issues
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def detect_inline_styles(lines: list[str], filepath: Path) -> list[Issue]:
|
|
146
|
+
"""Flag inline style= attributes in HTML files."""
|
|
147
|
+
if filepath.suffix.lower() not in {".html", ".htm"}:
|
|
148
|
+
return []
|
|
149
|
+
issues = []
|
|
150
|
+
for lineno, line in enumerate(lines, 1):
|
|
151
|
+
for m in RE_INLINE_STYLE.finditer(line):
|
|
152
|
+
issues.append({
|
|
153
|
+
"line": lineno, "col": m.start() + 1,
|
|
154
|
+
"code": "RUI-M01",
|
|
155
|
+
"message": f"Inline style attribute — hard to maintain and override",
|
|
156
|
+
"suggestion": "Move styles to a CSS class. Inline styles defeat cascade and make theming impossible.",
|
|
157
|
+
})
|
|
158
|
+
return issues
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# ---------------------------------------------------------------------------
|
|
162
|
+
# Scanner
|
|
163
|
+
# ---------------------------------------------------------------------------
|
|
164
|
+
|
|
165
|
+
def scan_file(path: Path) -> list[Issue]:
|
|
166
|
+
lines = read_lines(path)
|
|
167
|
+
if not lines:
|
|
168
|
+
return []
|
|
169
|
+
issues = []
|
|
170
|
+
issues.extend(detect_one_off_hex_colors(lines, path))
|
|
171
|
+
issues.extend(detect_arbitrary_px_values(lines, path))
|
|
172
|
+
issues.extend(detect_flat_hierarchy(lines, path))
|
|
173
|
+
issues.extend(detect_inline_styles(lines, path))
|
|
174
|
+
return sorted(issues, key=lambda i: (i["line"], i["col"]))
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def collect_files(target: Path) -> list[Path]:
|
|
178
|
+
if target.is_file():
|
|
179
|
+
return [target] if target.suffix.lower() in EXTENSIONS else []
|
|
180
|
+
return sorted(p for p in target.rglob("*") if p.suffix.lower() in EXTENSIONS)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
# ---------------------------------------------------------------------------
|
|
184
|
+
# Report
|
|
185
|
+
# ---------------------------------------------------------------------------
|
|
186
|
+
|
|
187
|
+
def print_report(results: dict[Path, list[Issue]]) -> int:
|
|
188
|
+
total = sum(len(v) for v in results.values())
|
|
189
|
+
files_with_issues = sum(1 for v in results.values() if v)
|
|
190
|
+
|
|
191
|
+
print("=" * 72)
|
|
192
|
+
print("REFACTORING UI CSS AUDIT REPORT")
|
|
193
|
+
print("=" * 72)
|
|
194
|
+
|
|
195
|
+
# Group by code across all files for summary
|
|
196
|
+
by_code: dict[str, list[tuple[Path, Issue]]] = defaultdict(list)
|
|
197
|
+
|
|
198
|
+
for path, issues in results.items():
|
|
199
|
+
if not issues:
|
|
200
|
+
continue
|
|
201
|
+
print(f"\n{path}")
|
|
202
|
+
print("-" * 72)
|
|
203
|
+
for issue in issues:
|
|
204
|
+
print(f" Line {issue['line']:>4}:{issue['col']:<4} [{issue['code']}] {issue['message']}")
|
|
205
|
+
print(f" -> {issue['suggestion']}")
|
|
206
|
+
by_code[issue["code"]].append((path, issue))
|
|
207
|
+
|
|
208
|
+
print("\n" + "=" * 72)
|
|
209
|
+
print("SUMMARY")
|
|
210
|
+
print("=" * 72)
|
|
211
|
+
CODE_LABELS = {
|
|
212
|
+
"RUI-C01": "One-off colors (not from a scale)",
|
|
213
|
+
"RUI-S01": "Arbitrary pixel values",
|
|
214
|
+
"RUI-H01": "Flat visual hierarchy",
|
|
215
|
+
"RUI-M01": "Inline styles in HTML",
|
|
216
|
+
}
|
|
217
|
+
for code, label in CODE_LABELS.items():
|
|
218
|
+
count = len(by_code.get(code, []))
|
|
219
|
+
marker = "[!]" if count else "[OK]"
|
|
220
|
+
print(f" {marker} {label}: {count} issue(s)")
|
|
221
|
+
|
|
222
|
+
print(f"\nFiles scanned : {len(results)}")
|
|
223
|
+
print(f"Files with issues: {files_with_issues}")
|
|
224
|
+
print(f"Total issues : {total}")
|
|
225
|
+
print("=" * 72)
|
|
226
|
+
return total
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def main():
|
|
230
|
+
if len(sys.argv) < 2:
|
|
231
|
+
print("Usage: python audit_css.py <file_or_directory>")
|
|
232
|
+
sys.exit(1)
|
|
233
|
+
|
|
234
|
+
target = Path(sys.argv[1])
|
|
235
|
+
if not target.exists():
|
|
236
|
+
print(f"Error: path not found: {target}")
|
|
237
|
+
sys.exit(1)
|
|
238
|
+
|
|
239
|
+
files = collect_files(target)
|
|
240
|
+
if not files:
|
|
241
|
+
print(f"No CSS/SCSS/HTML files found in: {target}")
|
|
242
|
+
sys.exit(0)
|
|
243
|
+
|
|
244
|
+
results = {f: scan_file(f) for f in files}
|
|
245
|
+
total = print_report(results)
|
|
246
|
+
sys.exit(1 if total else 0)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if __name__ == "__main__":
|
|
250
|
+
main()
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill-router
|
|
3
|
+
description: >
|
|
4
|
+
Select the 1-2 most relevant @booklib/skills for a given file, PR, or task.
|
|
5
|
+
Use before applying any skill when unsure which book's lens applies, or when
|
|
6
|
+
multiple skills could apply. Trigger on "which skill", "which book", "route this",
|
|
7
|
+
"what skill should I use", or whenever a user describes a task without specifying
|
|
8
|
+
a skill. Returns a ranked recommendation with rationale and anti-triggers.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Skill Router
|
|
12
|
+
|
|
13
|
+
You are a skill selector for the `@booklib/skills` library — a collection of 17 book-based AI skills covering code quality, architecture, language best practices, and design. Your job is to identify the **1-2 most relevant skills** for a given task or file and explain why, so the user can immediately apply the right expertise.
|
|
14
|
+
|
|
15
|
+
## When You're Triggered
|
|
16
|
+
|
|
17
|
+
- User says "which skill should I use for..."
|
|
18
|
+
- User says "route this to the right skill"
|
|
19
|
+
- User describes a task without naming a skill
|
|
20
|
+
- User asks "what book applies here?"
|
|
21
|
+
- Multiple skills seem to apply and you need to rank them
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Routing Process
|
|
26
|
+
|
|
27
|
+
### Step 1 — Classify the Work Type
|
|
28
|
+
|
|
29
|
+
Identify what the user is trying to do:
|
|
30
|
+
|
|
31
|
+
| Work Type | Description | Example |
|
|
32
|
+
|-----------|-------------|---------|
|
|
33
|
+
| **review** | Evaluate existing code for quality, patterns, or correctness | "Review my Python class" |
|
|
34
|
+
| **generate** | Create new code following a book's patterns | "Generate a saga for order processing" |
|
|
35
|
+
| **migrate** | Incrementally improve legacy code toward a better architecture | "Help me ratchet this legacy codebase toward clean code" |
|
|
36
|
+
| **design** | Make architectural or system-level decisions | "How should I decompose this monolith?" |
|
|
37
|
+
| **learn** | Understand a concept or pattern | "What is the Strangler Fig pattern?" |
|
|
38
|
+
| **visualize** | Create or critique data visualizations or UI | "Review my chart / UI component" |
|
|
39
|
+
|
|
40
|
+
### Step 2 — Identify Language + Domain
|
|
41
|
+
|
|
42
|
+
From the file extension, imports, description, or code provided:
|
|
43
|
+
|
|
44
|
+
- **Language signals:** `.py` → Python skills; `.java` → `effective-java` or `clean-code-reviewer`; `.kt` → `effective-kotlin` or `kotlin-in-action`; `.js`/`.ts` → `clean-code-reviewer` or `design-patterns`
|
|
45
|
+
- **Domain signals:** "microservice", "saga" → microservices-patterns; "bounded context", "aggregate" → domain-driven-design; "chart", "visualization" → storytelling-with-data; "UI", "layout", "typography" → refactoring-ui; "web scraping", "BeautifulSoup" → web-scraping-python; "asyncio", "coroutine" → using-asyncio-python; "data pipeline", "ETL" → data-pipelines; "replication", "partitioning", "database internals" → data-intensive-patterns
|
|
46
|
+
- **Architecture signals:** "monolith decomposition", "distributed systems" → microservices-patterns or system-design-interview
|
|
47
|
+
|
|
48
|
+
Read `references/skill-catalog.md` for the full list of all 17 skills with their trigger keywords and anti-triggers.
|
|
49
|
+
|
|
50
|
+
### Step 3 — Match to Skill(s)
|
|
51
|
+
|
|
52
|
+
Apply these primary routing rules:
|
|
53
|
+
|
|
54
|
+
1. **Code quality review (any language)** → `clean-code-reviewer`
|
|
55
|
+
2. **Java best practices** → `effective-java`
|
|
56
|
+
3. **Kotlin best practices** → `effective-kotlin` or `kotlin-in-action` (see conflict rules)
|
|
57
|
+
4. **Python best practices** → `effective-python`
|
|
58
|
+
5. **Python asyncio/concurrency** → `using-asyncio-python` (overrides effective-python for async topics)
|
|
59
|
+
6. **Python web scraping** → `web-scraping-python`
|
|
60
|
+
7. **OO design patterns (GoF)** → `design-patterns`
|
|
61
|
+
8. **Domain modeling, DDD** → `domain-driven-design`
|
|
62
|
+
9. **Microservices, sagas, decomposition** → `microservices-patterns`
|
|
63
|
+
10. **System scalability, estimation** → `system-design-interview`
|
|
64
|
+
11. **Data storage internals, replication** → `data-intensive-patterns`
|
|
65
|
+
12. **Data pipelines, ETL** → `data-pipelines`
|
|
66
|
+
13. **UI design, visual hierarchy** → `refactoring-ui`
|
|
67
|
+
14. **Charts, data visualization** → `storytelling-with-data`
|
|
68
|
+
15. **Web animation** → `animation-at-work`
|
|
69
|
+
16. **Startup strategy, MVP** → `lean-startup`
|
|
70
|
+
17. **Routing help** → `skill-router` (this skill)
|
|
71
|
+
|
|
72
|
+
Read `references/routing-heuristics.md` for detailed decision rules and conflict resolution.
|
|
73
|
+
|
|
74
|
+
### Step 4 — Check for Conflicts
|
|
75
|
+
|
|
76
|
+
Some skill pairs can conflict. Resolve using these rules:
|
|
77
|
+
|
|
78
|
+
| Conflict | Resolution |
|
|
79
|
+
|----------|------------|
|
|
80
|
+
| `clean-code-reviewer` vs `effective-java` | Use `effective-java` for Java-specific idioms (generics, enums, builders); use `clean-code-reviewer` for naming/functions/readability which applies cross-language |
|
|
81
|
+
| `effective-kotlin` vs `kotlin-in-action` | `effective-kotlin` for best practices and pitfall avoidance; `kotlin-in-action` for learning Kotlin language features |
|
|
82
|
+
| `domain-driven-design` vs `microservices-patterns` | `domain-driven-design` for domain model design; `microservices-patterns` for service decomposition and inter-service communication. Apply both if designing a new microservice with rich domain model |
|
|
83
|
+
| `clean-code-reviewer` vs `domain-driven-design` | Clean Code says "small functions"; DDD encourages "rich domain models." Clean Code wins for code-level review; DDD wins for model design |
|
|
84
|
+
| `data-intensive-patterns` vs `system-design-interview` | `data-intensive-patterns` for storage engine internals, replication, and consistency; `system-design-interview` for scalability estimates and high-level architecture |
|
|
85
|
+
| `effective-python` vs `using-asyncio-python` | `using-asyncio-python` wins for any async/concurrent Python topic; `effective-python` for everything else |
|
|
86
|
+
|
|
87
|
+
### Step 5 — Return Recommendation
|
|
88
|
+
|
|
89
|
+
Format your output as:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
**Primary skill:** `skill-name`
|
|
93
|
+
**Why:** [1-2 sentence rationale tying the task to the skill's domain]
|
|
94
|
+
**Secondary (optional):** `skill-name` — [brief rationale] OR none
|
|
95
|
+
**Don't apply:** `skill-name` — [why it would produce irrelevant feedback]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If you're genuinely uncertain between two equally applicable skills, say so and recommend applying both in sequence, primary first.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Anti-Trigger Rules
|
|
103
|
+
|
|
104
|
+
Do NOT route to a skill if:
|
|
105
|
+
- The task is too simple for that skill's complexity (don't route a 5-line script to `domain-driven-design`)
|
|
106
|
+
- The language doesn't match (don't route Python to `effective-java`)
|
|
107
|
+
- The domain doesn't match (don't route UI code to `microservices-patterns`)
|
|
108
|
+
- The user has already specified a skill (respect their choice; only offer alternatives if asked)
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Examples
|
|
113
|
+
|
|
114
|
+
**Example 1 — Clear single-skill case:**
|
|
115
|
+
```
|
|
116
|
+
User: "Review my Python class for code quality"
|
|
117
|
+
|
|
118
|
+
Primary skill: clean-code-reviewer
|
|
119
|
+
Why: Language-agnostic code quality review is exactly Clean Code's domain — naming, functions, comments, classes.
|
|
120
|
+
Secondary: none
|
|
121
|
+
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.
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Example 2 — Conflict case:**
|
|
125
|
+
```
|
|
126
|
+
User: "I'm building a new microservice for our e-commerce platform. Review the domain model."
|
|
127
|
+
|
|
128
|
+
Primary skill: domain-driven-design
|
|
129
|
+
Why: The request is about domain model design — Aggregates, Value Objects, Bounded Contexts. DDD is the authoritative source.
|
|
130
|
+
Secondary: microservices-patterns — apply after DDD review to check service boundaries, database ownership, and communication patterns.
|
|
131
|
+
Don't apply: clean-code-reviewer — code quality review is premature at the design stage; apply later when implementation code exists.
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Example 3 — Already routed (positive case):**
|
|
135
|
+
```
|
|
136
|
+
User: "Use the effective-java skill to review my builder pattern"
|
|
137
|
+
|
|
138
|
+
Primary skill: effective-java (already specified by user — confirm and proceed)
|
|
139
|
+
Why: User correctly identified the skill. effective-java Item 2 covers the Builder pattern directly.
|
|
140
|
+
Secondary: none
|
|
141
|
+
Don't apply: design-patterns — GoF Builder pattern is covered, but Effective Java's opinionated take on Java-specific Builder is more directly applicable.
|
|
142
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"evals": [
|
|
3
|
+
{
|
|
4
|
+
"id": "eval-01-clear-single-skill",
|
|
5
|
+
"prompt": "Which skill should I use? I have this Python function and want to make it more Pythonic:\n\n```python\ndef get_items(items_list, filter_value, sort_by_name):\n result = []\n for item in items_list:\n if item['category'] == filter_value:\n result.append(item)\n if sort_by_name:\n result = sorted(result, key=lambda x: x['name'])\n return result\n```",
|
|
6
|
+
"expectations": [
|
|
7
|
+
"Recommends effective-python as primary skill",
|
|
8
|
+
"Mentions that Pythonic idioms (list comprehensions, key functions, boolean flags) are effective-python's domain",
|
|
9
|
+
"Does NOT recommend clean-code-reviewer as primary (it's secondary at most)",
|
|
10
|
+
"Explains why (language-specific Pythonic advice vs general code quality)",
|
|
11
|
+
"Optionally mentions clean-code-reviewer as secondary for the flag argument (sort_by_name)"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "eval-02-conflict-case",
|
|
16
|
+
"prompt": "I'm designing a new service for our e-commerce platform. The service will handle order creation and needs to coordinate with the inventory and payment services. Here's a rough sketch:\n\n```python\nclass OrderService:\n def create_order(self, customer_id, items):\n # 1. Check inventory availability\n # 2. Reserve inventory\n # 3. Charge payment\n # If payment fails, how do I release the reservation?\n pass\n\n def cancel_order(self, order_id):\n # Need to reverse payment AND release inventory\n # What if one fails?\n pass\n```\n\nWhich skill should I use to design this coordination correctly?",
|
|
17
|
+
"expectations": [
|
|
18
|
+
"Identifies this as a design task, not a code review task",
|
|
19
|
+
"Recommends microservices-patterns as primary (service coordination, saga pattern)",
|
|
20
|
+
"Recommends domain-driven-design as secondary (order domain modeling)",
|
|
21
|
+
"Explains the distinction: microservices-patterns for inter-service coordination, DDD for domain model design",
|
|
22
|
+
"Does NOT recommend clean-code-reviewer (no code to review yet)",
|
|
23
|
+
"Does NOT recommend system-design-interview unless scale/estimation is mentioned"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "eval-03-already-routed",
|
|
28
|
+
"prompt": "Use the effective-java skill to review my enum usage:\n\n```java\npublic class OrderStatus {\n public static final int PENDING = 0;\n public static final int APPROVED = 1;\n public static final int REJECTED = 2;\n public static final int CANCELLED = 3;\n}\n```",
|
|
29
|
+
"expectations": [
|
|
30
|
+
"Confirms effective-java is the correct skill (already specified by user)",
|
|
31
|
+
"Does NOT override the user's skill choice",
|
|
32
|
+
"Optionally notes which Effective Java item applies (Item 34: Use enums instead of int constants)",
|
|
33
|
+
"May note clean-code-reviewer would also flag this (J3: Constants vs Enums) but defers to user's choice",
|
|
34
|
+
"Does not second-guess or add unnecessary routing complexity"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|