skilldrop-cli 0.16.35 → 0.16.37

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 (298) hide show
  1. package/README.md +1 -0
  2. package/agents/README.md +4 -1
  3. package/agents/docs-reviewer.md +47 -0
  4. package/agents/finding-adjudicator.md +49 -0
  5. package/agents/test-reviewer.md +52 -0
  6. package/catalogue.json +19 -7
  7. package/model-routing.json +48 -0
  8. package/package.json +1 -1
  9. package/packs/ai-engineering/skills/agent-config-review/SKILL.md +116 -0
  10. package/packs/ai-engineering/skills/agent-config-review/evals/eval_queries.json +12 -0
  11. package/packs/ai-engineering/skills/agent-config-review/evals/evals.json +75 -0
  12. package/packs/ai-engineering/skills/agent-config-review/evals/files/1/.claude/agents/db-migrator.md +8 -0
  13. package/packs/ai-engineering/skills/agent-config-review/evals/files/1/.claude/agents/reviewer.md +9 -0
  14. package/packs/ai-engineering/skills/agent-config-review/evals/files/1/.claude/settings.json +48 -0
  15. package/packs/ai-engineering/skills/agent-config-review/evals/files/1/.claude/settings.local.json +5 -0
  16. package/packs/ai-engineering/skills/agent-config-review/evals/files/1/.mcp.json +22 -0
  17. package/packs/ai-engineering/skills/agent-config-review/evals/files/1/package.json +12 -0
  18. package/packs/ai-engineering/skills/agent-config-review/evals/files/2/.cursor/mcp.json +17 -0
  19. package/packs/ai-engineering/skills/agent-config-review/evals/files/2/config.toml +21 -0
  20. package/packs/ai-engineering/skills/agent-config-review/evals/files/4/my-user-settings.json +11 -0
  21. package/packs/ai-engineering/skills/agent-config-review/evals/files/4/quillstack/.claude/agents/release-notes.md +13 -0
  22. package/packs/ai-engineering/skills/agent-config-review/evals/files/4/quillstack/.claude/settings.json +39 -0
  23. package/packs/ai-engineering/skills/agent-config-review/evals/files/4/quillstack/.mcp.json +18 -0
  24. package/packs/ai-engineering/skills/agent-config-review/evals/files/4/quillstack/package.json +14 -0
  25. package/packs/ai-engineering/skills/agent-config-review/evals/files/5/.github/workflows/codex-triage.yml +29 -0
  26. package/packs/ai-engineering/skills/agent-config-review/evals/files/5/AGENTS.md +16 -0
  27. package/packs/ai-engineering/skills/agent-config-review/evals/files/5/codex/config.toml +34 -0
  28. package/packs/ai-engineering/skills/agent-config-review/examples/inputs/tidewater-ingest/.claude/settings.json +22 -0
  29. package/packs/ai-engineering/skills/agent-config-review/examples/inputs/tidewater-ingest/.mcp.json +9 -0
  30. package/packs/ai-engineering/skills/agent-config-review/examples/python-repo-tighten.md +81 -0
  31. package/packs/ai-engineering/skills/agent-config-review/manifest.json +60 -0
  32. package/packs/ai-engineering/skills/agent-config-review/reference.md +205 -0
  33. package/packs/ai-engineering/skills/agent-config-review/scripts/agent_config_scan.py +989 -0
  34. package/packs/ai-engineering/skills/agent-incident-response/SKILL.md +175 -0
  35. package/packs/ai-engineering/skills/agent-incident-response/evals/eval_queries.json +14 -0
  36. package/packs/ai-engineering/skills/agent-incident-response/evals/evals.json +107 -0
  37. package/packs/ai-engineering/skills/agent-incident-response/evals/files/1/agent-session-excerpt.txt +11 -0
  38. package/packs/ai-engineering/skills/agent-incident-response/evals/files/1/ci-build-log.txt +24 -0
  39. package/packs/ai-engineering/skills/agent-incident-response/evals/files/1/incident-notes.md +19 -0
  40. package/packs/ai-engineering/skills/agent-incident-response/evals/files/2/mcp-config.json +20 -0
  41. package/packs/ai-engineering/skills/agent-incident-response/evals/files/2/session-transcript.txt +8 -0
  42. package/packs/ai-engineering/skills/agent-incident-response/evals/files/4/agent-session.log +70 -0
  43. package/packs/ai-engineering/skills/agent-incident-response/evals/files/4/infra/staging-db.tf +25 -0
  44. package/packs/ai-engineering/skills/agent-incident-response/evals/files/5/jobs/nightly-triage/job.yaml +19 -0
  45. package/packs/ai-engineering/skills/agent-incident-response/evals/files/5/jobs/nightly-triage/run.log +13 -0
  46. package/packs/ai-engineering/skills/agent-incident-response/evals/files/5/usage-export-2026-10-20.csv +13 -0
  47. package/packs/ai-engineering/skills/agent-incident-response/evals/files/6/.mcp.json +20 -0
  48. package/packs/ai-engineering/skills/agent-incident-response/evals/files/6/git-log.txt +12 -0
  49. package/packs/ai-engineering/skills/agent-incident-response/evals/files/6/notesync-excerpt.txt +30 -0
  50. package/packs/ai-engineering/skills/agent-incident-response/evals/files/6/notesync.log +15 -0
  51. package/packs/ai-engineering/skills/agent-incident-response/evals/files/6/ssh-config.txt +16 -0
  52. package/packs/ai-engineering/skills/agent-incident-response/evals/files/7/.github/workflows/ci.yml +28 -0
  53. package/packs/ai-engineering/skills/agent-incident-response/evals/files/7/SECURITY.md +8 -0
  54. package/packs/ai-engineering/skills/agent-incident-response/evals/files/7/issue-479.md +35 -0
  55. package/packs/ai-engineering/skills/agent-incident-response/evals/files/7/package.json +15 -0
  56. package/packs/ai-engineering/skills/agent-incident-response/evals/files/7/pr-482.diff +20 -0
  57. package/packs/ai-engineering/skills/agent-incident-response/evals/files/7/run-log.txt +30 -0
  58. package/packs/ai-engineering/skills/agent-incident-response/examples/injected-issue-comment.md +57 -0
  59. package/packs/ai-engineering/skills/agent-incident-response/manifest.json +55 -0
  60. package/packs/ai-engineering/skills/agent-incident-response/reference.md +152 -0
  61. package/packs/ai-engineering/skills/agent-incident-response/scripts/find_secret_exposure.py +239 -0
  62. package/packs/ai-engineering/skills/agent-incident-response/scripts/usage_split.py +194 -0
  63. package/packs/ai-engineering/skills/judge-audit/SKILL.md +157 -0
  64. package/packs/ai-engineering/skills/judge-audit/evals/eval_queries.json +11 -0
  65. package/packs/ai-engineering/skills/judge-audit/evals/evals.json +136 -0
  66. package/packs/ai-engineering/skills/judge-audit/evals/files/1/judgements.csv +321 -0
  67. package/packs/ai-engineering/skills/judge-audit/evals/files/1/notes.md +28 -0
  68. package/packs/ai-engineering/skills/judge-audit/evals/files/2/pairwise.csv +101 -0
  69. package/packs/ai-engineering/skills/judge-audit/evals/files/2/run-notes.md +16 -0
  70. package/packs/ai-engineering/skills/judge-audit/evals/files/4/grades.csv +97 -0
  71. package/packs/ai-engineering/skills/judge-audit/evals/files/5/pairwise_judgements.jsonl +120 -0
  72. package/packs/ai-engineering/skills/judge-audit/evals/files/6/rag-judge/README.md +36 -0
  73. package/packs/ai-engineering/skills/judge-audit/evals/files/6/rag-judge/judgments.csv +301 -0
  74. package/packs/ai-engineering/skills/judge-audit/evals/files/7/moderation/gold_labels.csv +101 -0
  75. package/packs/ai-engineering/skills/judge-audit/evals/files/7/moderation/run_1.jsonl +100 -0
  76. package/packs/ai-engineering/skills/judge-audit/evals/files/7/moderation/run_2.jsonl +100 -0
  77. package/packs/ai-engineering/skills/judge-audit/evals/files/8/patches.csv +241 -0
  78. package/packs/ai-engineering/skills/judge-audit/evals/files/9/adequacy_ratings.csv +151 -0
  79. package/packs/ai-engineering/skills/judge-audit/examples/summary-panel.md +70 -0
  80. package/packs/ai-engineering/skills/judge-audit/manifest.json +44 -0
  81. package/packs/ai-engineering/skills/judge-audit/reference.md +176 -0
  82. package/packs/ai-engineering/skills/judge-audit/scripts/judge_stats.py +1735 -0
  83. package/packs/converters/skills/file-to-markdown/SKILL.md +2 -1
  84. package/packs/converters/skills/file-to-markdown/evals/eval_queries.json +4 -0
  85. package/packs/converters/skills/file-to-markdown/manifest.json +2 -2
  86. package/packs/converters/skills/file-to-markdown/scripts/to_markdown.py +253 -3
  87. package/packs/converters/skills/md-to-confluence/SKILL.md +139 -0
  88. package/packs/converters/skills/md-to-confluence/evals/eval_queries.json +42 -0
  89. package/packs/converters/skills/md-to-confluence/evals/evals.json +89 -0
  90. package/packs/converters/skills/md-to-confluence/evals/files/1/img/latency-dashboard.png +0 -0
  91. package/packs/converters/skills/md-to-confluence/evals/files/1/payments-runbook.md +60 -0
  92. package/packs/converters/skills/md-to-confluence/evals/files/2/deploy-checklist.md +33 -0
  93. package/packs/converters/skills/md-to-confluence/evals/files/3/img/after/screen.png +0 -0
  94. package/packs/converters/skills/md-to-confluence/evals/files/3/img/before/screen.png +0 -0
  95. package/packs/converters/skills/md-to-confluence/evals/files/3/release-notes-4.2.md +49 -0
  96. package/packs/converters/skills/md-to-confluence/evals/files/4/docs/img/topology.png +0 -0
  97. package/packs/converters/skills/md-to-confluence/evals/files/4/docs/ingest-pipeline-design.md +65 -0
  98. package/packs/converters/skills/md-to-confluence/evals/files/5/support/troubleshooting-sso.md +57 -0
  99. package/packs/converters/skills/md-to-confluence/examples/inputs/img/queue-depth.png +0 -0
  100. package/packs/converters/skills/md-to-confluence/examples/inputs/queue-runbook.fixed.md +21 -0
  101. package/packs/converters/skills/md-to-confluence/examples/inputs/queue-runbook.md +21 -0
  102. package/packs/converters/skills/md-to-confluence/examples/queue-runbook.md +57 -0
  103. package/packs/converters/skills/md-to-confluence/manifest.json +52 -0
  104. package/packs/converters/skills/md-to-confluence/reference.md +92 -0
  105. package/packs/converters/skills/md-to-confluence/scripts/md_to_confluence.py +821 -0
  106. package/packs/converters/skills/md-to-pptx/SKILL.md +131 -0
  107. package/packs/converters/skills/md-to-pptx/evals/eval_queries.json +12 -0
  108. package/packs/converters/skills/md-to-pptx/evals/evals.json +84 -0
  109. package/packs/converters/skills/md-to-pptx/evals/files/1/img/defect-burndown.png +0 -0
  110. package/packs/converters/skills/md-to-pptx/evals/files/1/status-report.md +75 -0
  111. package/packs/converters/skills/md-to-pptx/evals/files/3/brand.json +12 -0
  112. package/packs/converters/skills/md-to-pptx/evals/files/3/night-shift-induction.md +53 -0
  113. package/packs/converters/skills/md-to-pptx/evals/files/4/charts/ontime.png +0 -0
  114. package/packs/converters/skills/md-to-pptx/evals/files/4/qbr-q3.md +85 -0
  115. package/packs/converters/skills/md-to-pptx/evals/files/5/vendor-sync-notes.md +28 -0
  116. package/packs/converters/skills/md-to-pptx/examples/support-weekly-input.md +48 -0
  117. package/packs/converters/skills/md-to-pptx/examples/support-weekly.md +75 -0
  118. package/packs/converters/skills/md-to-pptx/examples/tickets-by-week.png +0 -0
  119. package/packs/converters/skills/md-to-pptx/manifest.json +49 -0
  120. package/packs/converters/skills/md-to-pptx/reference.md +139 -0
  121. package/packs/converters/skills/md-to-pptx/scripts/md_to_pptx.py +1841 -0
  122. package/packs/dev-team/loops/modernize/LOOP.md +124 -0
  123. package/packs/dev-team/loops/modernize/evals/eval_queries.json +9 -0
  124. package/packs/dev-team/loops/modernize/evals/evals.json +27 -0
  125. package/packs/dev-team/loops/modernize/loop.json +60 -0
  126. package/packs/dev-team/skills/behaviour-equivalence/SKILL.md +155 -0
  127. package/packs/dev-team/skills/behaviour-equivalence/evals/eval_queries.json +11 -0
  128. package/packs/dev-team/skills/behaviour-equivalence/evals/evals.json +76 -0
  129. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/cases.jsonl +12 -0
  130. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/new.jsonl +12 -0
  131. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/notes.md +15 -0
  132. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/old.jsonl +12 -0
  133. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/old_rerun.jsonl +12 -0
  134. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/pricing_v1.py +45 -0
  135. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/pricing_v2.py +65 -0
  136. package/packs/dev-team/skills/behaviour-equivalence/evals/files/1/rules.json +10 -0
  137. package/packs/dev-team/skills/behaviour-equivalence/evals/files/3/diff-summary.txt +16 -0
  138. package/packs/dev-team/skills/behaviour-equivalence/evals/files/4/diff.txt +13 -0
  139. package/packs/dev-team/skills/behaviour-equivalence/evals/files/4/fee_calc_py2.py +16 -0
  140. package/packs/dev-team/skills/behaviour-equivalence/evals/files/4/fee_calc_py3.py +24 -0
  141. package/packs/dev-team/skills/behaviour-equivalence/evals/files/4/input.csv +13 -0
  142. package/packs/dev-team/skills/behaviour-equivalence/evals/files/4/new_output.csv +13 -0
  143. package/packs/dev-team/skills/behaviour-equivalence/evals/files/4/old_output.csv +13 -0
  144. package/packs/dev-team/skills/behaviour-equivalence/evals/files/5/TEAM_NOTES.md +19 -0
  145. package/packs/dev-team/skills/behaviour-equivalence/evals/files/5/normalisation.yaml +12 -0
  146. package/packs/dev-team/skills/behaviour-equivalence/evals/files/5/recordings/new_run.jsonl +8 -0
  147. package/packs/dev-team/skills/behaviour-equivalence/evals/files/5/recordings/old_run1.jsonl +8 -0
  148. package/packs/dev-team/skills/behaviour-equivalence/evals/files/5/recordings/old_run2.jsonl +8 -0
  149. package/packs/dev-team/skills/behaviour-equivalence/examples/delivery-date.md +78 -0
  150. package/packs/dev-team/skills/behaviour-equivalence/manifest.json +33 -0
  151. package/packs/dev-team/skills/behaviour-equivalence/reference.md +97 -0
  152. package/packs/dev-team/skills/behaviour-equivalence/scripts/golden_diff.py +524 -0
  153. package/packs/dev-team/skills/behaviour-equivalence/templates/accepted.json +10 -0
  154. package/packs/dev-team/skills/behaviour-equivalence/templates/rules.json +7 -0
  155. package/packs/frontend/pack.json +61 -0
  156. package/packs/frontend/skills/bundle-size-review/SKILL.md +114 -0
  157. package/packs/frontend/skills/bundle-size-review/evals/eval_queries.json +12 -0
  158. package/packs/frontend/skills/bundle-size-review/evals/evals.json +108 -0
  159. package/packs/frontend/skills/bundle-size-review/evals/files/1/package.json +28 -0
  160. package/packs/frontend/skills/bundle-size-review/evals/files/1/src/utils/format.js +26 -0
  161. package/packs/frontend/skills/bundle-size-review/evals/files/1/stats.json +1334 -0
  162. package/packs/frontend/skills/bundle-size-review/evals/files/2/PR.md +21 -0
  163. package/packs/frontend/skills/bundle-size-review/evals/files/2/meta-after.json +440 -0
  164. package/packs/frontend/skills/bundle-size-review/evals/files/2/meta-before.json +360 -0
  165. package/packs/frontend/skills/bundle-size-review/evals/files/3/package.json +29 -0
  166. package/packs/frontend/skills/bundle-size-review/evals/files/3/stats.json +1583 -0
  167. package/packs/frontend/skills/bundle-size-review/evals/files/4/src/components/CommentBox.jsx +24 -0
  168. package/packs/frontend/skills/bundle-size-review/evals/files/4/stats/after.json +299 -0
  169. package/packs/frontend/skills/bundle-size-review/evals/files/4/stats/before.json +275 -0
  170. package/packs/frontend/skills/bundle-size-review/evals/files/5/.browserslistrc +3 -0
  171. package/packs/frontend/skills/bundle-size-review/evals/files/5/build/meta.json +371 -0
  172. package/packs/frontend/skills/bundle-size-review/evals/files/5/build.mjs +18 -0
  173. package/packs/frontend/skills/bundle-size-review/evals/files/5/package-lock.json +39 -0
  174. package/packs/frontend/skills/bundle-size-review/evals/files/5/package.json +22 -0
  175. package/packs/frontend/skills/bundle-size-review/evals/files/5/src/components/Icon.jsx +8 -0
  176. package/packs/frontend/skills/bundle-size-review/evals/files/5/src/polyfills.js +7 -0
  177. package/packs/frontend/skills/bundle-size-review/evals/files/5/src/utils/groupRows.js +4 -0
  178. package/packs/frontend/skills/bundle-size-review/evals/files/6/.browserslistrc +3 -0
  179. package/packs/frontend/skills/bundle-size-review/evals/files/6/package.json +25 -0
  180. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/App.tsx +8 -0
  181. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/i18n/chartLocales.ts +16 -0
  182. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/i18n/index.ts +8 -0
  183. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/i18n/messages/de.ts +5 -0
  184. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/i18n/messages/en.ts +5 -0
  185. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/i18n/useLocale.ts +14 -0
  186. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/main.tsx +10 -0
  187. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/pages/Home.tsx +14 -0
  188. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/pages/Reports.tsx +31 -0
  189. package/packs/frontend/skills/bundle-size-review/evals/files/6/src/routes.tsx +17 -0
  190. package/packs/frontend/skills/bundle-size-review/evals/files/6/stats.json +1869 -0
  191. package/packs/frontend/skills/bundle-size-review/evals/files/6/vite.config.ts +13 -0
  192. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/backoffice/package.json +26 -0
  193. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/backoffice/src/App.tsx +27 -0
  194. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/backoffice/src/pages/Analytics.tsx +10 -0
  195. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/backoffice/src/pages/Users.tsx +13 -0
  196. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/backoffice/stats.json +1421 -0
  197. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/backoffice/webpack.config.js +25 -0
  198. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/storefront/package.json +27 -0
  199. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/storefront/src/App.tsx +18 -0
  200. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/storefront/src/index.tsx +4 -0
  201. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/storefront/src/pages/Home.tsx +10 -0
  202. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/storefront/src/pages/Product.tsx +13 -0
  203. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/storefront/stats.json +1496 -0
  204. package/packs/frontend/skills/bundle-size-review/evals/files/7/apps/storefront/webpack.config.js +26 -0
  205. package/packs/frontend/skills/bundle-size-review/evals/files/7/package.json +9 -0
  206. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/dist/Button.css +3 -0
  207. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/dist/Button.js +14 -0
  208. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/dist/Chart.js +21 -0
  209. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/dist/index.js +22 -0
  210. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/package.json +20 -0
  211. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/src/Button.css +3 -0
  212. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/src/Button.tsx +9 -0
  213. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/src/Chart.tsx +14 -0
  214. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/src/index.ts +6 -0
  215. package/packs/frontend/skills/bundle-size-review/evals/files/7/packages/ui/tsconfig.json +14 -0
  216. package/packs/frontend/skills/bundle-size-review/examples/inputs/stats-after.json +1358 -0
  217. package/packs/frontend/skills/bundle-size-review/examples/inputs/stats-before.json +1334 -0
  218. package/packs/frontend/skills/bundle-size-review/examples/larkspur-sparkline.md +52 -0
  219. package/packs/frontend/skills/bundle-size-review/manifest.json +52 -0
  220. package/packs/frontend/skills/bundle-size-review/reference.md +147 -0
  221. package/packs/frontend/skills/bundle-size-review/scripts/bundle_stats.py +1633 -0
  222. package/packs/frontend/skills/rendering-strategy/SKILL.md +149 -0
  223. package/packs/frontend/skills/rendering-strategy/evals/eval_queries.json +38 -0
  224. package/packs/frontend/skills/rendering-strategy/evals/evals.json +77 -0
  225. package/packs/frontend/skills/rendering-strategy/evals/files/1/fernhill-app.md +40 -0
  226. package/packs/frontend/skills/rendering-strategy/evals/files/3/routes.md +33 -0
  227. package/packs/frontend/skills/rendering-strategy/evals/files/4/build-notes.txt +5 -0
  228. package/packs/frontend/skills/rendering-strategy/evals/files/4/nuxt.config.ts +19 -0
  229. package/packs/frontend/skills/rendering-strategy/evals/files/4/pages/recipes/[slug].vue +37 -0
  230. package/packs/frontend/skills/rendering-strategy/evals/files/4/routes.md +15 -0
  231. package/packs/frontend/skills/rendering-strategy/evals/files/5/routes.txt +18 -0
  232. package/packs/frontend/skills/rendering-strategy/evals/files/5/src/hooks.server.ts +14 -0
  233. package/packs/frontend/skills/rendering-strategy/evals/files/5/src/routes/(marketing)/pricing/+page.server.ts +10 -0
  234. package/packs/frontend/skills/rendering-strategy/evals/files/5/src/routes/+layout.server.ts +10 -0
  235. package/packs/frontend/skills/rendering-strategy/evals/files/5/svelte.config.js +10 -0
  236. package/packs/frontend/skills/rendering-strategy/evals/files/5/traffic.md +18 -0
  237. package/packs/frontend/skills/rendering-strategy/examples/saas-site.md +42 -0
  238. package/packs/frontend/skills/rendering-strategy/manifest.json +50 -0
  239. package/packs/frontend/skills/rendering-strategy/reference.md +116 -0
  240. package/packs/frontend/skills/rendering-strategy/scripts/render_load.py +181 -0
  241. package/packs/frontend/skills/web-performance-review/SKILL.md +106 -0
  242. package/packs/frontend/skills/web-performance-review/evals/eval_queries.json +38 -0
  243. package/packs/frontend/skills/web-performance-review/evals/evals.json +76 -0
  244. package/packs/frontend/skills/web-performance-review/evals/files/1/psi.json +1065 -0
  245. package/packs/frontend/skills/web-performance-review/evals/files/2/after.json +359 -0
  246. package/packs/frontend/skills/web-performance-review/evals/files/2/before.json +375 -0
  247. package/packs/frontend/skills/web-performance-review/evals/files/4/psi-pdp-mobile-2026-10-19.json +171 -0
  248. package/packs/frontend/skills/web-performance-review/evals/files/4/rum-inp-attribution-oct14-19.csv +6 -0
  249. package/packs/frontend/skills/web-performance-review/evals/files/4/rum-inp-daily.csv +15 -0
  250. package/packs/frontend/skills/web-performance-review/evals/files/5/crux-home-phone.json +35 -0
  251. package/packs/frontend/skills/web-performance-review/evals/files/5/lighthouse-home-mobile.json +173 -0
  252. package/packs/frontend/skills/web-performance-review/examples/quayside-article-lhr.json +480 -0
  253. package/packs/frontend/skills/web-performance-review/examples/quayside-article.md +103 -0
  254. package/packs/frontend/skills/web-performance-review/manifest.json +49 -0
  255. package/packs/frontend/skills/web-performance-review/reference.md +105 -0
  256. package/packs/frontend/skills/web-performance-review/scripts/lh_summary.py +743 -0
  257. package/packs/product-manager/skills/lean-canvas/SKILL.md +162 -0
  258. package/packs/product-manager/skills/lean-canvas/evals/eval_queries.json +42 -0
  259. package/packs/product-manager/skills/lean-canvas/evals/evals.json +82 -0
  260. package/packs/product-manager/skills/lean-canvas/evals/files/1/pawpass-notes.md +54 -0
  261. package/packs/product-manager/skills/lean-canvas/evals/files/3/lunchloop-pitch.md +30 -0
  262. package/packs/product-manager/skills/lean-canvas/evals/files/4/clubkit-notes.md +44 -0
  263. package/packs/product-manager/skills/lean-canvas/evals/files/5/cost-model.csv +5 -0
  264. package/packs/product-manager/skills/lean-canvas/evals/files/5/proposal.md +40 -0
  265. package/packs/product-manager/skills/lean-canvas/evals/files/5/stakeholder-emails.txt +18 -0
  266. package/packs/product-manager/skills/lean-canvas/examples/bike-repair.md +72 -0
  267. package/packs/product-manager/skills/lean-canvas/manifest.json +34 -0
  268. package/packs/product-manager/skills/lean-canvas/reference.md +102 -0
  269. package/packs/product-manager/skills/lean-canvas/scripts/unit_economics.py +211 -0
  270. package/packs/solution-architect/skills/api-contract-draft/SKILL.md +2 -2
  271. package/packs/solution-architect/skills/api-contract-draft/manifest.json +28 -6
  272. package/packs/solution-architect/skills/event-contract-draft/SKILL.md +167 -0
  273. package/packs/solution-architect/skills/event-contract-draft/evals/eval_queries.json +38 -0
  274. package/packs/solution-architect/skills/event-contract-draft/evals/evals.json +76 -0
  275. package/packs/solution-architect/skills/event-contract-draft/evals/files/1/order-events-brief.md +45 -0
  276. package/packs/solution-architect/skills/event-contract-draft/evals/files/4/NOTES.md +23 -0
  277. package/packs/solution-architect/skills/event-contract-draft/evals/files/4/schemas/shipment-update.json +40 -0
  278. package/packs/solution-architect/skills/event-contract-draft/evals/files/5/invoice.example.json +25 -0
  279. package/packs/solution-architect/skills/event-contract-draft/examples/order-service.asyncapi.json +246 -0
  280. package/packs/solution-architect/skills/event-contract-draft/examples/order-service.md +92 -0
  281. package/packs/solution-architect/skills/event-contract-draft/manifest.json +25 -0
  282. package/packs/solution-architect/skills/event-contract-draft/reference.md +113 -0
  283. package/packs/solution-architect/skills/event-contract-draft/scripts/check_asyncapi.py +502 -0
  284. package/packs/solution-architect/skills/event-contract-draft/templates/asyncapi-skeleton.json +144 -0
  285. package/packs/sre-oncall/skills/slo-spec/SKILL.md +161 -0
  286. package/packs/sre-oncall/skills/slo-spec/evals/eval_queries.json +38 -0
  287. package/packs/sre-oncall/skills/slo-spec/evals/evals.json +75 -0
  288. package/packs/sre-oncall/skills/slo-spec/evals/files/1/order-service.md +51 -0
  289. package/packs/sre-oncall/skills/slo-spec/evals/files/3/search-slo-status.md +30 -0
  290. package/packs/sre-oncall/skills/slo-spec/evals/files/4/alerts/payments-api.rules.yaml +16 -0
  291. package/packs/sre-oncall/skills/slo-spec/evals/files/4/docs/dependencies.md +8 -0
  292. package/packs/sre-oncall/skills/slo-spec/evals/files/4/metrics/summary-90d.md +51 -0
  293. package/packs/sre-oncall/skills/slo-spec/evals/files/5/ops-notes.md +34 -0
  294. package/packs/sre-oncall/skills/slo-spec/examples/ticket-booking.md +88 -0
  295. package/packs/sre-oncall/skills/slo-spec/manifest.json +34 -0
  296. package/packs/sre-oncall/skills/slo-spec/reference.md +113 -0
  297. package/packs/sre-oncall/skills/slo-spec/scripts/slo_math.py +449 -0
  298. package/packs/sre-oncall/skills/slo-spec/templates/slo-spec.md +35 -0
