@friedbotstudio/create-baseline 0.2.0 → 0.3.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.
Files changed (88) hide show
  1. package/README.md +7 -3
  2. package/obj/template/.claude/commands/grant-push.md +19 -0
  3. package/obj/template/.claude/commands/init-project.md +26 -4
  4. package/obj/template/.claude/hooks/consent_gate_grant.mjs +107 -0
  5. package/obj/template/.claude/hooks/git_commit_guard.mjs +224 -0
  6. package/obj/template/.claude/hooks/harness_continuation.sh +101 -34
  7. package/obj/template/.claude/hooks/lib/common.mjs +283 -0
  8. package/obj/template/.claude/hooks/lib/common.sh +1 -1
  9. package/obj/template/.claude/hooks/memory_session_start.sh +20 -6
  10. package/obj/template/.claude/hooks/memory_stop.sh +161 -2
  11. package/obj/template/.claude/hooks/spec_approval_guard.sh +1 -1
  12. package/obj/template/.claude/hooks/swarm_approval_guard.sh +1 -1
  13. package/obj/template/.claude/hooks/tests/fixtures/ac008_byte_equal_reference.txt +7 -7
  14. package/obj/template/.claude/hooks/tests/fixtures/memory_stop_landmark_baseline.txt +21 -0
  15. package/obj/template/.claude/hooks/tests/fixtures/regenerate-ac008.sh +47 -0
  16. package/obj/template/.claude/hooks/tests/memory_session_start_test.sh +7 -3
  17. package/obj/template/.claude/hooks/tests/memory_stop_intent_test.sh +329 -0
  18. package/obj/template/.claude/hooks/tests/regenerate_ac008_test.sh +99 -0
  19. package/obj/template/.claude/memory/README.md +8 -3
  20. package/obj/template/.claude/memory/backlog.md +12 -0
  21. package/obj/template/.claude/project.json +6 -1
  22. package/obj/template/.claude/settings.json +3 -4
  23. package/obj/template/.claude/skills/audit-baseline/audit.sh +39 -21
  24. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/_pending_opener_only.md +3 -0
  25. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_full_empty_body.md +4 -0
  26. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_full_with_entries.md +9 -0
  27. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_no_opener.md +3 -0
  28. package/obj/template/.claude/skills/audit-baseline/tests/fixtures/preamble_opener_only.md +3 -0
  29. package/obj/template/.claude/skills/audit-baseline/tests/preamble_check_test.sh +147 -0
  30. package/obj/template/.claude/skills/chore/SKILL.md +5 -3
  31. package/obj/template/.claude/skills/commit/SKILL.md +5 -4
  32. package/obj/template/.claude/skills/copywriting/LICENSE +21 -0
  33. package/obj/template/.claude/skills/copywriting/NOTICE +23 -0
  34. package/obj/template/.claude/skills/copywriting/SKILL.md +1 -1
  35. package/obj/template/.claude/skills/design-ui/SKILL.md +23 -5
  36. package/obj/template/.claude/skills/design-ui/references/design-vs-development.md +26 -5
  37. package/obj/template/.claude/skills/design-ui/references/orchestration.md +1 -0
  38. package/obj/template/.claude/skills/design-ui/references/state-machine.md +5 -3
  39. package/obj/template/.claude/skills/documentation/LICENSE +202 -0
  40. package/obj/template/.claude/skills/documentation/NOTICE +22 -0
  41. package/obj/template/.claude/skills/google-analytics/SKILL.md +129 -0
  42. package/obj/template/.claude/skills/google-analytics/references/audiences.md +389 -0
  43. package/obj/template/.claude/skills/google-analytics/references/bigquery.md +470 -0
  44. package/obj/template/.claude/skills/google-analytics/references/custom-dimensions.md +355 -0
  45. package/obj/template/.claude/skills/google-analytics/references/custom-events.md +383 -0
  46. package/obj/template/.claude/skills/google-analytics/references/data-management.md +416 -0
  47. package/obj/template/.claude/skills/google-analytics/references/debugview.md +364 -0
  48. package/obj/template/.claude/skills/google-analytics/references/events-fundamentals.md +398 -0
  49. package/obj/template/.claude/skills/google-analytics/references/gtag.md +502 -0
  50. package/obj/template/.claude/skills/google-analytics/references/gtm-integration.md +483 -0
  51. package/obj/template/.claude/skills/google-analytics/references/measurement-protocol.md +519 -0
  52. package/obj/template/.claude/skills/google-analytics/references/privacy.md +441 -0
  53. package/obj/template/.claude/skills/google-analytics/references/recommended-events.md +464 -0
  54. package/obj/template/.claude/skills/google-analytics/references/reporting.md +397 -0
  55. package/obj/template/.claude/skills/google-analytics/references/setup.md +344 -0
  56. package/obj/template/.claude/skills/google-analytics/references/user-tracking.md +417 -0
  57. package/obj/template/.claude/skills/harness/SKILL.md +3 -1
  58. package/obj/template/.claude/skills/humanizer/LICENSE +21 -0
  59. package/obj/template/.claude/skills/humanizer/NOTICE +21 -0
  60. package/obj/template/.claude/skills/impeccable/LICENSE +202 -0
  61. package/obj/template/.claude/skills/impeccable/NOTICE +24 -0
  62. package/obj/template/.claude/skills/memory-flush/SKILL.md +20 -4
  63. package/obj/template/.claude/skills/memory-flush/sweep.py +74 -6
  64. package/obj/template/.claude/skills/memory-flush/tests/run.sh +300 -1
  65. package/obj/template/.claude/skills/optimize-seo/SKILL.md +313 -0
  66. package/obj/template/.claude/skills/optimize-seo/scripts/pagespeed.mjs +197 -0
  67. package/obj/template/.claude/skills/pagespeed-insights/LICENSE.md +37 -0
  68. package/obj/template/.claude/skills/pagespeed-insights/SKILL.md +446 -0
  69. package/obj/template/.claude/skills/pagespeed-insights/reference.md +50 -0
  70. package/obj/template/.claude/skills/tdd/SKILL.md +2 -1
  71. package/obj/template/.claude/skills/tdd/drift_check.py +180 -0
  72. package/obj/template/.claude/skills/tdd/tests/drift_check_test.sh +190 -0
  73. package/obj/template/.claude/skills/tdd/tests/run.sh +21 -0
  74. package/obj/template/.claude/skills/technical-tutorials/LICENSE +21 -0
  75. package/obj/template/.claude/skills/technical-tutorials/NOTICE +23 -0
  76. package/obj/template/.claude/skills/technical-tutorials/SKILL.md +1 -1
  77. package/obj/template/.claude/skills/triage/SKILL.md +8 -3
  78. package/obj/template/CLAUDE.md +37 -26
  79. package/obj/template/docs/init/seed.md +38 -23
  80. package/obj/template/manifest.json +80 -33
  81. package/package.json +1 -1
  82. package/src/CLAUDE.template.md +37 -26
  83. package/src/memory/backlog.template.md +12 -0
  84. package/src/project.template.json +6 -1
  85. package/src/seed.template.md +38 -23
  86. package/src/settings.template.json +3 -4
  87. package/obj/template/.claude/hooks/consent_gate_grant.sh +0 -89
  88. package/obj/template/.claude/hooks/git_commit_guard.sh +0 -93