@@ -0,0 +1,116 @@
1
+ # rendering-strategy reference
2
+
3
+ ## Modes: what each costs and how each fails
4
+
5
+ | Mode | Renders | Fresh to | Personalised? | Indexed / previews | When the data source fails |
6
+ |---|---|---|---|---|---|
7
+ | Static at build (SSG) | once per build per page | last build | no (fragments only) | yes | page still served; data is as of the build |
8
+ | Revalidated (ISR, stale-while-revalidate, CDN `s-maxage` + `stale-while-revalidate`) | once per window per page that is visited, plus once per on-demand event | window, or the change event if on-demand | no (fragments only) | yes | last good copy keeps serving; regeneration retries |
9
+ | Server per request (SSR) | once per view | the request | yes | yes | TTFB waits on the slowest call; without a timeout the page errors or hangs |
10
+ | SSR streaming | once per view; shell first | the request | yes | yes, for content in the shell | shell arrives; the slow part shows its placeholder or fallback |
11
+ | Edge render | once per view, near the user | the request | yes, from cookie or geo | yes | as SSR, and every data call still travels to the origin region |
12
+ | Client-rendered (CSR, SPA) | none on the server; one data call or more per view | the request | yes | no: crawlers and preview bots get an empty shell | spinner, then an error state; nothing without JavaScript |
13
+ | Islands / server components | per the page's mode; only interactive parts ship JavaScript | per the page's mode | the island can be | yes | per the page's mode; an island can fail alone |
14
+
15
+ Two rules the table implies:
16
+
17
+ - **Revalidation reduces renders only when a page gets more views than windows.** A long tail
18
+ of pages each viewed a few times a month renders about once per view under a 5-minute
19
+ window. On-demand revalidation on the real change event is the saving.
20
+ - **Edge rendering is not faster when the data is in one region.** The HTML starts near the
21
+ user and then waits on a round trip to the origin database. It pays off for decisions made
22
+ from the request alone (geo, cookie, A/B bucket) or data replicated to the edge.
23
+
24
+ ## Splitting a page
25
+
26
+ | The page has… | Render the page | Render the part |
27
+ |---|---|---|
28
+ | A greeting, avatar or cart count | cached (static or revalidated) | client fetch to a `private, no-store` endpoint after load, or an edge-rendered fragment |
29
+ | A stock, price or seat count that must be fresh within seconds | cached | client fetch to an endpoint with a CDN TTL at or under the tolerance (which also collapses a spike to one origin call per TTL); the authoritative check at checkout |
30
+ | Recommendations per user | cached | client island, lazy, below the fold |
31
+ | A/B variant or locale | cached per variant (variant in the cache key, not a cookie `Vary`) | — |
32
+ | Whole page differs per user (dashboard, orders, settings) | per request or client-rendered, never shared-cached | — |
33
+
34
+ ## Cache headers
35
+
36
+ - Shared, revalidated HTML: `Cache-Control: public, s-maxage=<window>, stale-while-revalidate=<grace>`.
37
+ - Personalised HTML or JSON: `Cache-Control: private, no-store`. Never rely on `Vary: Cookie` to
38
+ separate users at a CDN: many CDNs ignore it or it turns the hit rate to zero.
39
+ - A response with `Set-Cookie` is never stored in a shared cache. Check the CDN's default.
40
+ - Query strings: list the parameters that change the content (`?category=`, `?page=`) and strip
41
+ or ignore tracking ones (`utm_*`, `gclid`) from the cache key. Faceted combinations that
42
+ explode the key space are rendered client-side from a cached listing, or get `noindex` and a
43
+ canonical URL.
44
+
45
+ ## Invalidation events
46
+
47
+ Write each as event → pages:
48
+
49
+ - Content publish or edit in a CMS → the page, its index and listing pages, the sitemap.
50
+ - Product, price or stock-threshold change in a catalogue system → the product page, its
51
+ category pages, any page featuring it (home carousel).
52
+ - Deploy → every static page rebuilt; say whether a deploy is the only way a page changes.
53
+ - Time → only for data with no event (exchange rates polled, aggregated counts).
54
+
55
+ ## Framework settings
56
+
57
+ Use only the section for the framework the user named. Behaviour that changed between major
58
+ versions is marked; confirm the version in `package.json` before stating it.
59
+
60
+ ### Next.js
61
+
62
+ - **App Router.** Route segment config per route: `export const revalidate = 600` (time-based),
63
+ `export const dynamic = 'force-static'` or `'force-dynamic'`; `generateStaticParams` to
64
+ prerender dynamic segments. On-demand: `revalidatePath('/p/slug')` or `revalidateTag('product:123')`
65
+ from a route handler the webhook calls; tag the fetch with `next: { tags: [...] }`.
66
+ - **The trap:** calling `cookies()` or `headers()` in a layout makes every route under it
67
+ dynamic. A greeting in the root layout turns the whole site into per-request SSR. Move the
68
+ personal part into a client component that fetches after load, or behind `<Suspense>`.
69
+ Reading `searchParams` in a page does the same to that page: filters and sorting as query
70
+ strings make a listing dynamic. Filter client-side over the cached listing, or make the
71
+ indexed combinations path segments with `generateStaticParams`.
72
+ - **Version-dependent:** the default caching of `fetch` changed between major versions (cached by
73
+ default earlier, not cached by default from 15). Partial prerendering and the `"use cache"`
74
+ directive are experimental in some versions. State the version before relying on any of these.
75
+ - **Pages Router.** `getStaticProps` with `revalidate`, `getStaticPaths` with `fallback: 'blocking'`,
76
+ `getServerSideProps` for per request, `res.revalidate()` for on-demand.
77
+
78
+ ### Nuxt
79
+
80
+ - `routeRules` in `nuxt.config`: `{ prerender: true }` (static at build), `{ swr: 600 }` (cached
81
+ response with background revalidation), `{ isr: 600 }` (the same on hosts with ISR support,
82
+ such as Vercel or Netlify), `{ ssr: false }` (client-rendered), `{ headers: { 'cache-control': ... } }`.
83
+ - **The trap:** `swr` and `isr` cache the rendered response keyed by path, shared across users.
84
+ On a personalised path they serve one user's page to everyone. Personalised routes get
85
+ `{ ssr: false }` or no cache rule plus `private, no-store`.
86
+ - `prerender: true` on a page that changes between deploys freezes it until the next build.
87
+
88
+ ### Remix / React Router (framework mode)
89
+
90
+ - Rendering is per request by default; caching is the `Cache-Control` the route's `headers`
91
+ export returns (`public, s-maxage=…, stale-while-revalidate=…` for shared, `private, no-store`
92
+ for personal). The CDN does the revalidation.
93
+ - Slow data: return the promise from the loader without awaiting it and render it with
94
+ `<Await>` inside `<Suspense>`, so the shell streams first.
95
+ - **Version-dependent:** React Router 7 adds `prerender` and `ssr: false` in
96
+ `react-router.config.ts` for static and SPA modes; Remix 2 has neither.
97
+
98
+ ### SvelteKit
99
+
100
+ - Per route in `+page.js` / `+page.server.js` or a layout: `export const prerender = true`,
101
+ `export const ssr = false` (client-rendered), `export const csr = false` (no JavaScript at all
102
+ for a read-only page). `setHeaders({ 'cache-control': ... })` in `load` for CDN caching.
103
+ - ISR is adapter-specific (for example `export const config = { isr: { expiration: 600 } }` on the
104
+ Vercel adapter); on other adapters use CDN headers.
105
+ - **The trap:** `prerender = true` on a layout applies to every child route, including ones that
106
+ need the request (cookies, `url.searchParams`); the build errors on them or the personal part
107
+ is rendered once at build. Set it per route, or override with `prerender = false` below.
108
+
109
+ ### Astro
110
+
111
+ - Static by default. Per page: `export const prerender = false` to render on request (needs an
112
+ adapter); site-wide `output: 'server'` flips the default.
113
+ - Islands: `client:load`, `client:idle`, `client:visible` hydrate one component; everything else
114
+ ships no JavaScript. Server islands (`server:defer`) render a personal fragment per request
115
+ inside a cached static page — the direct fit for a greeting on a static page.
116
+ - **Version-dependent:** server islands need a version that supports `server:defer`.
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env python3
2
+ """Count the page renders each route costs per month under its rendering mode.
3
+
4
+ Reads a CSV of routes (a path, or "-" for stdin) and prints a Markdown table of
5
+ origin renders per month under the chosen mode beside what per-request SSR
6
+ would cost, so the cost question in a rendering decision is a number, not a
7
+ guess. Stdlib only, Python 3.9+.
8
+
9
+ CSV columns (header row required; blank cells allowed where noted):
10
+ route name of the route, e.g. /products/[slug]
11
+ mode ssg | isr | ssr | csr | edge
12
+ views_month page views per month for the whole route (all pages)
13
+ pages distinct pages the route has (default 1)
14
+ revalidate_s isr only: time-based revalidation window in seconds
15
+ (blank = on-demand revalidation only)
16
+ changes_month ssg/isr: content changes per month that trigger a rebuild or
17
+ on-demand revalidation of one page (default 0)
18
+ builds_month ssg only: full builds per month (default 0)
19
+
20
+ Usage:
21
+ python3 render_load.py routes.csv [-o report.md]
22
+ """
23
+
24
+ import argparse
25
+ import csv
26
+ import io
27
+ import sys
28
+
29
+ MONTH_S = 30 * 24 * 3600
30
+ MODES = {"ssg", "isr", "ssr", "csr", "edge"}
31
+
32
+
33
+ def num(row, key, default=None, line=0):
34
+ raw = (row.get(key) or "").strip().replace(",", "").replace("_", "")
35
+ if raw == "":
36
+ if default is None:
37
+ raise ValueError(f"line {line}: '{key}' is required")
38
+ return default
39
+ try:
40
+ value = float(raw)
41
+ except ValueError:
42
+ raise ValueError(f"line {line}: '{key}' must be a number, got '{raw}'")
43
+ if value < 0:
44
+ raise ValueError(f"line {line}: '{key}' must not be negative")
45
+ return value
46
+
47
+
48
+ def renders(row, line):
49
+ mode = (row.get("mode") or "").strip().lower()
50
+ if mode not in MODES:
51
+ raise ValueError(f"line {line}: mode must be one of {sorted(MODES)}, got '{mode}'")
52
+ views = num(row, "views_month", line=line)
53
+ pages = max(num(row, "pages", 1, line), 1)
54
+ changes = num(row, "changes_month", 0, line)
55
+ note = ""
56
+ if mode == "ssr":
57
+ origin = views
58
+ note = "one render per view; TTFB depends on the data source"
59
+ elif mode == "edge":
60
+ origin = views
61
+ note = "one render per view, at the edge; data calls still go to origin"
62
+ elif mode == "csr":
63
+ origin = 0
64
+ note = f"static shell; at least {fmt(views)} client data calls"
65
+ elif mode == "ssg":
66
+ builds = num(row, "builds_month", 0, line)
67
+ origin = builds * pages + changes
68
+ note = "renders happen at build time, not per view"
69
+ else: # isr
70
+ reval = num(row, "revalidate_s", 0, line)
71
+ if reval == 0:
72
+ origin = min(changes, views)
73
+ note = "on-demand revalidation only"
74
+ else:
75
+ windows = MONTH_S / reval
76
+ per_page = views / pages
77
+ # each render is triggered by a view, so renders never exceed views
78
+ origin = min(pages * min(per_page, windows) + changes, views)
79
+ if per_page <= windows:
80
+ note = ("upper bound; each page gets fewer views than windows, "
81
+ "so time-based revalidation saves little: use on-demand")
82
+ elif pages == 1:
83
+ note = "at most one render per window"
84
+ else:
85
+ note = "upper bound if traffic is even; skewed traffic renders less"
86
+ saved = 0.0 if views == 0 else 1 - origin / views
87
+ return {
88
+ "route": (row.get("route") or "").strip() or f"(line {line})",
89
+ "mode": mode,
90
+ "views": views,
91
+ "origin": origin,
92
+ "saved": saved,
93
+ "note": note,
94
+ }
95
+
96
+
97
+ def pct(saved):
98
+ if saved <= 0:
99
+ return "no fewer" if saved == 0 else f"{-saved * 100:.0f}% more"
100
+ if saved >= 0.995 and saved < 1:
101
+ return ">99% fewer"
102
+ if saved < 0.005:
103
+ return "<1% fewer"
104
+ return f"{saved * 100:.0f}% fewer"
105
+
106
+
107
+ def fmt(n):
108
+ return f"{int(round(n)):,}"
109
+
110
+
111
+ def report(rows):
112
+ out = [
113
+ "| Route | Mode | Views/month | Origin renders/month | vs SSR per request | Note |",
114
+ "|---|---|---:|---:|---:|---|",
115
+ ]
116
+ total_views = total_origin = 0.0
117
+ for r in rows:
118
+ total_views += r["views"]
119
+ total_origin += r["origin"]
120
+ out.append(
121
+ f"| {r['route']} | {r['mode']} | {fmt(r['views'])} | {fmt(r['origin'])} | "
122
+ f"{pct(r['saved'])} | {r['note']} |"
123
+ )
124
+ saved = 0.0 if total_views == 0 else 1 - total_origin / total_views
125
+ out.append(
126
+ f"| **Total** | | {fmt(total_views)} | {fmt(total_origin)} | {pct(saved)} | |"
127
+ )
128
+ out.append("")
129
+ out.append(
130
+ "Origin renders are upper bounds assuming views spread evenly across a route's pages; "
131
+ "a 30-day month is used. SSR per request renders once per view."
132
+ )
133
+ return "\n".join(out) + "\n"
134
+
135
+
136
+ def main(argv=None):
137
+ ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
138
+ ap.add_argument("csv", help="routes CSV, or - for stdin")
139
+ ap.add_argument("-o", "--output", help="write the Markdown report here (default: stdout)")
140
+ args = ap.parse_args(argv)
141
+
142
+ try:
143
+ if args.csv == "-":
144
+ text = sys.stdin.read()
145
+ else:
146
+ with open(args.csv, encoding="utf-8") as fh:
147
+ text = fh.read()
148
+ except OSError as exc:
149
+ print(f"error: cannot read {args.csv}: {exc}", file=sys.stderr)
150
+ return 2
151
+
152
+ reader = csv.DictReader(io.StringIO(text))
153
+ missing = {"route", "mode", "views_month"} - set(reader.fieldnames or [])
154
+ if missing:
155
+ print(f"error: CSV is missing columns: {', '.join(sorted(missing))}", file=sys.stderr)
156
+ return 2
157
+ rows = []
158
+ try:
159
+ for i, row in enumerate(reader, start=2):
160
+ if not any((v or "").strip() for v in row.values()):
161
+ continue
162
+ rows.append(renders(row, i))
163
+ except ValueError as exc:
164
+ print(f"error: {exc}", file=sys.stderr)
165
+ return 2
166
+ if not rows:
167
+ print("error: no routes in the CSV", file=sys.stderr)
168
+ return 2
169
+
170
+ text = report(rows)
171
+ if args.output:
172
+ with open(args.output, "w", encoding="utf-8") as fh:
173
+ fh.write(text)
174
+ print(f"wrote {args.output}")
175
+ else:
176
+ sys.stdout.write(text)
177
+ return 0
178
+
179
+
180
+ if __name__ == "__main__":
181
+ sys.exit(main())
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: web-performance-review
3
+ description: Read a Lighthouse report or PageSpeed Insights result, with field data when there is any (CrUX, PSI loadingExperience or RUM p75), and say what makes the page slow for real users and what to fix first, ranked by how much each fix moves LCP, INP and CLS at the 75th percentile. Names the LCP element and which LCP phase dominates, the elements that shift and why, the long tasks and third parties by main-thread time, and treats estimated savings as lab estimates that overlap. Use when the user shares a Lighthouse JSON or PSI result and asks "why is this page slow", "what should we fix first", "we score 92 but Search Console says LCP is poor", "did our change fix INP", "review this Lighthouse report", or "how do we pass Core Web Vitals".
4
+ ---
5
+
6
+ # web-performance-review
7
+
8
+ Reads a Lighthouse run the way a performance engineer does: real-user p75 numbers decide whether
9
+ the page has a problem, and the one lab run explains why. The output names the element, the URL
10
+ and the change, in the order that moves the failing vital most. Accessibility findings in the
11
+ same report go to `accessibility-audit`. What is inside a heavy JavaScript bundle is
12
+ `bundle-size-review`. Choosing SSR, static or client rendering for a route is
13
+ `rendering-strategy`. Setting up RUM or alerting on the vitals is `observability-plan`.
14
+
15
+ ## How to respond
16
+
17
+ **Four rules come before the steps and outrank them:**
18
+
19
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
20
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
21
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
22
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
23
+ - **For this skill:** Field p75 decides whether there is a problem; the lab run explains why. Never call a page good or bad from the Performance score, and say which data each verdict rests on.
24
+
25
+ 1. **Get the report and any field data.** Accept the Lighthouse JSON, a PageSpeed Insights API response (it embeds the Lighthouse result and the CrUX field data), a CrUX API record, or RUM p75 numbers typed in the message. Ask once, in one sentence, for field data when there is none; never hold the review back for it. When the user can run Lighthouse, ask for three to five runs, not one:
26
+ ```bash
27
+ for i in 1 2 3 4 5; do npx lighthouse "$URL" --only-categories=performance --output=json --output-path="run-$i.json" --quiet --chrome-flags="--headless"; done
28
+ ```
29
+ An installed CLI is the same command without `npx`: `lighthouse "$URL" --output=json --output-path=report.json`.
30
+
31
+ 2. **Run the summary script; read numbers from it, not by eye.** It prints the run settings, lab metrics against thresholds, field p75 with ratings and the Core Web Vitals outcome, the LCP element and phases, layout-shift culprits, failing audits ranked by the vital they move (with overlaps marked), long tasks and third parties, and render-blocking resources. It exits 2 on a file that is not a Lighthouse, PSI or CrUX result.
32
+ ```bash
33
+ # Claude Code
34
+ python3 "${CLAUDE_SKILL_DIR}/scripts/lh_summary.py" psi.json
35
+ python3 "${CLAUDE_SKILL_DIR}/scripts/lh_summary.py" report.json --lcp-p75 3100 --inp-p75 420 --cls-p75 0.04
36
+ python3 "${CLAUDE_SKILL_DIR}/scripts/lh_summary.py" before.json after.json
37
+ # Other IDEs (from the skill folder)
38
+ python3 scripts/lh_summary.py psi.json --json
39
+ ```
40
+ Pass RUM numbers with `--lcp-p75 / --inp-p75 / --cls-p75` and a CrUX file with `--field`. Two reports print a comparability check and the deltas. When only a pasted excerpt is available, apply the same steps by hand and say which sections were not in the excerpt.
41
+
42
+ 3. **Give the verdict from field data, per vital, with the threshold and the source.** Good at p75 is LCP ≤ 2.5 s, INP ≤ 200 ms, CLS ≤ 0.1; poor is LCP > 4 s, INP > 500 ms, CLS > 0.25. Say whether the numbers are for this URL or the whole origin (PSI's `origin_fallback`), and the form factor.
43
+ - ✅ *"Real mobile users wait 4.3 s for the main image at p75 (poor; good is 2.5 s). The 92 is one simulated lab load, and its 2.4 s LCP is not what users get."*
44
+ - ❌ *"The page scores 92, so performance is good; LCP could be improved slightly."*
45
+ - With no field data: ✅ *"Whether the page passes Core Web Vitals can't be told from a lab run. This run shows LCP at 3.1 s in the lab, and here is why."* PSI reports CLS p75 multiplied by 100: `14` is 0.14.
46
+
47
+ 4. **Name the LCP element and fix the phase that dominates.** Quote the element's selector or snippet and split LCP into TTFB, resource load delay, resource load duration and element render delay. The biggest phase picks the fix:
48
+ - **Load delay** dominates: the browser found the resource late. `loading="lazy"` on the LCP image, no `fetchpriority="high"`, or an image set from JS or a CSS `background-image` (which needs an `<img>` in the HTML, or `<link rel="preload" as="image" fetchpriority="high">`). ✅ *"Remove `loading=\"lazy\"` from `img.collection-hero__image` and add `fetchpriority=\"high\"`; it is in the HTML already, so it needs no preload."* ❌ *"Optimize images."*
49
+ - **TTFB** dominates: server time, redirects or no HTML caching.
50
+ - Field TTFB needs improvement or worse while lab TTFB is small: say part of the field LCP is server and network time the lab run can't show. The lab measures one request from one place.
51
+ - **Load duration** dominates: the file is too large for the viewport (a 2400 px image on a 412 px screen). Name the URL and the `srcset` widths.
52
+ - **Render delay** dominates: render-blocking CSS or JS, client-side rendering, or long tasks before paint. A text LCP element has no resource, so all of its time is TTFB plus render delay.
53
+
54
+ 5. **Name what shifts and why.** For each shifting element give its score and the cause the report gives: unsized image → `width`/`height` or `aspect-ratio`; web font → `font-display` plus a size-adjusted fallback; injected iframe or banner → reserve the slot with `min-height`. A lab run sees only shifts during load. When field CLS is worse than lab CLS, say the extra comes from shifts after load (scrolling, late banners, ads) that this report can't show, and say what would show them.
55
+
56
+ 6. **Treat TBT as a lab proxy for INP, never as INP.** Name the long tasks by script and the third parties by entity with their main-thread and blocking time: ✅ *"ChatterBox's loader.js: one 170 ms task at 3.1 s; 412 ms of main-thread time in total."* When field INP is good, TBT is not a priority, whatever the score weights say. When field INP is poor, point at the scripts that run on interaction too, because a navigation run records no interactions.
57
+
58
+ 7. **Rank fixes by the failing vital they move, and how much.** Fixes for the vital furthest past its field threshold come first, even when the script's table lists another first. Within a vital, use the audit's per-metric saving (`metricSavings`), not the headline "Est savings", which is lab load time. An audit with a big load saving and no LCP, TBT or CLS saving goes last or is left out: ✅ *"Converting the product-grid JPEGs saves 1.2 MB but does not move LCP; the LCP image is the hero."* Savings that touch the same resource overlap: never add them into a total. Give each fix as the change, on the named element or URL, and the vital it moves.
59
+
60
+ 8. **Say how sure the numbers are.** One run is noisy: say so once, name the emulated device and throttling (Lighthouse's default mobile is a mid-range phone on slow 4G with 4x CPU slowdown), and note any run warnings. Before calling a change an improvement, ask for the median of 3 to 5 runs per side with the same settings, then field data. Runs with different device, throttling or Lighthouse version are not comparable, and the script lists every such difference. CrUX is a 28-day rolling window, so it trails a fix by weeks; RUM shows it sooner.
61
+
62
+ 9. **Write the reply in this order.** First, two or three sentences: whether real users have a problem, on which vital, and the main cause. Then up to five numbered fixes, each with the change, where, the vital it moves and the evidence. Then one short paragraph on what this report can't tell. Add "To confirm" only for missing inputs. Leave out the metric tables unless the user asked for them, keep a chat question to a chat-length answer, and keep to any word limit the user sets.
63
+
64
+ **Non-interactive runs** (subagent, CI, headless): missing field data becomes `[assumption] no field data given; Core Web Vitals pass/fail not stated, lab findings only`, stated first. A missing report, a report with `runtimeError`, or a file the script rejects emits `BLOCKED: need the Lighthouse JSON (lighthouse <url> --output=json) or the PageSpeed Insights API response for the page`. Never review a report that failed to load the page.
65
+
66
+ ## Useful references in this skill
67
+
68
+ - [`reference.md`](reference.md): thresholds, the Lighthouse and PSI fields read, LCP phases and their fixes, CLS causes, audit-to-vital map, throttling presets, field-data quirks
69
+ - [`scripts/lh_summary.py`](scripts/lh_summary.py): stdlib summariser for Lighthouse, PSI and CrUX JSON; `--json`, `-o`, two-report comparison; exits 2 on bad input
70
+ - [`examples/quayside-article.md`](examples/quayside-article.md): worked example, a news article with poor field CLS from an ad slot and a TTFB-heavy LCP
71
+
72
+ ## Quality bar
73
+
74
+ - **The first lines say whether real users have a problem**, on which vital, from which data, with the p75 threshold.
75
+ - **No verdict from the Performance score.** The score is described as a lab weighting, not as Core Web Vitals.
76
+ - **The LCP element is named** by selector or snippet, with the phase breakdown when the report has it, and the fix matches the dominant phase.
77
+ - **Every CLS fix names the shifting element and its cause**; field CLS above lab CLS is called out as after-load shifts the run can't see.
78
+ - **TBT is never reported as INP.** Long tasks and third parties are named by script or entity with milliseconds.
79
+ - **Fixes are ranked by the failing vital's per-metric saving**, load-time-only savings are not ranked as vital fixes, and overlapping savings are not summed.
80
+ - **The single-run caveat and the emulated device and network appear once**, with medians of 3 to 5 runs or field data as the bar for "improved".
81
+ - **No invented numbers, elements or URLs.** Every figure and selector is in the input or computed from it.
82
+
83
+ ## When to use this skill
84
+
85
+ - ✅ A Lighthouse JSON or PSI result is shared with "why is this slow" or "what do we fix first"
86
+ - ✅ The lab score and Search Console or CrUX disagree
87
+ - ✅ Checking whether a performance change worked, from before and after runs
88
+ - ✅ Planning Core Web Vitals work for a page from its report and RUM numbers
89
+
90
+ ## When NOT to use this skill
91
+
92
+ - ❌ The accessibility findings in the same Lighthouse report: use `accessibility-audit`
93
+ - ❌ What is in a JavaScript bundle and why it is heavy (source maps, stats files): use `bundle-size-review`
94
+ - ❌ Choosing SSR, static, ISR or client rendering for routes: use `rendering-strategy`
95
+ - ❌ Setting up RUM, web-vitals collection, dashboards or alerts: use `observability-plan`
96
+ - ❌ Lighthouse SEO and Best Practices scores; this skill reads the Performance category only
97
+
98
+ ## Anti-patterns to avoid
99
+
100
+ - ❌ **"92, so it's fine."** The score weights one simulated load; it says nothing about users on slower phones and networks.
101
+ - ❌ **Calling TBT "INP".** A load run has no clicks or taps. INP comes from field data.
102
+ - ❌ **Leading with the biggest "Est savings".** It is page load time in the lab, often for images below the fold.
103
+ - ❌ **Adding savings up.** "Fix these four for 5.9 s" double-counts the same images and the same main thread.
104
+ - ❌ **Preloading a lazy-loaded hero.** The fix is removing `loading="lazy"` and adding `fetchpriority="high"`; a preload on top works around the attribute and leaves the cause in the markup.
105
+ - ❌ **A generic checklist.** "Minify CSS, use a CDN, enable compression" with no element, URL or number from the report.
106
+ - ❌ **"Fixed" after one better run.** Run-to-run variance, a different device or throttling, or a different Lighthouse version can move the score as much as the change did.
@@ -0,0 +1,38 @@
1
+ [
2
+ {
3
+ "query": "Here's our Lighthouse JSON for the product page, why is it slow and what should we fix first?",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "PageSpeed says 92 but Search Console says LCP is poor on mobile. Which one is right?",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "We deferred the analytics scripts and the Lighthouse score went up 12 points. Did that fix INP?",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "Review this PSI result and tell me how to get the homepage passing Core Web Vitals",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "What is the LCP element in this Lighthouse report and why is load delay so high?",
20
+ "should_trigger": true
21
+ },
22
+ {
23
+ "query": "Lighthouse flagged contrast and missing labels on the checkout form, can you audit it against WCAG?",
24
+ "should_trigger": false
25
+ },
26
+ {
27
+ "query": "Our main.js is 1.4 MB, here's the webpack stats file, what's making it so big?",
28
+ "should_trigger": false
29
+ },
30
+ {
31
+ "query": "Should the blog and product pages be SSR or static with revalidation in Next.js?",
32
+ "should_trigger": false
33
+ },
34
+ {
35
+ "query": "Set up real-user monitoring and alerts for Core Web Vitals across our site",
36
+ "should_trigger": false
37
+ }
38
+ ]
@@ -0,0 +1,76 @@
1
+ {
2
+ "skill_name": "web-performance-review",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Our marketing lead says the raincoats collection page is fine because PageSpeed gives it 92 on mobile, but Search Console keeps flagging LCP as poor. Here's the PageSpeed Insights API response: psi.json. What's actually making it slow and what should the team fix first?",
7
+ "assertions": [
8
+ "Opens by saying real mobile users do have a problem: field LCP at p75 is 4.3 s, which is poor against the 2.5 s threshold, and that the 92 is a lab score from one run rather than a Core Web Vitals verdict",
9
+ "Names the LCP element as img.collection-hero__image (the raincoats hero image) and identifies that it has loading=\"lazy\", with resource load delay (about 1.19 s, half of the lab LCP) as the largest phase",
10
+ "Makes removing loading=\"lazy\" from the hero image and adding fetchpriority=\"high\" the first fix",
11
+ "Does not rank 'Serve images in next-gen formats' (est. 2.85 s / 1,240 KiB) as an LCP fix, and says it covers the product-grid images and has no LCP saving",
12
+ "Reads field CLS as 0.14 (needs improvement), not 14, notes it is higher than the lab CLS of 0.04 so some shifts happen after load and are not in this run, and names the unsized product-card images or the late web font as the culprits the run does show",
13
+ "Does not make TBT, long tasks or the third-party scripts a top priority, because field INP is 168 ms, which is good",
14
+ "Does not add the estimated savings of different audits into a total, and mentions that this is a single lab run on an emulated mid-range phone with slow 4G",
15
+ "Does not invent metrics, elements, URLs or field numbers that are not in psi.json"
16
+ ]
17
+ },
18
+ {
19
+ "id": 2,
20
+ "prompt": "We deferred the ChatterBox chat widget on the Fernhill autumn-lights event page until after load, and Lighthouse went from 58 to 71. Before the change our RUM had INP at p75 = 380 ms on mobile. Did we fix our INP problem? Runs attached: before.json (before the change) and after.json (after).",
21
+ "assertions": [
22
+ "Answers in the first lines that these runs do not show INP is fixed",
23
+ "Points out the two runs are not comparable because after.json was run with a 2x CPU slowdown and before.json with 4x, so part or all of the TBT and score change comes from the settings",
24
+ "States that TBT is a lab proxy and not INP, that a load run records no interactions, and that the check is RUM INP p75 after the change against the 200 ms threshold (380 ms was needs improvement)",
25
+ "Says each side is a single run and recommends the median of 3 to 5 runs per side with identical settings",
26
+ "Confirms ChatterBox no longer appears in the after run's long tasks or third-party list, so the deferral did take it out of the load",
27
+ "Names the first-party seatmap.4f2a91.js as the largest remaining long task (620 ms before, 410 ms after at 2x CPU) and the likely next target for INP work",
28
+ "Does not invent RUM or field numbers for the period after the change"
29
+ ]
30
+ },
31
+ {
32
+ "id": 3,
33
+ "prompt": "Quick one for the Slack thread, under 200 words please. Lighthouse mobile gives the Lumen Ledger pricing page a 48 — are we failing Core Web Vitals? What I can see in the report: Performance 48. FCP 3.2 s, LCP 6.8 s, TBT 1,450 ms, CLS 0.02, Speed Index 5.9 s. LCP element: <div class=\"pricing-hero\" style=\"background-image:url(/img/pricing-hero.jpg)\">. LCP breakdown: TTFB 380 ms, Load Delay 4,900 ms, Load Time 1,100 ms, Render Delay 420 ms. Opportunities: Reduce unused JavaScript, est savings 2.9 s; Eliminate render-blocking resources, est savings 1.1 s. Third-party: HelpDock 980 ms main-thread time.",
34
+ "assertions": [
35
+ "Says that whether the page passes or fails Core Web Vitals cannot be told from a lab run alone, and that field data at p75 (Search Console, CrUX or PageSpeed field data, or RUM) is needed",
36
+ "Does not present TBT 1,450 ms as INP; calls it a lab proxy",
37
+ "Identifies the LCP element as the CSS background image on div.pricing-hero and resource load delay (4.9 s of 6.8 s) as the dominant phase",
38
+ "Recommends making the hero image discoverable early: an <img> in the HTML with fetchpriority=\"high\", or a preload of /img/pricing-hero.jpg with fetchpriority=\"high\"",
39
+ "Does not add the 2.9 s and 1.1 s savings into a combined figure, and does not claim the unused-JavaScript saving moves LCP by 2.9 s",
40
+ "Mentions that this is one lab run on emulated mobile",
41
+ "Does not invent numbers, elements or field data not in the message",
42
+ "Stays under 200 words"
43
+ ]
44
+ },
45
+ {
46
+ "id": 4,
47
+ "held_out": "2026-10-20",
48
+ "prompt": "hey, quick one. attached the PSI run for our jacket PDP from this morning (psi-pdp-mobile-2026-10-19.json) plus two exports from our RUM tool (rum-inp-daily.csv and rum-inp-attribution-oct14-19.csv). we shipped the 'defer chatnest until after load' change on oct 13 and lighthouse went 78 -> 91, TBT 640 -> 290. PM wants to close the INP ticket today. search console still says INP poor but i assume that's just lag?? did our change fix INP or not, and if not what do we do next",
49
+ "assertions": [
50
+ "Answers the actual question up front: the change helped but did not fix INP, so the ticket should not be closed. It cites the RUM daily file, where PDP mobile INP p75 drops from roughly 539-580 ms (Oct 6-12) to roughly 459-481 ms (Oct 14-19). That is still above the 200 ms 'good' threshold (in the needs-improvement band).",
51
+ "Explains that the Lighthouse score and TBT gains (78 -> 91, 640 -> 290 ms) cannot show INP is fixed, because a lab navigation run has no user interactions and does not measure INP. TBT is only a load-time proxy.",
52
+ "Points out that the PSI field data has origin_fallback: true, so the INP p75 of 540 ms is for the whole fernhollow-outfitters.example origin, not this PDP URL. It also notes that CrUX/Search Console use a rolling 28-day window that is mostly from before the Oct 13 deploy, so they cannot confirm or refute the change yet. Lag is only part of the explanation.",
53
+ "Names button.add-to-cart as the main remaining INP problem (inp p75 486 ms, 4120 interactions). Its processing time dominates (processing p75 362 ms vs input delay p75 38 ms), and it is attributed to pdp-cart.8c1e.js. The fix offered is to shorten or split that handler, e.g. yield to the main thread, paint the feedback first and defer the non-visual work.",
54
+ "Uses the attribution data correctly: input delay on add-to-cart is small, so ChatNest contention is no longer the main cause there. It still flags that the ChatNest launcher interaction is poor (610 ms p75, input delay 290 ms, though only 520 interactions), and that ChatNest was deferred, not removed (820 ms main-thread time and two long tasks after TTI in the lab run).",
55
+ "Keeps the focus on INP. It does not lead with LCP, render-blocking CSS or the unused-JavaScript opportunity, and if it mentions them it says they do not bear on the INP question.",
56
+ "Gives a concrete way to verify the next fix: watch the RUM INP p75 per day and per target after deploying, and check CrUX/Search Console again once a full 28-day window has passed since the fix. Any lookup that needs the network (PSI/CrUX API, Search Console) is written as a command or step for the user, not reported as a result.",
57
+ "Invents nothing. Every number, selector, script URL, entity name and date it cites appears in the three provided files or the prompt, and it does not claim a URL-level CrUX value or post-deploy CrUX figures that the files do not contain."
58
+ ]
59
+ },
60
+ {
61
+ "id": 5,
62
+ "held_out": "2026-10-20",
63
+ "prompt": "Our agency, Brightline Digital, ran Lighthouse on the Quillstack homepage (lighthouse-home-mobile.json) and is proposing a three-week code-splitting project, because the top opportunity in the report is \"Reduce unused JavaScript\" with estimated savings of 1.9 s. Search Console shows the homepage failing Core Web Vitals on mobile. I've also pulled the CrUX API record for the page (crux-home-phone.json). Before I sign the SOW: will that project get us passing Core Web Vitals? If not, what should we fix instead? I'll forward your answer to our VP of Marketing, so please keep it short and non-technical where you can.",
64
+ "assertions": [
65
+ "Answers directly at the start: no, the unused-JavaScript project will not get the homepage passing Core Web Vitals. The field data fails only on CLS (p75 0.27, poor, above 0.25), while LCP p75 is 2100 ms and INP p75 is 160 ms, both already 'good'.",
66
+ "Explains that the 1.9 s figure is a lab estimate tied to load metrics (the report lists FCP 900 / LCP 1050 metric savings) and does nothing for layout shift. It also notes that Lighthouse's estimated savings overlap (for example with render-blocking-resources' 620 ms on FCP/LCP), so they cannot simply be added up.",
67
+ "Names the biggest shift correctly. The element that moves is body > main#content (score 0.091), and it moves because the late TallyConsent cookie banner (cdn.tallyconsent.example/v2/banner.js) is inserted above it; the banner itself is not the shifted element. The fix offered is to render the banner as a fixed or bottom overlay, or to reserve its space up front.",
68
+ "Names the second shift: section.hero > h1 (0.038), caused by the web font northwind-sans-bold.woff2 loading. It notes that the passing font-display audit (text visible with swap) does not prevent this shift, and recommends preloading the font and/or matching the fallback font's metrics (size-adjust / ascent-override), or using font-display: optional.",
69
+ "Ranks the fixes by CLS impact: cookie banner first, web font second, and the unsized Brightmoor logo image in ul.logo-strip (0.011, also flagged by unsized-images) last as a small width/height or aspect-ratio fix.",
70
+ "Notes that lab CLS (0.14) understates the field p75 (0.27), so a good Lighthouse number after the fix does not prove the page passes. Success should be confirmed in field data (CrUX's 28-day window, collection period here Sep 19 - Oct 16, or RUM), which takes up to about four weeks to show.",
71
+ "Is sized for forwarding to a VP: a short answer (roughly under 300 words, or a few bullets) in plain language. It is not an audit of every Lighthouse item, and it does not dwell on the 0.68 performance score, which is not what Core Web Vitals assessment uses.",
72
+ "Invents nothing. Every metric, selector, URL, vendor name and date it cites appears in lighthouse-home-mobile.json, crux-home-phone.json or the prompt, and it does not give made-up effort estimates or post-fix CLS numbers as if they were measured."
73
+ ]
74
+ }
75
+ ]
76
+ }