@@ -0,0 +1,446 @@
1
+ ---
2
+ name: pagespeed-insights
3
+ description: Audit web pages for performance optimization following PageSpeed Insights guidelines. Use when analyzing page performance, optimizing web applications, reviewing performance metrics, implementing Core Web Vitals improvements, or when the user mentions page speed, performance optimization, Lighthouse scores, or Core Web Vitals.
4
+ ---
5
+
6
+ # PageSpeed Insights Auditor
7
+
8
+ ## Overview
9
+
10
+ You are a **PageSpeed Insights Auditor** - an expert in web performance optimization who helps developers achieve excellent PageSpeed scores by identifying performance issues, avoiding bad practices, and implementing best practices based on Google's PageSpeed Insights guidelines.
11
+
12
+ **Core Principle**: Guide developers to achieve scores of 90+ (Good) in Performance, Accessibility, Best Practices, and SEO categories, while ensuring Core Web Vitals metrics meet the "Good" thresholds.
13
+
14
+ ## Understanding PageSpeed Insights
15
+
16
+ PageSpeed Insights (PSI) analyzes page performance on mobile and desktop devices, providing both **lab data** (simulated) and **field data** (real user experiences). PSI reports on user experience metrics and provides diagnostic suggestions to improve page performance.
17
+
18
+ ### Two Types of Data
19
+
20
+ 1. **Lab Data**: Collected in a controlled environment using Lighthouse. Useful for debugging but may not capture real-world bottlenecks.
21
+ 2. **Field Data**: Real user experience data from Chrome User Experience Report (CrUX). Useful for capturing actual user experiences but has a more limited set of metrics.
22
+
23
+ ## Performance Score Thresholds
24
+
25
+ ### Lab Scores (Lighthouse)
26
+
27
+ | Score Range | Rating | Icon |
28
+ | ----------- | ----------------- | --------------- |
29
+ | 90-100 | Good | 🟢 Green circle |
30
+ | 50-89 | Needs Improvement | 🟡 Amber square |
31
+ | 0-49 | Poor | 🔴 Red triangle |
32
+
33
+ **Target**: Always aim for scores of **90 or higher** in all categories.
34
+
35
+ ### Core Web Vitals Thresholds
36
+
37
+ Core Web Vitals are the three most important metrics for web performance:
38
+
39
+ | Metric | Good | Needs Improvement | Poor |
40
+ | ----------------------------------- | ------------ | ------------------ | --------- |
41
+ | **FCP** (First Contentful Paint) | [0, 1800 ms] | [1800 ms, 3000 ms] | > 3000 ms |
42
+ | **LCP** (Largest Contentful Paint) | [0, 2500 ms] | [2500 ms, 4000 ms] | > 4000 ms |
43
+ | **CLS** (Cumulative Layout Shift) | [0, 0.1] | [0.1, 0.25] | > 0.25 |
44
+ | **INP** (Interaction to Next Paint) | [0, 200 ms] | [200 ms, 500 ms] | > 500 ms |
45
+ | **TTFB** (Time to First Byte) | [0, 800 ms] | [800 ms, 1800 ms] | > 1800 ms |
46
+
47
+ **Target**: Ensure the 75th percentile of all Core Web Vitals metrics are in the "Good" range.
48
+
49
+ ## Key Performance Metrics
50
+
51
+ ### Lab Metrics (Lighthouse)
52
+
53
+ 1. **First Contentful Paint (FCP)**: Time until first content is rendered
54
+ 2. **Largest Contentful Paint (LCP)**: Time until largest content element is rendered
55
+ 3. **Speed Index**: How quickly content is visually displayed
56
+ 4. **Cumulative Layout Shift (CLS)**: Visual stability measure
57
+ 5. **Total Blocking Time (TBT)**: Sum of blocking time between FCP and TTI
58
+ 6. **Time to Interactive (TTI)**: Time until page is fully interactive
59
+
60
+ ### Field Metrics (CrUX)
61
+
62
+ - **FCP**: First Contentful Paint from real users
63
+ - **LCP**: Largest Contentful Paint from real users
64
+ - **CLS**: Cumulative Layout Shift from real users
65
+ - **INP**: Interaction to Next Paint (replaces FID)
66
+ - **TTFB**: Time to First Byte (experimental)
67
+
68
+ ## Common Performance Issues & Solutions
69
+
70
+ ### ❌ Bad Practice: Unoptimized Images
71
+
72
+ **Problem**: Large images without compression, modern formats, or proper sizing.
73
+
74
+ **Impact**: Poor LCP scores, slow page loads.
75
+
76
+ **✅ Solutions**:
77
+
78
+ - Use modern image formats (WebP, AVIF)
79
+ - Implement responsive images with `srcset`
80
+ - Compress images before uploading
81
+ - Set explicit width/height to prevent CLS
82
+ - Use lazy loading for below-the-fold images
83
+
84
+ ```html
85
+ <!-- Bad -->
86
+ <img src="large-image.jpg" alt="Description" />
87
+
88
+ <!-- Good -->
89
+ <img
90
+ src="image.webp"
91
+ srcset="image-small.webp 400w, image-medium.webp 800w, image-large.webp 1200w"
92
+ sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
93
+ width="1200"
94
+ height="800"
95
+ alt="Description"
96
+ loading="lazy"
97
+ />
98
+ ```
99
+
100
+ ### ❌ Bad Practice: Render-Blocking Resources
101
+
102
+ **Problem**: CSS and JavaScript blocking initial render.
103
+
104
+ **Impact**: Poor FCP and LCP scores.
105
+
106
+ **✅ Solutions**:
107
+
108
+ - Defer non-critical CSS
109
+ - Inline critical CSS
110
+ - Use `async` or `defer` for JavaScript
111
+ - Remove unused CSS/JS
112
+ - Split code and lazy load routes
113
+
114
+ ```html
115
+ <!-- Bad -->
116
+ <link rel="stylesheet" href="styles.css" />
117
+ <script src="app.js"></script>
118
+
119
+ <!-- Good -->
120
+ <link
121
+ rel="stylesheet"
122
+ href="styles.css"
123
+ media="print"
124
+ onload="this.media='all'"
125
+ />
126
+ <link rel="preload" href="critical.css" as="style" />
127
+ <script src="app.js" defer></script>
128
+ ```
129
+
130
+ ### ❌ Bad Practice: Missing Resource Hints
131
+
132
+ **Problem**: Not preconnecting to important origins or prefetching critical resources.
133
+
134
+ **Impact**: Slow TTFB and LCP.
135
+
136
+ **✅ Solutions**:
137
+
138
+ - Use `rel="preconnect"` for third-party origins
139
+ - Use `rel="dns-prefetch"` for DNS resolution
140
+ - Use `rel="preload"` for critical resources
141
+ - Use `rel="prefetch"` for likely next-page resources
142
+
143
+ ```html
144
+ <!-- Good -->
145
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
146
+ <link rel="dns-prefetch" href="https://api.example.com" />
147
+ <link rel="preload" href="hero-image.webp" as="image" />
148
+ ```
149
+
150
+ ### ❌ Bad Practice: Layout Shift (CLS)
151
+
152
+ **Problem**: Content shifting during page load.
153
+
154
+ **Impact**: Poor CLS scores, bad user experience.
155
+
156
+ **✅ Solutions**:
157
+
158
+ - Set explicit dimensions for images and videos
159
+ - Reserve space for ads and embeds
160
+ - Avoid inserting content above existing content
161
+ - Use CSS aspect-ratio for responsive containers
162
+ - Prefer transform animations over layout-triggering properties
163
+
164
+ ```css
165
+ /* Bad */
166
+ .image-container {
167
+ width: 100%;
168
+ /* height not set - causes CLS */
169
+ }
170
+
171
+ /* Good */
172
+ .image-container {
173
+ width: 100%;
174
+ aspect-ratio: 16 / 9;
175
+ /* or */
176
+ height: 0;
177
+ padding-bottom: 56.25%; /* 16:9 ratio */
178
+ }
179
+ ```
180
+
181
+ ### ❌ Bad Practice: Large JavaScript Bundles
182
+
183
+ **Problem**: Loading unnecessary JavaScript code.
184
+
185
+ **Impact**: Poor TTI, high TBT.
186
+
187
+ **✅ Solutions**:
188
+
189
+ - Code splitting and lazy loading
190
+ - Remove unused code (tree shaking)
191
+ - Minimize and compress JavaScript
192
+ - Use dynamic imports for routes
193
+ - Avoid large third-party libraries when possible
194
+
195
+ ```javascript
196
+ // Bad - loading everything upfront
197
+ import { heavyLibrary } from "./heavy-library";
198
+
199
+ // Good - lazy load when needed
200
+ const loadHeavyLibrary = () => import("./heavy-library");
201
+ ```
202
+
203
+ ### ❌ Bad Practice: Inefficient Font Loading
204
+
205
+ **Problem**: Fonts causing FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text).
206
+
207
+ **Impact**: Poor FCP, layout shifts.
208
+
209
+ **✅ Solutions**:
210
+
211
+ - Use `font-display: swap` or `optional`
212
+ - Preload critical fonts
213
+ - Subset fonts to include only needed characters
214
+ - Use system fonts when possible
215
+
216
+ ```css
217
+ /* Good */
218
+ @font-face {
219
+ font-family: "CustomFont";
220
+ src: url("font.woff2") format("woff2");
221
+ font-display: swap; /* or optional */
222
+ }
223
+ ```
224
+
225
+ ### ❌ Bad Practice: No Caching Strategy
226
+
227
+ **Problem**: Resources not cached, causing repeated downloads.
228
+
229
+ **Impact**: Slow repeat visits, poor performance.
230
+
231
+ **✅ Solutions**:
232
+
233
+ - Set appropriate Cache-Control headers
234
+ - Use service workers for offline caching
235
+ - Implement HTTP/2 server push for critical resources
236
+ - Use CDN for static assets
237
+
238
+ ```
239
+ Cache-Control: public, max-age=31536000, immutable
240
+ ```
241
+
242
+ ### ❌ Bad Practice: Third-Party Scripts Blocking Render
243
+
244
+ **Problem**: Analytics, ads, or widgets blocking page load.
245
+
246
+ **Impact**: Poor TTI, high TBT.
247
+
248
+ **✅ Solutions**:
249
+
250
+ - Load third-party scripts asynchronously
251
+ - Defer non-critical third-party code
252
+ - Use `rel="noopener"` for external links
253
+ - Consider self-hosting analytics when possible
254
+
255
+ ```html
256
+ <!-- Good -->
257
+ <script async src="https://www.google-analytics.com/analytics.js"></script>
258
+ ```
259
+
260
+ ## Accessibility Best Practices
261
+
262
+ ### ❌ Bad Practice: Missing Alt Text
263
+
264
+ **Problem**: Images without descriptive alt attributes.
265
+
266
+ **Impact**: Poor accessibility score.
267
+
268
+ **✅ Solution**: Always provide meaningful alt text.
269
+
270
+ ```html
271
+ <!-- Bad -->
272
+ <img src="chart.png" />
273
+
274
+ <!-- Good -->
275
+ <img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
276
+ ```
277
+
278
+ ### ❌ Bad Practice: Poor Color Contrast
279
+
280
+ **Problem**: Text not readable due to low contrast.
281
+
282
+ **Impact**: Poor accessibility score.
283
+
284
+ **✅ Solution**: Ensure contrast ratio of at least 4.5:1 for normal text, 3:1 for large text.
285
+
286
+ ### ❌ Bad Practice: Missing ARIA Labels
287
+
288
+ **Problem**: Interactive elements without proper labels.
289
+
290
+ **Impact**: Poor accessibility score.
291
+
292
+ **✅ Solution**: Use ARIA labels for screen readers.
293
+
294
+ ```html
295
+ <!-- Good -->
296
+ <button aria-label="Close dialog">×</button>
297
+ ```
298
+
299
+ ## SEO Best Practices
300
+
301
+ ### ❌ Bad Practice: Missing Meta Tags
302
+
303
+ **Problem**: No title, description, or viewport meta tags.
304
+
305
+ **Impact**: Poor SEO score.
306
+
307
+ **✅ Solution**: Include essential meta tags.
308
+
309
+ ```html
310
+ <!-- Good -->
311
+ <meta charset="UTF-8" />
312
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
313
+ <meta name="description" content="Page description" />
314
+ <title>Page Title</title>
315
+ ```
316
+
317
+ ### ❌ Bad Practice: Non-Descriptive Links
318
+
319
+ **Problem**: Links with generic text like "click here".
320
+
321
+ **Impact**: Poor SEO score.
322
+
323
+ **✅ Solution**: Use descriptive link text.
324
+
325
+ ```html
326
+ <!-- Bad -->
327
+ <a href="/about">Click here</a>
328
+
329
+ <!-- Good -->
330
+ <a href="/about">Learn more about our company</a>
331
+ ```
332
+
333
+ ## Best Practices Checklist
334
+
335
+ ### Performance
336
+
337
+ - [ ] Images optimized (WebP/AVIF, compressed, responsive)
338
+ - [ ] Critical CSS inlined
339
+ - [ ] Non-critical CSS deferred
340
+ - [ ] JavaScript code-split and lazy-loaded
341
+ - [ ] Render-blocking resources minimized
342
+ - [ ] Resource hints implemented (preconnect, preload, dns-prefetch)
343
+ - [ ] Fonts optimized with font-display
344
+ - [ ] Caching strategy implemented
345
+ - [ ] Third-party scripts loaded asynchronously
346
+ - [ ] Layout shifts prevented (explicit dimensions, aspect-ratio)
347
+
348
+ ### Core Web Vitals
349
+
350
+ - [ ] LCP < 2.5 seconds (75th percentile)
351
+ - [ ] FCP < 1.8 seconds (75th percentile)
352
+ - [ ] CLS < 0.1 (75th percentile)
353
+ - [ ] INP < 200ms (75th percentile)
354
+ - [ ] TTFB < 800ms (75th percentile)
355
+
356
+ ### Accessibility
357
+
358
+ - [ ] All images have alt text
359
+ - [ ] Color contrast meets WCAG standards
360
+ - [ ] ARIA labels on interactive elements
361
+ - [ ] Semantic HTML used
362
+ - [ ] Keyboard navigation supported
363
+
364
+ ### SEO
365
+
366
+ - [ ] Meta tags present (title, description, viewport)
367
+ - [ ] Descriptive link text
368
+ - [ ] Proper heading hierarchy (h1-h6)
369
+ - [ ] Structured data implemented
370
+ - [ ] Mobile-friendly design
371
+
372
+ ## Audit Workflow
373
+
374
+ When auditing a page for PageSpeed optimization:
375
+
376
+ 1. **Analyze Current State**
377
+
378
+ - Check current PageSpeed scores
379
+ - Identify Core Web Vitals metrics
380
+ - Review lab and field data differences
381
+
382
+ 2. **Identify Issues**
383
+
384
+ - List all performance problems
385
+ - Prioritize by impact (Core Web Vitals first)
386
+ - Categorize by type (images, JS, CSS, etc.)
387
+
388
+ 3. **Provide Solutions**
389
+
390
+ - Suggest specific optimizations
391
+ - Provide code examples
392
+ - Explain expected improvements
393
+
394
+ 4. **Verify Improvements**
395
+ - Re-test after changes
396
+ - Ensure scores reach 90+
397
+ - Confirm Core Web Vitals are "Good"
398
+
399
+ ## Common Mistakes to Avoid
400
+
401
+ ### ❌ Focusing Only on Lab Data
402
+
403
+ **Problem**: Optimizing only for Lighthouse scores without considering real user data.
404
+
405
+ **✅ Solution**: Balance both lab and field data. Field data shows real-world performance.
406
+
407
+ ### ❌ Over-Optimizing
408
+
409
+ **Problem**: Implementing too many optimizations at once, making debugging difficult.
410
+
411
+ **✅ Solution**: Make incremental changes and test after each optimization.
412
+
413
+ ### ❌ Ignoring Mobile Performance
414
+
415
+ **Problem**: Optimizing only for desktop.
416
+
417
+ **✅ Solution**: Mobile-first approach. Most users are on mobile devices.
418
+
419
+ ### ❌ Not Testing After Changes
420
+
421
+ **Problem**: Assuming optimizations worked without verification.
422
+
423
+ **✅ Solution**: Always re-run PageSpeed Insights after implementing changes.
424
+
425
+ ## Performance Optimization Priority
426
+
427
+ 1. **Critical Path**: Optimize resources needed for initial render
428
+ 2. **Core Web Vitals**: Focus on LCP, CLS, and INP first
429
+ 3. **Render-Blocking**: Eliminate blocking CSS and JS
430
+ 4. **Images**: Optimize largest contentful paint element
431
+ 5. **Third-Party**: Minimize impact of external scripts
432
+ 6. **Caching**: Implement proper caching strategies
433
+
434
+ ## Additional Resources
435
+
436
+ - [reference.md](reference.md) — Official PageSpeed, Lighthouse, Core Web Vitals, optimization guides — indexable
437
+ - **Official**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
438
+ - **PageSpeed Insights**: https://pagespeed.web.dev/
439
+ - **Lighthouse**: Built into Chrome DevTools
440
+ - **Web Vitals**: https://web.dev/vitals/
441
+
442
+ ## Specification Reference
443
+
444
+ This skill is based on the official [PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419) from Google Developers.
445
+
446
+ All thresholds, metrics, and best practices in this skill follow the official PageSpeed Insights guidelines and Core Web Vitals specifications. For complete documentation, refer to the [official PageSpeed Insights documentation](https://developers.google.com/speed/docs/insights/v5/about?hl=es-419).
@@ -0,0 +1,50 @@
1
+ # PageSpeed Insights — Reference & Official Documentation
2
+
3
+ This file complements the pagespeed-insights skill with official documentation links for indexing.
4
+
5
+ ## Official documentation (indexable)
6
+
7
+ - **PageSpeed Insights about**: https://developers.google.com/speed/docs/insights/v5/about?hl=es-419
8
+ - **PageSpeed Insights (tool)**: https://pagespeed.web.dev/
9
+ - **Lighthouse**: https://developer.chrome.com/docs/lighthouse/
10
+ - **Core Web Vitals**: https://web.dev/vitals/
11
+ - **Chrome User Experience Report (CrUX)**: https://developer.chrome.com/docs/crux/
12
+
13
+ ## Core Web Vitals (metrics)
14
+
15
+ - **LCP (Largest Contentful Paint)**: https://web.dev/lcp/
16
+ - **FCP (First Contentful Paint)**: https://web.dev/fcp/
17
+ - **CLS (Cumulative Layout Shift)**: https://web.dev/cls/
18
+ - **INP (Interaction to Next Paint)**: https://web.dev/inp/
19
+ - **TTFB (Time to First Byte)**: https://web.dev/ttfb/
20
+
21
+ ## Lab vs field data
22
+
23
+ - **Lab data**: Lighthouse, controlled environment, debugging
24
+ - **Field data**: CrUX, real user metrics, 28-day aggregation
25
+ - **Understanding metrics**: https://web.dev/metrics/
26
+
27
+ ## Performance optimization guides
28
+
29
+ - **Optimize LCP**: https://web.dev/optimize-lcp/
30
+ - **Optimize CLS**: https://web.dev/optimize-cls/
31
+ - **Optimize INP**: https://web.dev/optimize-inp/
32
+ - **Optimize FCP**: https://web.dev/optimize-fcp/
33
+ - **Resource hints**: https://web.dev/preconnect-and-dns-prefetch/
34
+ - **Image optimization**: https://web.dev/fast/#optimize-your-images
35
+
36
+ ## Tools
37
+
38
+ - **PageSpeed Insights**: https://pagespeed.web.dev/
39
+ - **Lighthouse (Chrome DevTools)**: Built-in, Audits tab
40
+ - **Web Vitals extension**: Real-time monitoring
41
+ - **Chromatic (Lighthouse CI)**: https://github.com/GoogleChrome/lighthouse-ci
42
+
43
+ ## Score thresholds (reminder)
44
+
45
+ | Category | Good | Needs Improvement | Poor |
46
+ |----------|------|-------------------|------|
47
+ | Performance | 90-100 | 50-89 | 0-49 |
48
+ | Accessibility | 90-100 | 50-89 | 0-49 |
49
+ | Best Practices | 90-100 | 50-89 | 0-49 |
50
+ | SEO | 90-100 | 50-89 | 0-49 |
@@ -77,7 +77,8 @@ Create tasks via `TaskCreate`; wire `addBlockedBy` so the chain is sequential. U
77
77
  - **Task B — implement-tick**: subject `"Run /implement for <slug>"`; metadata `{phase: "implement-tick", slug}`; activeForm `"Running implement"`; `addBlockedBy [A]`.
78
78
  - **Task C — verify-tick**: subject `"Run inline verify for <slug>"`; metadata `{phase: "verify-tick", slug}`; activeForm `"Running verify (inlined)"`; `addBlockedBy [B]`. The harness, when this task becomes next-pending, inlines the four mechanical operations from `.claude/skills/verify/SKILL.md` rather than invoking that skill via the Skill tool (the verify skill is contract-only after the harness-auto-continuation refactor).
79
79
  - **Tasks D₁..D_N — design-ui-tick (post-verify design implementation step; only when design_calls_rows is non-empty AND the implement write_set intersects `tdd.ui_globs`)**: one task per row. Subject `"Run /design-ui for <row.slug>"`; metadata `{phase: "design-ui-tick", slug, row_index: i}`; activeForm `"Running design-ui row <i>"`; `addBlockedBy [C]` for D₁, then chained `addBlockedBy [D_{i-1}]`. The design-ui worker handles the design implementation per the spec's `## Design calls` rows. After every D_i completes, the harness inlines a second verify pass (re-stamps `last_test_result`) to confirm the design work did not break behavior tests.
80
- - **Task Ztdd-finalize**: subject `"Finalize tdd for <slug>"`; metadata `{phase: "tdd-finalize", slug}`; activeForm `"Finalizing tdd"`; `addBlockedBy` the last D_i (or C if no design-ui). On execution, the harness appends `"tdd"` to `workflow.json completed`, writes `harness_state: continue` with reason "tdd green; next: simplify", and proceeds.
80
+ - **Task Edrift-check-tick (spec-to-implementation drift analysis; seeded for every spec-track workflow)**: subject `"Run drift-check for <slug>"`; metadata `{phase: "drift-check-tick", slug}`; activeForm `"Running drift-check (inlined)"`; `addBlockedBy [D_N]` if any design-ui-tick exists, else `[C]`. The harness inlines `python3 .claude/skills/tdd/drift_check.py --slug <slug>` against the approved spec and the branch diff. On exit 0 (zero unresolved): write the drift report path to the harness log; continue to Task Z. On exit 1 (≥ 1 unresolved): EXIT LOOP with YIELD (`reason: "drift analysis: <N> unresolved items"`); the user investigates and either fixes the impl gap or amends the spec + re-`/approve-spec`s. NO auto-loop. On `chore`-track workflows (no spec on disk), drift_check exits 0 with "no spec; skipped" and the harness proceeds to Z. On the workflow that initially introduces drift-check-tick, the harness instance in flight at that workflow predates the SKILL.md update and SHALL NOT seed Task E — the helper is unit-tested via the recipe scenarios and live runtime use begins in the next spec-track workflow.
81
+ - **Task Z — tdd-finalize**: subject `"Finalize tdd for <slug>"`; metadata `{phase: "tdd-finalize", slug}`; activeForm `"Finalizing tdd"`; `addBlockedBy` Task E (if seeded), else the last D_i, else C. On execution, the harness appends `"tdd"` to `workflow.json → completed`, writes `harness_state: continue` with reason "tdd green; next: simplify", and proceeds.
81
82
 
82
83
  ## 7. Write harness_state and yield
83
84
 
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env python3
2
+ """Spec-to-implementation drift analysis (Phase 6 worker step).
3
+
4
+ CLI:
5
+ python3 drift_check.py --slug <slug> [--project-root <path>] [--diff <path>]
6
+
7
+ Reads `docs/specs/<slug>.md` from `--project-root`, scores every numbered AC
8
+ in the ## Acceptance criteria table and every row of the ## Design calls
9
+ table against the implementation diff (--diff override, else `git diff
10
+ <merge-base>..HEAD` against the main branch). Writes a markdown report at
11
+ `<project-root>/.claude/state/drift/<slug>.md` with a per-item verdict of
12
+ `resolved | unresolved | unknown` plus evidence.
13
+
14
+ Exit codes:
15
+ 0 zero unresolved (`resolved` and `unknown` items are advisory)
16
+ 1 >=1 unresolved
17
+ 2 tool error (handled by argparse / unhandled exception)
18
+
19
+ Special case: spec file missing at the named slug → print "no spec; skipped"
20
+ to stdout, exit 0, no report file written (supports chore-track workflows).
21
+ """
22
+ from __future__ import annotations
23
+ import argparse
24
+ import re
25
+ import subprocess
26
+ import sys
27
+ from datetime import datetime, timezone
28
+ from pathlib import Path
29
+
30
+ # --- Foundation: regex + IO --------------------------------------------------
31
+
32
+ AC_ROW_RE = re.compile(r'^\|\s*(AC-\d+)\s*\|', re.MULTILINE)
33
+ DESIGN_CALLS_SECTION_RE = re.compile(
34
+ r'^##\s+Design calls\s*\n(.*?)(?=^##\s|\Z)',
35
+ re.MULTILINE | re.DOTALL,
36
+ )
37
+ DESIGN_ROW_RE = re.compile(r'^\|\s*([^|]+?)\s*\|', re.MULTILINE)
38
+ NONE_BODY_RE = re.compile(r'^[\s\-]*\*?\(?none\)?\*?[\s\-]*$', re.IGNORECASE)
39
+
40
+
41
+ def load_spec(project_root: Path, slug: str) -> str | None:
42
+ spec_path = project_root / 'docs' / 'specs' / f'{slug}.md'
43
+ if not spec_path.is_file():
44
+ return None
45
+ return spec_path.read_text(encoding='utf-8', errors='replace')
46
+
47
+
48
+ def load_diff(project_root: Path, diff_path: Path | None) -> str:
49
+ if diff_path:
50
+ return diff_path.read_text(encoding='utf-8', errors='replace')
51
+ try:
52
+ merge_base = subprocess.check_output(
53
+ ['git', '-C', str(project_root), 'merge-base', 'HEAD', 'main'],
54
+ stderr=subprocess.DEVNULL, text=True,
55
+ ).strip()
56
+ return subprocess.check_output(
57
+ ['git', '-C', str(project_root), 'diff', f'{merge_base}..HEAD'],
58
+ stderr=subprocess.DEVNULL, text=True,
59
+ )
60
+ except Exception:
61
+ return ''
62
+
63
+
64
+ def write_report(project_root: Path, slug: str, body: str) -> Path:
65
+ out_dir = project_root / '.claude' / 'state' / 'drift'
66
+ out_dir.mkdir(parents=True, exist_ok=True)
67
+ out_path = out_dir / f'{slug}.md'
68
+ out_path.write_text(body, encoding='utf-8')
69
+ return out_path
70
+
71
+
72
+ def now_iso() -> str:
73
+ return datetime.now(tz=timezone.utc).isoformat(timespec='seconds').replace('+00:00', 'Z')
74
+
75
+
76
+ def added_lines(diff_text: str) -> list[str]:
77
+ return [ln for ln in diff_text.splitlines()
78
+ if ln.startswith('+') and not ln.startswith('+++')]
79
+
80
+
81
+ # --- Domain: parse + score ---------------------------------------------------
82
+
83
+ def parse_acs(spec_text: str) -> list[str]:
84
+ return AC_ROW_RE.findall(spec_text)
85
+
86
+
87
+ def parse_design_calls(spec_text: str) -> list[str]:
88
+ """Return the list of row-slugs in the spec's `## Design calls` table.
89
+ Empty list iff section absent or body is the *(none)* sentinel."""
90
+ m = DESIGN_CALLS_SECTION_RE.search(spec_text)
91
+ if not m:
92
+ return []
93
+ body = m.group(1).strip()
94
+ if NONE_BODY_RE.match(body) or '*(none)*' in body or '(none)' in body.lower():
95
+ return []
96
+ rows = []
97
+ for row_match in DESIGN_ROW_RE.finditer(body):
98
+ first_cell = row_match.group(1).strip()
99
+ if re.match(r'^[\s:|\-]+$', first_cell):
100
+ continue
101
+ if first_cell.lower() in ('slug', 'kind'):
102
+ continue
103
+ rows.append(first_cell)
104
+ return rows
105
+
106
+
107
+ def score_against_diff(item_id: str, diff_added: list[str]) -> tuple[str, str]:
108
+ for ln in diff_added:
109
+ if item_id in ln:
110
+ snippet = ln.strip()
111
+ if len(snippet) > 120:
112
+ snippet = snippet[:117] + '...'
113
+ return ('resolved', f'found in diff: {snippet}')
114
+ return ('unresolved', 'no diff added-line references this item')
115
+
116
+
117
+ def render_report(slug: str,
118
+ acs: list[tuple[str, str, str]],
119
+ design_rows: list[tuple[str, str, str]]) -> str:
120
+ lines = [
121
+ f'# Drift report — {slug}',
122
+ '',
123
+ f'Generated at: {now_iso()}',
124
+ '',
125
+ '## Acceptance criteria',
126
+ '',
127
+ '| kind | id | verdict | evidence |',
128
+ '|---|---|---|---|',
129
+ ]
130
+ for ac_id, verdict, evidence in acs:
131
+ lines.append(f'| ac | {ac_id} | {verdict} | {evidence} |')
132
+ lines.append('')
133
+ lines.append('## Design calls')
134
+ lines.append('')
135
+ if not design_rows:
136
+ lines.append('no design calls — skipped')
137
+ else:
138
+ lines.append('| kind | id | verdict | evidence |')
139
+ lines.append('|---|---|---|---|')
140
+ for row_slug, verdict, evidence in design_rows:
141
+ lines.append(f'| design-call | {row_slug} | {verdict} | {evidence} |')
142
+ lines.append('')
143
+ return '\n'.join(lines)
144
+
145
+
146
+ # --- Orchestration -----------------------------------------------------------
147
+
148
+ def main(argv) -> int:
149
+ parser = argparse.ArgumentParser(description='Spec-to-implementation drift analysis')
150
+ parser.add_argument('--slug', required=True)
151
+ parser.add_argument('--project-root', default='.')
152
+ parser.add_argument('--diff', default=None)
153
+ args = parser.parse_args(argv)
154
+
155
+ project_root = Path(args.project_root).resolve()
156
+ spec_text = load_spec(project_root, args.slug)
157
+ if spec_text is None:
158
+ print('no spec; skipped')
159
+ return 0
160
+
161
+ diff_path = Path(args.diff).resolve() if args.diff else None
162
+ diff_text = load_diff(project_root, diff_path)
163
+ diff_added = added_lines(diff_text)
164
+
165
+ ac_results = [(ac_id, *score_against_diff(ac_id, diff_added))
166
+ for ac_id in parse_acs(spec_text)]
167
+
168
+ design_results = [(slug_, *score_against_diff(slug_, diff_added))
169
+ for slug_ in parse_design_calls(spec_text)]
170
+
171
+ report = render_report(args.slug, ac_results, design_results)
172
+ write_report(project_root, args.slug, report)
173
+
174
+ unresolved = sum(1 for _, v, _ in ac_results if v == 'unresolved')
175
+ unresolved += sum(1 for _, v, _ in design_results if v == 'unresolved')
176
+ return 0 if unresolved == 0 else 1
177
+
178
+
179
+ if __name__ == '__main__':
180
+ sys.exit(main(sys.argv[1:]))