@booklib/core 2.0.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 (374) hide show
  1. package/.cursor/rules/booklib-standards.mdc +40 -0
  2. package/.gemini/context.md +372 -0
  3. package/AGENTS.md +166 -0
  4. package/CHANGELOG.md +226 -0
  5. package/CLAUDE.md +81 -0
  6. package/CODE_OF_CONDUCT.md +31 -0
  7. package/CONTRIBUTING.md +304 -0
  8. package/LICENSE +21 -0
  9. package/PLAN.md +28 -0
  10. package/README.ja.md +198 -0
  11. package/README.ko.md +198 -0
  12. package/README.md +503 -0
  13. package/README.pt-BR.md +198 -0
  14. package/README.uk.md +241 -0
  15. package/README.zh-CN.md +198 -0
  16. package/SECURITY.md +9 -0
  17. package/agents/architecture-reviewer.md +136 -0
  18. package/agents/booklib-reviewer.md +90 -0
  19. package/agents/data-reviewer.md +107 -0
  20. package/agents/jvm-reviewer.md +146 -0
  21. package/agents/python-reviewer.md +128 -0
  22. package/agents/rust-reviewer.md +115 -0
  23. package/agents/ts-reviewer.md +110 -0
  24. package/agents/ui-reviewer.md +117 -0
  25. package/assets/logo.svg +36 -0
  26. package/bin/booklib-mcp.js +304 -0
  27. package/bin/booklib.js +1705 -0
  28. package/bin/skills.cjs +1292 -0
  29. package/booklib-router.mdc +36 -0
  30. package/booklib.config.json +19 -0
  31. package/commands/animation-at-work.md +10 -0
  32. package/commands/clean-code-reviewer.md +10 -0
  33. package/commands/data-intensive-patterns.md +10 -0
  34. package/commands/data-pipelines.md +10 -0
  35. package/commands/design-patterns.md +10 -0
  36. package/commands/domain-driven-design.md +10 -0
  37. package/commands/effective-java.md +10 -0
  38. package/commands/effective-kotlin.md +10 -0
  39. package/commands/effective-python.md +10 -0
  40. package/commands/effective-typescript.md +10 -0
  41. package/commands/kotlin-in-action.md +10 -0
  42. package/commands/lean-startup.md +10 -0
  43. package/commands/microservices-patterns.md +10 -0
  44. package/commands/programming-with-rust.md +10 -0
  45. package/commands/refactoring-ui.md +10 -0
  46. package/commands/rust-in-action.md +10 -0
  47. package/commands/skill-router.md +10 -0
  48. package/commands/spring-boot-in-action.md +10 -0
  49. package/commands/storytelling-with-data.md +10 -0
  50. package/commands/system-design-interview.md +10 -0
  51. package/commands/using-asyncio-python.md +10 -0
  52. package/commands/web-scraping-python.md +10 -0
  53. package/community/registry.json +1616 -0
  54. package/hooks/hooks.json +23 -0
  55. package/hooks/posttooluse-capture.mjs +67 -0
  56. package/hooks/suggest.js +153 -0
  57. package/lib/agent-behaviors.js +40 -0
  58. package/lib/agent-detector.js +96 -0
  59. package/lib/config-loader.js +39 -0
  60. package/lib/conflict-resolver.js +148 -0
  61. package/lib/context-builder.js +574 -0
  62. package/lib/discovery-engine.js +298 -0
  63. package/lib/doctor/hook-installer.js +83 -0
  64. package/lib/doctor/usage-tracker.js +87 -0
  65. package/lib/engine/ai-features.js +253 -0
  66. package/lib/engine/auditor.js +103 -0
  67. package/lib/engine/bm25-index.js +178 -0
  68. package/lib/engine/capture.js +120 -0
  69. package/lib/engine/corrections.js +198 -0
  70. package/lib/engine/doctor.js +195 -0
  71. package/lib/engine/graph-injector.js +137 -0
  72. package/lib/engine/graph.js +161 -0
  73. package/lib/engine/handoff.js +405 -0
  74. package/lib/engine/indexer.js +242 -0
  75. package/lib/engine/parser.js +53 -0
  76. package/lib/engine/query-expander.js +42 -0
  77. package/lib/engine/reranker.js +40 -0
  78. package/lib/engine/rrf.js +59 -0
  79. package/lib/engine/scanner.js +151 -0
  80. package/lib/engine/searcher.js +139 -0
  81. package/lib/engine/session-coordinator.js +306 -0
  82. package/lib/engine/session-manager.js +429 -0
  83. package/lib/engine/synthesizer.js +70 -0
  84. package/lib/installer.js +70 -0
  85. package/lib/instinct-block.js +33 -0
  86. package/lib/mcp-config-writer.js +88 -0
  87. package/lib/paths.js +57 -0
  88. package/lib/profiles/design.md +19 -0
  89. package/lib/profiles/general.md +16 -0
  90. package/lib/profiles/research-analysis.md +22 -0
  91. package/lib/profiles/software-development.md +23 -0
  92. package/lib/profiles/writing-content.md +19 -0
  93. package/lib/project-initializer.js +916 -0
  94. package/lib/registry/skills.js +102 -0
  95. package/lib/registry-searcher.js +99 -0
  96. package/lib/rules/rules-manager.js +169 -0
  97. package/lib/skill-fetcher.js +333 -0
  98. package/lib/well-known-builder.js +70 -0
  99. package/lib/wizard/index.js +404 -0
  100. package/lib/wizard/integration-detector.js +41 -0
  101. package/lib/wizard/project-detector.js +100 -0
  102. package/lib/wizard/prompt.js +156 -0
  103. package/lib/wizard/registry-embeddings.js +107 -0
  104. package/lib/wizard/skill-recommender.js +69 -0
  105. package/llms-full.txt +254 -0
  106. package/llms.txt +70 -0
  107. package/package.json +45 -0
  108. package/research-reports/2026-04-01-current-architecture.md +160 -0
  109. package/research-reports/IDEAS.md +93 -0
  110. package/rules/common/clean-code.md +42 -0
  111. package/rules/java/effective-java.md +42 -0
  112. package/rules/kotlin/effective-kotlin.md +37 -0
  113. package/rules/python/effective-python.md +38 -0
  114. package/rules/rust/rust.md +37 -0
  115. package/rules/typescript/effective-typescript.md +42 -0
  116. package/scripts/gen-llms-full.mjs +36 -0
  117. package/scripts/gen-og.mjs +142 -0
  118. package/scripts/validate-frontmatter.js +25 -0
  119. package/skills/animation-at-work/SKILL.md +270 -0
  120. package/skills/animation-at-work/assets/example_asset.txt +1 -0
  121. package/skills/animation-at-work/evals/evals.json +44 -0
  122. package/skills/animation-at-work/evals/results.json +13 -0
  123. package/skills/animation-at-work/examples/after.md +64 -0
  124. package/skills/animation-at-work/examples/before.md +35 -0
  125. package/skills/animation-at-work/references/api_reference.md +369 -0
  126. package/skills/animation-at-work/references/review-checklist.md +79 -0
  127. package/skills/animation-at-work/scripts/audit_animations.py +295 -0
  128. package/skills/animation-at-work/scripts/example.py +1 -0
  129. package/skills/clean-code-reviewer/SKILL.md +444 -0
  130. package/skills/clean-code-reviewer/audit.json +35 -0
  131. package/skills/clean-code-reviewer/evals/evals.json +185 -0
  132. package/skills/clean-code-reviewer/evals/results.json +13 -0
  133. package/skills/clean-code-reviewer/examples/after.md +48 -0
  134. package/skills/clean-code-reviewer/examples/before.md +33 -0
  135. package/skills/clean-code-reviewer/references/api_reference.md +158 -0
  136. package/skills/clean-code-reviewer/references/practices-catalog.md +282 -0
  137. package/skills/clean-code-reviewer/references/review-checklist.md +254 -0
  138. package/skills/clean-code-reviewer/scripts/pre-review.py +206 -0
  139. package/skills/data-intensive-patterns/SKILL.md +267 -0
  140. package/skills/data-intensive-patterns/assets/example_asset.txt +1 -0
  141. package/skills/data-intensive-patterns/evals/evals.json +54 -0
  142. package/skills/data-intensive-patterns/evals/results.json +13 -0
  143. package/skills/data-intensive-patterns/examples/after.md +61 -0
  144. package/skills/data-intensive-patterns/examples/before.md +38 -0
  145. package/skills/data-intensive-patterns/references/api_reference.md +34 -0
  146. package/skills/data-intensive-patterns/references/patterns-catalog.md +551 -0
  147. package/skills/data-intensive-patterns/references/review-checklist.md +193 -0
  148. package/skills/data-intensive-patterns/scripts/adr.py +213 -0
  149. package/skills/data-intensive-patterns/scripts/example.py +1 -0
  150. package/skills/data-pipelines/SKILL.md +259 -0
  151. package/skills/data-pipelines/assets/example_asset.txt +1 -0
  152. package/skills/data-pipelines/evals/evals.json +45 -0
  153. package/skills/data-pipelines/evals/results.json +13 -0
  154. package/skills/data-pipelines/examples/after.md +97 -0
  155. package/skills/data-pipelines/examples/before.md +37 -0
  156. package/skills/data-pipelines/references/api_reference.md +301 -0
  157. package/skills/data-pipelines/references/review-checklist.md +181 -0
  158. package/skills/data-pipelines/scripts/example.py +1 -0
  159. package/skills/data-pipelines/scripts/new_pipeline.py +444 -0
  160. package/skills/design-patterns/SKILL.md +271 -0
  161. package/skills/design-patterns/assets/example_asset.txt +1 -0
  162. package/skills/design-patterns/evals/evals.json +46 -0
  163. package/skills/design-patterns/evals/results.json +13 -0
  164. package/skills/design-patterns/examples/after.md +52 -0
  165. package/skills/design-patterns/examples/before.md +29 -0
  166. package/skills/design-patterns/references/api_reference.md +1 -0
  167. package/skills/design-patterns/references/patterns-catalog.md +726 -0
  168. package/skills/design-patterns/references/review-checklist.md +173 -0
  169. package/skills/design-patterns/scripts/example.py +1 -0
  170. package/skills/design-patterns/scripts/scaffold.py +807 -0
  171. package/skills/domain-driven-design/SKILL.md +142 -0
  172. package/skills/domain-driven-design/assets/example_asset.txt +1 -0
  173. package/skills/domain-driven-design/evals/evals.json +48 -0
  174. package/skills/domain-driven-design/evals/results.json +13 -0
  175. package/skills/domain-driven-design/examples/after.md +80 -0
  176. package/skills/domain-driven-design/examples/before.md +43 -0
  177. package/skills/domain-driven-design/references/api_reference.md +1 -0
  178. package/skills/domain-driven-design/references/patterns-catalog.md +545 -0
  179. package/skills/domain-driven-design/references/review-checklist.md +158 -0
  180. package/skills/domain-driven-design/scripts/example.py +1 -0
  181. package/skills/domain-driven-design/scripts/scaffold.py +421 -0
  182. package/skills/effective-java/SKILL.md +227 -0
  183. package/skills/effective-java/assets/example_asset.txt +1 -0
  184. package/skills/effective-java/evals/evals.json +46 -0
  185. package/skills/effective-java/evals/results.json +13 -0
  186. package/skills/effective-java/examples/after.md +83 -0
  187. package/skills/effective-java/examples/before.md +37 -0
  188. package/skills/effective-java/references/api_reference.md +1 -0
  189. package/skills/effective-java/references/items-catalog.md +955 -0
  190. package/skills/effective-java/references/review-checklist.md +216 -0
  191. package/skills/effective-java/scripts/checkstyle_setup.py +211 -0
  192. package/skills/effective-java/scripts/example.py +1 -0
  193. package/skills/effective-kotlin/SKILL.md +271 -0
  194. package/skills/effective-kotlin/assets/example_asset.txt +1 -0
  195. package/skills/effective-kotlin/audit.json +29 -0
  196. package/skills/effective-kotlin/evals/evals.json +45 -0
  197. package/skills/effective-kotlin/evals/results.json +13 -0
  198. package/skills/effective-kotlin/examples/after.md +36 -0
  199. package/skills/effective-kotlin/examples/before.md +38 -0
  200. package/skills/effective-kotlin/references/api_reference.md +1 -0
  201. package/skills/effective-kotlin/references/practices-catalog.md +1228 -0
  202. package/skills/effective-kotlin/references/review-checklist.md +126 -0
  203. package/skills/effective-kotlin/scripts/example.py +1 -0
  204. package/skills/effective-python/SKILL.md +441 -0
  205. package/skills/effective-python/evals/evals.json +44 -0
  206. package/skills/effective-python/evals/results.json +13 -0
  207. package/skills/effective-python/examples/after.md +56 -0
  208. package/skills/effective-python/examples/before.md +40 -0
  209. package/skills/effective-python/ref-01-pythonic-thinking.md +202 -0
  210. package/skills/effective-python/ref-02-lists-and-dicts.md +146 -0
  211. package/skills/effective-python/ref-03-functions.md +186 -0
  212. package/skills/effective-python/ref-04-comprehensions-generators.md +211 -0
  213. package/skills/effective-python/ref-05-classes-interfaces.md +188 -0
  214. package/skills/effective-python/ref-06-metaclasses-attributes.md +209 -0
  215. package/skills/effective-python/ref-07-concurrency.md +213 -0
  216. package/skills/effective-python/ref-08-robustness-performance.md +248 -0
  217. package/skills/effective-python/ref-09-testing-debugging.md +253 -0
  218. package/skills/effective-python/ref-10-collaboration.md +175 -0
  219. package/skills/effective-python/references/api_reference.md +218 -0
  220. package/skills/effective-python/references/practices-catalog.md +483 -0
  221. package/skills/effective-python/references/review-checklist.md +190 -0
  222. package/skills/effective-python/scripts/lint.py +173 -0
  223. package/skills/effective-typescript/SKILL.md +262 -0
  224. package/skills/effective-typescript/audit.json +29 -0
  225. package/skills/effective-typescript/evals/evals.json +37 -0
  226. package/skills/effective-typescript/evals/results.json +13 -0
  227. package/skills/effective-typescript/examples/after.md +70 -0
  228. package/skills/effective-typescript/examples/before.md +47 -0
  229. package/skills/effective-typescript/references/api_reference.md +118 -0
  230. package/skills/effective-typescript/references/practices-catalog.md +371 -0
  231. package/skills/effective-typescript/scripts/review.py +169 -0
  232. package/skills/kotlin-in-action/SKILL.md +261 -0
  233. package/skills/kotlin-in-action/assets/example_asset.txt +1 -0
  234. package/skills/kotlin-in-action/evals/evals.json +43 -0
  235. package/skills/kotlin-in-action/evals/results.json +13 -0
  236. package/skills/kotlin-in-action/examples/after.md +53 -0
  237. package/skills/kotlin-in-action/examples/before.md +39 -0
  238. package/skills/kotlin-in-action/references/api_reference.md +1 -0
  239. package/skills/kotlin-in-action/references/practices-catalog.md +436 -0
  240. package/skills/kotlin-in-action/references/review-checklist.md +204 -0
  241. package/skills/kotlin-in-action/scripts/example.py +1 -0
  242. package/skills/kotlin-in-action/scripts/setup_detekt.py +224 -0
  243. package/skills/lean-startup/SKILL.md +160 -0
  244. package/skills/lean-startup/assets/example_asset.txt +1 -0
  245. package/skills/lean-startup/evals/evals.json +43 -0
  246. package/skills/lean-startup/evals/results.json +13 -0
  247. package/skills/lean-startup/examples/after.md +80 -0
  248. package/skills/lean-startup/examples/before.md +34 -0
  249. package/skills/lean-startup/references/api_reference.md +319 -0
  250. package/skills/lean-startup/references/review-checklist.md +137 -0
  251. package/skills/lean-startup/scripts/example.py +1 -0
  252. package/skills/lean-startup/scripts/new_experiment.py +286 -0
  253. package/skills/microservices-patterns/SKILL.md +384 -0
  254. package/skills/microservices-patterns/evals/evals.json +45 -0
  255. package/skills/microservices-patterns/evals/results.json +13 -0
  256. package/skills/microservices-patterns/examples/after.md +69 -0
  257. package/skills/microservices-patterns/examples/before.md +40 -0
  258. package/skills/microservices-patterns/references/patterns-catalog.md +391 -0
  259. package/skills/microservices-patterns/references/review-checklist.md +169 -0
  260. package/skills/microservices-patterns/scripts/new_service.py +583 -0
  261. package/skills/programming-with-rust/SKILL.md +209 -0
  262. package/skills/programming-with-rust/evals/evals.json +37 -0
  263. package/skills/programming-with-rust/evals/results.json +13 -0
  264. package/skills/programming-with-rust/examples/after.md +107 -0
  265. package/skills/programming-with-rust/examples/before.md +59 -0
  266. package/skills/programming-with-rust/references/api_reference.md +152 -0
  267. package/skills/programming-with-rust/references/practices-catalog.md +335 -0
  268. package/skills/programming-with-rust/scripts/review.py +142 -0
  269. package/skills/refactoring-ui/SKILL.md +362 -0
  270. package/skills/refactoring-ui/assets/example_asset.txt +1 -0
  271. package/skills/refactoring-ui/evals/evals.json +45 -0
  272. package/skills/refactoring-ui/evals/results.json +13 -0
  273. package/skills/refactoring-ui/examples/after.md +85 -0
  274. package/skills/refactoring-ui/examples/before.md +58 -0
  275. package/skills/refactoring-ui/references/api_reference.md +355 -0
  276. package/skills/refactoring-ui/references/review-checklist.md +114 -0
  277. package/skills/refactoring-ui/scripts/audit_css.py +250 -0
  278. package/skills/refactoring-ui/scripts/example.py +1 -0
  279. package/skills/rust-in-action/SKILL.md +350 -0
  280. package/skills/rust-in-action/evals/evals.json +38 -0
  281. package/skills/rust-in-action/evals/results.json +13 -0
  282. package/skills/rust-in-action/examples/after.md +156 -0
  283. package/skills/rust-in-action/examples/before.md +56 -0
  284. package/skills/rust-in-action/references/practices-catalog.md +346 -0
  285. package/skills/rust-in-action/scripts/review.py +147 -0
  286. package/skills/skill-router/SKILL.md +186 -0
  287. package/skills/skill-router/evals/evals.json +38 -0
  288. package/skills/skill-router/evals/results.json +13 -0
  289. package/skills/skill-router/examples/after.md +63 -0
  290. package/skills/skill-router/examples/before.md +39 -0
  291. package/skills/skill-router/references/api_reference.md +24 -0
  292. package/skills/skill-router/references/routing-heuristics.md +89 -0
  293. package/skills/skill-router/references/skill-catalog.md +174 -0
  294. package/skills/skill-router/scripts/route.py +266 -0
  295. package/skills/spring-boot-in-action/SKILL.md +340 -0
  296. package/skills/spring-boot-in-action/evals/evals.json +39 -0
  297. package/skills/spring-boot-in-action/evals/results.json +13 -0
  298. package/skills/spring-boot-in-action/examples/after.md +185 -0
  299. package/skills/spring-boot-in-action/examples/before.md +84 -0
  300. package/skills/spring-boot-in-action/references/practices-catalog.md +403 -0
  301. package/skills/spring-boot-in-action/scripts/review.py +184 -0
  302. package/skills/storytelling-with-data/SKILL.md +241 -0
  303. package/skills/storytelling-with-data/assets/example_asset.txt +1 -0
  304. package/skills/storytelling-with-data/evals/evals.json +47 -0
  305. package/skills/storytelling-with-data/evals/results.json +13 -0
  306. package/skills/storytelling-with-data/examples/after.md +50 -0
  307. package/skills/storytelling-with-data/examples/before.md +33 -0
  308. package/skills/storytelling-with-data/references/api_reference.md +379 -0
  309. package/skills/storytelling-with-data/references/review-checklist.md +111 -0
  310. package/skills/storytelling-with-data/scripts/chart_review.py +301 -0
  311. package/skills/storytelling-with-data/scripts/example.py +1 -0
  312. package/skills/system-design-interview/SKILL.md +233 -0
  313. package/skills/system-design-interview/assets/example_asset.txt +1 -0
  314. package/skills/system-design-interview/evals/evals.json +46 -0
  315. package/skills/system-design-interview/evals/results.json +13 -0
  316. package/skills/system-design-interview/examples/after.md +94 -0
  317. package/skills/system-design-interview/examples/before.md +27 -0
  318. package/skills/system-design-interview/references/api_reference.md +582 -0
  319. package/skills/system-design-interview/references/review-checklist.md +201 -0
  320. package/skills/system-design-interview/scripts/example.py +1 -0
  321. package/skills/system-design-interview/scripts/new_design.py +421 -0
  322. package/skills/using-asyncio-python/SKILL.md +290 -0
  323. package/skills/using-asyncio-python/assets/example_asset.txt +1 -0
  324. package/skills/using-asyncio-python/evals/evals.json +43 -0
  325. package/skills/using-asyncio-python/evals/results.json +13 -0
  326. package/skills/using-asyncio-python/examples/after.md +68 -0
  327. package/skills/using-asyncio-python/examples/before.md +39 -0
  328. package/skills/using-asyncio-python/references/api_reference.md +267 -0
  329. package/skills/using-asyncio-python/references/review-checklist.md +149 -0
  330. package/skills/using-asyncio-python/scripts/check_blocking.py +270 -0
  331. package/skills/using-asyncio-python/scripts/example.py +1 -0
  332. package/skills/web-scraping-python/SKILL.md +280 -0
  333. package/skills/web-scraping-python/assets/example_asset.txt +1 -0
  334. package/skills/web-scraping-python/evals/evals.json +46 -0
  335. package/skills/web-scraping-python/evals/results.json +13 -0
  336. package/skills/web-scraping-python/examples/after.md +109 -0
  337. package/skills/web-scraping-python/examples/before.md +40 -0
  338. package/skills/web-scraping-python/references/api_reference.md +393 -0
  339. package/skills/web-scraping-python/references/review-checklist.md +163 -0
  340. package/skills/web-scraping-python/scripts/example.py +1 -0
  341. package/skills/web-scraping-python/scripts/new_scraper.py +231 -0
  342. package/skills/writing-plans/audit.json +34 -0
  343. package/tests/agent-detector.test.js +83 -0
  344. package/tests/corrections.test.js +245 -0
  345. package/tests/doctor/hook-installer.test.js +72 -0
  346. package/tests/doctor/usage-tracker.test.js +140 -0
  347. package/tests/engine/benchmark-eval.test.js +31 -0
  348. package/tests/engine/bm25-index.test.js +85 -0
  349. package/tests/engine/capture-command.test.js +35 -0
  350. package/tests/engine/capture.test.js +17 -0
  351. package/tests/engine/graph-augmented-search.test.js +107 -0
  352. package/tests/engine/graph-injector.test.js +44 -0
  353. package/tests/engine/graph.test.js +216 -0
  354. package/tests/engine/hybrid-searcher.test.js +74 -0
  355. package/tests/engine/indexer-bm25.test.js +37 -0
  356. package/tests/engine/mcp-tools.test.js +73 -0
  357. package/tests/engine/project-initializer-mcp.test.js +99 -0
  358. package/tests/engine/query-expander.test.js +36 -0
  359. package/tests/engine/reranker.test.js +51 -0
  360. package/tests/engine/rrf.test.js +49 -0
  361. package/tests/engine/srag-prefix.test.js +47 -0
  362. package/tests/instinct-block.test.js +23 -0
  363. package/tests/mcp-config-writer.test.js +60 -0
  364. package/tests/project-initializer-new-agents.test.js +48 -0
  365. package/tests/rules/rules-manager.test.js +230 -0
  366. package/tests/well-known-builder.test.js +40 -0
  367. package/tests/wizard/integration-detector.test.js +31 -0
  368. package/tests/wizard/project-detector.test.js +51 -0
  369. package/tests/wizard/prompt-session.test.js +61 -0
  370. package/tests/wizard/prompt.test.js +16 -0
  371. package/tests/wizard/registry-embeddings.test.js +35 -0
  372. package/tests/wizard/skill-recommender.test.js +34 -0
  373. package/tests/wizard/slot-count.test.js +25 -0
  374. package/vercel.json +21 -0
@@ -0,0 +1,126 @@
1
+ # Effective Kotlin — Code Review Checklist
2
+
3
+ Systematic checklist for reviewing Kotlin code against the 52 best-practice items
4
+ from *Effective Kotlin* (2nd Edition) by Marcin Moskała.
5
+
6
+ ---
7
+
8
+ ## 1. Safety (Items 1–10)
9
+
10
+ ### Mutability & Scope
11
+ - [ ] **Item 1 — Limit mutability** — Are `val` and immutable collections used by default? Is `var` used only when truly necessary? Are mutable collections encapsulated?
12
+ - [ ] **Item 2 — Minimize variable scope** — Are variables declared close to first use? Are any variables declared at function-top that could be scoped tighter? Are `let`/`run` used to restrict scope?
13
+
14
+ ### Null Safety & Types
15
+ - [ ] **Item 3 — Eliminate platform types** — At Java/Kotlin boundaries, are types explicitly annotated? Do platform types (`Type!`) leak into Kotlin APIs?
16
+ - [ ] **Item 4 — No exposed inferred types** — Do public functions and properties declare explicit types? Could an implementation change silently alter the public type?
17
+
18
+ ### Preconditions & Error Handling
19
+ - [ ] **Item 5 — Specify expectations** — Are `require()` and `check()` used at function entry points? Are preconditions documented for public functions?
20
+ - [ ] **Item 6 — Standard errors** — Are standard exceptions (IllegalArgumentException, IllegalStateException) used instead of custom exceptions for common conditions?
21
+ - [ ] **Item 7 — Null or Failure for expected outcomes** — Do functions that can legitimately fail return `null` or `Result` instead of throwing? Are exceptions reserved for programming errors?
22
+ - [ ] **Item 8 — Proper null handling** — Is `!!` absent or justified? Are safe calls (`?.`), Elvis (`?:`), and smart casts used consistently? No unnecessary null checks?
23
+
24
+ ### Resources & Testing
25
+ - [ ] **Item 9 — Resources with use()** — Are all Closeable/AutoCloseable resources wrapped with `use()`? Are file reads using `useLines()` or `use()`?
26
+ - [ ] **Item 10 — Unit tests** — Is business logic covered by tests? Are edge cases and error paths tested? Are tests independent and descriptive?
27
+
28
+ ---
29
+
30
+ ## 2. Readability (Items 11–18)
31
+
32
+ - [ ] **Item 11 — Design for readability** — Is the code clear on first read? Are there unnecessarily clever constructions? Are complex expressions broken into named intermediate variables?
33
+ - [ ] **Item 12 — Operator meaning consistent** — Do operator overloads match their conventional function names (`plus`, `times`, `contains`)? No surprising operator semantics?
34
+ - [ ] **Item 13 — No Unit? returns** — Does any function return `Unit?`? Is `Unit?` used in conditional logic? Replace with Boolean or sealed type.
35
+ - [ ] **Item 14 — Types specified when unclear** — Are inferred types obvious from context? Do public APIs have explicit type annotations? Would a reader need to navigate to a function to understand the type?
36
+ - [ ] **Item 15 — Explicit receivers** — In nested scope functions or DSLs, are receivers referenced explicitly when ambiguous? Is `@DslMarker` used for DSL scope control?
37
+ - [ ] **Item 16 — Properties represent state** — Do custom getters perform only cheap, side-effect-free, idempotent computations? Is behavior in functions, not properties?
38
+ - [ ] **Item 17 — Named arguments** — Are boolean parameters named? Are same-typed parameters named? Are configuration-style calls using named arguments?
39
+ - [ ] **Item 18 — Coding conventions** — Does the code follow Kotlin coding conventions? Are naming, formatting, and structure consistent? Is ktlint/detekt configured?
40
+
41
+ ---
42
+
43
+ ## 3. Reusability (Items 19–25)
44
+
45
+ - [ ] **Item 19 — No repeated knowledge** — Is any business rule, validation, or algorithm defined in more than one place? Is there a single source of truth for each concept?
46
+ - [ ] **Item 20 — stdlib used** — Are standard library functions used instead of hand-rolled equivalents? Check: collection operations, string building, scope functions.
47
+ - [ ] **Item 21 — Property delegation** — Are there repeated property patterns (lazy init, change notification, validation) that should use `by lazy`, `Delegates.observable`, or custom delegates?
48
+ - [ ] **Item 22 — Generics for algorithms** — Are utility functions generic where possible? Is there type-specific duplication that could be parameterized?
49
+ - [ ] **Item 23 — No shadowed type parameters** — In generic classes, do member functions avoid redeclaring the class's type parameter with the same name?
50
+ - [ ] **Item 24 — Variance considered** — Are `out`/`in` modifiers applied to type parameters that are only produced or consumed? Could variance allow more flexible subtype usage?
51
+ - [ ] **Item 25 — Multiplatform reuse** — If targeting multiple platforms, is platform-independent logic in common modules? Are `expect`/`actual` declarations used appropriately?
52
+
53
+ ---
54
+
55
+ ## 4. Abstraction Design (Items 26–32)
56
+
57
+ - [ ] **Item 26 — Single level of abstraction** — Does each function operate at one consistent level of detail? Are there functions mixing high-level orchestration with low-level manipulation?
58
+ - [ ] **Item 27 — Abstraction protects against changes** — Are external dependencies wrapped behind interfaces? Can implementations be swapped without changing business logic?
59
+ - [ ] **Item 28 — API stability specified** — Are experimental APIs annotated with `@RequiresOptIn`? Are deprecated elements marked with `@Deprecated` with `ReplaceWith`?
60
+ - [ ] **Item 29 — External APIs wrapped** — Are third-party libraries accessed through your own abstractions? Can they be mocked in tests?
61
+ - [ ] **Item 30 — Minimal visibility** — Is `private` the default? Are `internal` and `public` used only when needed? Do properties have restricted setters where appropriate?
62
+ - [ ] **Item 31 — Contracts documented** — Do public APIs have KDoc? Are parameters, return values, exceptions, and edge cases documented?
63
+ - [ ] **Item 32 — Contracts respected** — Do implementations honor the contracts of interfaces they implement? Are `equals`/`hashCode`/`compareTo` contracts maintained?
64
+
65
+ ---
66
+
67
+ ## 5. Object Creation (Items 33–35)
68
+
69
+ - [ ] **Item 33 — Factory functions considered** — Where constructors are limiting, are factory functions used? Are there complex constructors that would benefit from named factories?
70
+ - [ ] **Item 34 — Primary constructor with defaults** — Are Kotlin primary constructors with default values used instead of Java-style builders or telescoping constructors?
71
+ - [ ] **Item 35 — DSL for complex creation** — For hierarchical or complex object assembly, is a type-safe builder DSL used? Is `@DslMarker` applied?
72
+
73
+ ---
74
+
75
+ ## 6. Class Design (Items 36–44)
76
+
77
+ ### Composition & Data
78
+ - [ ] **Item 36 — Composition over inheritance** — Is inheritance used only for IS-A relationships? Is Kotlin's `by` delegation used for code reuse? Are there fragile base class issues?
79
+ - [ ] **Item 37 — Data modifier** — Are data-holding classes using the `data` modifier? Are generated methods (equals, hashCode, copy, toString) appropriate?
80
+ - [ ] **Item 38 — Function types for single-method interfaces** — Are single-method interfaces replaced with function types `(A) -> B` or `fun interface`? Is SAM conversion used for Java interop?
81
+
82
+ ### Hierarchies & Contracts
83
+ - [ ] **Item 39 — Sealed hierarchies over tagged classes** — Are there classes with type enums and conditional logic that should be sealed class hierarchies? Do `when` blocks benefit from exhaustiveness?
84
+ - [ ] **Item 40 — equals contract** — Is `equals` reflexive, symmetric, transitive, and consistent? Is it overridden together with `hashCode`? Does inheritance break symmetry?
85
+ - [ ] **Item 41 — hashCode contract** — Is `hashCode` consistent with `equals`? Are the same properties used in both? Are mutable objects used as hash keys?
86
+ - [ ] **Item 42 — compareTo contract** — Is `compareTo` antisymmetric, transitive, and consistent with equals? Is `compareBy`/`compareValuesBy` used for clean implementation?
87
+
88
+ ### Extensions
89
+ - [ ] **Item 43 — Non-essential API in extensions** — Are classes bloated with utility methods that could be extensions? Could non-essential methods be extracted to improve core API focus?
90
+ - [ ] **Item 44 — No member extensions** — Are extension functions defined at top-level or locally, not as class members? Member extensions are confusing and limited.
91
+
92
+ ---
93
+
94
+ ## 7. Efficiency (Items 45–52)
95
+
96
+ ### Object Creation & Inline
97
+ - [ ] **Item 45 — No unnecessary objects** — In hot paths: are Regex instances cached? Are strings concatenated with StringBuilder? Are primitives used instead of nullable/boxed types?
98
+ - [ ] **Item 46 — Inline for lambdas** — Are frequently-called higher-order functions marked `inline`? Is `noinline` used for stored lambdas? Is `reified` used where runtime type info is needed?
99
+ - [ ] **Item 47 — Inline value classes** — Are domain primitives (IDs, quantities, validated strings) using `@JvmInline value class` to avoid allocation? Are boxing scenarios understood?
100
+ - [ ] **Item 48 — Obsolete references eliminated** — Are unneeded references nulled out? Are caches bounded? Are listeners/callbacks properly unregistered? Are closure captures reviewed?
101
+
102
+ ### Collection Processing
103
+ - [ ] **Item 49 — Sequence for multi-step processing** — For large collections with 2+ chained operations, is `.asSequence()` used? Are intermediate collections avoided?
104
+ - [ ] **Item 50 — Operations limited** — Is `any {}` used instead of `filter {}.isNotEmpty()`? Is `count {}` used instead of `filter {}.count()`? Is `maxByOrNull` used instead of `sortedBy {}.last()`?
105
+ - [ ] **Item 51 — Primitive arrays** — For numeric-heavy processing, are `IntArray`/`LongArray`/`DoubleArray` used instead of `List<Int>`/`Array<Int>`?
106
+ - [ ] **Item 52 — Mutable collections where needed** — In local scope hot paths, are mutable collections used for accumulation instead of repeated immutable concatenation? Is mutability kept local?
107
+
108
+ ---
109
+
110
+ ## Quick Review Workflow
111
+
112
+ 1. **Safety first** — Scan for `!!`, `var`, unclosed resources, missing preconditions, platform types
113
+ 2. **Readability pass** — Check for clarity, naming, operator usage, coding conventions
114
+ 3. **Design assessment** — Evaluate abstraction levels, duplication, visibility, inheritance vs composition
115
+ 4. **Kotlin idiom check** — Are Kotlin features (data class, sealed class, extension functions, scope functions, delegation) used appropriately?
116
+ 5. **Efficiency review** — For hot paths only: check collection processing, object creation, inline opportunities
117
+ 6. **Prioritize findings** — Rank by severity: safety > correctness > readability > design > efficiency
118
+
119
+ ## Severity Levels
120
+
121
+ | Severity | Description | Example |
122
+ |----------|-------------|---------|
123
+ | **Critical** | Safety issues, potential crashes, data corruption | `!!` on user input, leaked resources, broken equals/hashCode, mutable shared state without synchronization |
124
+ | **High** | Incorrect Kotlin usage, missed null safety, design violations | Platform types leaking, inheritance abuse, throwing on expected failures, no precondition checks |
125
+ | **Medium** | Non-idiomatic code, missed Kotlin features, readability issues | Java-style builders, manual loops instead of stdlib, tagged classes, no named arguments for booleans |
126
+ | **Low** | Polish, minor optimizations, style improvements | Missing KDoc, Sequence opportunity, inline value class opportunity, convention inconsistencies |
@@ -0,0 +1,441 @@
1
+ ---
2
+ name: effective-python
3
+ version: "1.0"
4
+ license: MIT
5
+ tags: [python, oop, idioms]
6
+ description: Review existing Python code and write new Python code following the 90 best practices from "Effective Python" by Brett Slatkin (2nd Edition). Use when writing Python, reviewing Python code, or wanting idiomatic, Pythonic solutions.
7
+ ---
8
+
9
+ # Effective Python Skill
10
+
11
+ Apply the 90 items from Brett Slatkin's "Effective Python" (2nd Edition) to review existing code and write new Python code. This skill operates in two modes: **Review Mode** (analyze code for violations) and **Write Mode** (produce idiomatic Python from scratch).
12
+
13
+ ## Reference Files
14
+
15
+ This skill includes categorized reference files with all 90 items:
16
+
17
+ - `ref-01-pythonic-thinking.md` — Items 1-10: PEP 8, f-strings, bytes/str, walrus operator, unpacking, enumerate, zip, slicing
18
+ - `ref-02-lists-and-dicts.md` — Items 11-18: Slicing, sorting, dict ordering, defaultdict, __missing__
19
+ - `ref-03-functions.md` — Items 19-26: Exceptions vs None, closures, *args/**kwargs, keyword-only args, decorators
20
+ - `ref-04-comprehensions-generators.md` — Items 27-36: Comprehensions, generators, yield from, itertools
21
+ - `ref-05-classes-interfaces.md` — Items 37-43: Composition, @classmethod, super(), mix-ins, public attrs
22
+ - `ref-06-metaclasses-attributes.md` — Items 44-51: @property, descriptors, __getattr__, __init_subclass__, class decorators
23
+ - `ref-07-concurrency.md` — Items 52-64: subprocess, threads, Lock, Queue, coroutines, asyncio
24
+ - `ref-08-robustness-performance.md` — Items 65-76: try/except, contextlib, datetime, decimal, profiling, data structures
25
+ - `ref-09-testing-debugging.md` — Items 77-85: TestCase, mocks, dependency injection, pdb, tracemalloc
26
+ - `ref-10-collaboration.md` — Items 86-90: Docstrings, packages, root exceptions, virtual environments
27
+
28
+ ## How to Use This Skill
29
+
30
+ **Before responding**, read the relevant reference files based on the code's topic. For a general review, read all files. For targeted work (e.g., writing async code), read the specific reference (e.g., `ref-07-concurrency.md`).
31
+
32
+ ---
33
+
34
+ ## Mode 1: Code Review
35
+
36
+ When the user asks you to **review** existing Python code, follow this process:
37
+
38
+ ### Step 1: Read Relevant References
39
+ Determine which chapters apply to the code under review and read those reference files. If unsure, read all of them.
40
+
41
+ ### Step 2: Calibrate Your Response
42
+
43
+ **If the code is already well-written and idiomatic:**
44
+ - Say so explicitly and upfront. Do not manufacture issues to appear thorough.
45
+ - Praise the good patterns you see (see "Praising Good Patterns" below).
46
+ - Any suggestions must be framed as minor optional improvements, not as violations or issues.
47
+
48
+ **If the code has real problems:**
49
+ - Identify and report them clearly with item references.
50
+
51
+ ### Step 3: Praise Good Patterns (when present)
52
+ When the code uses these patterns correctly, explicitly praise them:
53
+
54
+ <strengths_to_praise>
55
+ - **`@contextmanager`** for resource management: "Good use of `@contextmanager` (Item 66) — avoids boilerplate try/finally and makes the cleanup intent clear."
56
+ - **Generator functions** (`yield`) for memory efficiency: "Good use of a generator (Item 30) — avoids loading the entire sequence into memory."
57
+ - **Type annotations** on public functions: "Good use of type annotations (Item 84) — improves readability and enables static analysis."
58
+ - **Docstrings** on all public APIs: "Good docstrings (Item 84) — clearly communicates purpose and parameters."
59
+ - **`@dataclass`** for plain data holders: "Good use of `@dataclass` (Items 37–43) — reduces boilerplate and provides automatic `__repr__`, `__eq__`."
60
+ - **List/dict/set comprehensions** instead of manual loops: "Good use of comprehensions (Item 27) — more readable and Pythonic."
61
+ - **`enumerate`** instead of `range(len(...))`: "Good use of `enumerate` (Item 7)."
62
+ </strengths_to_praise>
63
+
64
+ ### Step 4: Analyze the Code for Issues
65
+ For each relevant item from the book, check whether the code follows or violates the guideline. Focus on:
66
+
67
+ <core_principles>
68
+ 1. **Style and Idiom** (Items 1-10): Is it Pythonic? Does it use f-strings, unpacking, enumerate, zip properly?
69
+ 2. **Data Structures** (Items 11-18): Are lists and dicts used correctly? Is sorting done with key functions?
70
+ 3. **Function Design** (Items 19-26): Do functions raise exceptions instead of returning None? Are args well-structured?
71
+ 4. **Comprehensions & Generators** (Items 27-36): Are comprehensions preferred over map/filter? Are generators used for large sequences?
72
+ 5. **Class Design** (Items 37-43): Is composition preferred over deep nesting? Are mix-ins used correctly? Is `@dataclass` used for plain data holders?
73
+ 6. **Metaclasses & Attributes** (Items 44-51): Are plain attributes used instead of getter/setter methods? Is @property used appropriately?
74
+ 7. **Concurrency** (Items 52-64): Are threads used only for I/O? Is asyncio structured correctly?
75
+ 8. **Robustness** (Items 65-76): Is error handling structured with try/except/else/finally? Are the right data structures chosen?
76
+ 9. **Testing** (Items 77-85): Are tests well-structured? Are mocks used appropriately?
77
+ 10. **Collaboration** (Items 86-90): Are docstrings present? Are APIs stable?
78
+
79
+ ### Key Anti-Patterns to Always Check
80
+
81
+ <anti_patterns>
82
+ - **Mutable default arguments** (Item 24): `def f(items=[])` is a critical bug — the list is shared across all calls. Always use `None` and initialize inside the function body.
83
+ ```python
84
+ # WRONG — shared mutable default
85
+ def process(results=[]):
86
+ results.append(...)
87
+
88
+ # RIGHT — use None sentinel
89
+ def process(results=None):
90
+ if results is None:
91
+ results = []
92
+ results.append(...)
93
+ ```
94
+
95
+ - **Bare `except:`** clause (Item 65): `except:` without a type catches `KeyboardInterrupt`, `SystemExit`, and `GeneratorExit`, silently killing the program. Always catch specific exception types: `except (ValueError, KeyError):` or at minimum `except Exception:`.
96
+
97
+ - **`for i in range(len(seq))`** (Item 7): Use `for item in seq` directly, or `for i, item in enumerate(seq)` when you need the index.
98
+
99
+ - **Manual list-building loops** (Item 27): Any loop that creates an empty list and appends inside the loop body should be a list comprehension.
100
+ ```python
101
+ # WRONG
102
+ result = []
103
+ for x in items:
104
+ if x > 0:
105
+ result.append(x * 2)
106
+
107
+ # RIGHT
108
+ result = [x * 2 for x in items if x > 0]
109
+ ```
110
+
111
+ - **Java-style getter/setter methods** (Item 44): `get_name()`, `set_price()`, `get_value()` are non-Pythonic. Access attributes directly or use `@property` when validation is required.
112
+
113
+ - **`== True` / `== False` comparisons** (Item 2 / PEP 8): `if x == True:` should be `if x:`. `return self.in_stock == True` should be `return self.in_stock`.
114
+
115
+ - **Double-underscore name mangling** (Item 42): `self.__items` makes the attribute inaccessible to subclasses and creates maintenance friction. Use single underscore `self._items` to signal "internal use" without enforced hiding.
116
+
117
+ - **Plain data-holder class without `@dataclass`** (Items 37–43): Any class whose `__init__` only assigns parameters to `self.attr` with no logic should be a `@dataclass`. Dataclasses automatically generate `__repr__`, `__eq__`, and `__init__`, and signal the data-holder intent. **Crucially: `@dataclass` and `@property` can coexist.** If one field needs validation, make it a `@property` with a setter inside the `@dataclass`. This is the correct Pythonic pattern — do NOT abandon `@dataclass` just because one field has a validator.
118
+ ```python
119
+ from dataclasses import dataclass, field
120
+
121
+ @dataclass
122
+ class Product:
123
+ name: str
124
+ category: str
125
+ in_stock: bool = True
126
+ _price: float = field(default=0.0, repr=False)
127
+
128
+ @property
129
+ def price(self) -> float:
130
+ return self._price
131
+
132
+ @price.setter
133
+ def price(self, value: float) -> None:
134
+ if value < 0:
135
+ raise ValueError('Price cannot be negative')
136
+ self._price = value
137
+ ```
138
+
139
+ - **Missing `__repr__`** (Items 37–43): Any class that is not a `@dataclass` should define `__repr__` to aid debugging. Without it, `repr(obj)` shows only the class name and memory address.
140
+
141
+ - **Returning `None` for failure** (Item 20): Functions should raise exceptions for error conditions, not return `None`. Returning `None` forces callers to check for `None` every time and doesn't carry error information.
142
+
143
+ - **`else` block after `for`/`while`** (Item 9): The loop-`else` clause fires when the loop completes without a `break`, which is rarely the intended semantics and confuses readers. Avoid it.
144
+ </anti_patterns>
145
+ </core_principles>
146
+
147
+ ### Step 5: Report Findings
148
+ For each issue found, report:
149
+ - **Item number and name** (e.g., "Item 4: Prefer Interpolated F-Strings")
150
+ - **Location** in the code
151
+ - **What's wrong** (the anti-pattern)
152
+ - **How to fix it** (the Pythonic way)
153
+ - **Priority**: Critical (bugs/correctness), Important (maintainability), Suggestion (style)
154
+
155
+ ### Step 6: Provide Fixed Code
156
+ Offer a corrected version of the code with all issues addressed, with comments explaining each change.
157
+
158
+ ---
159
+
160
+ ## Mode 2: Writing New Code
161
+
162
+ When the user asks you to **write** new Python code, follow these principles:
163
+
164
+ ### Always Apply These Core Practices
165
+
166
+ <guidelines>
167
+ 1. **Follow PEP 8** — Use consistent naming (snake_case for functions/variables, PascalCase for classes). Use `pylint` and `black`-compatible style.
168
+
169
+ 2. **Use f-strings** for string formatting (Item 4). Never use % or .format() for simple cases.
170
+
171
+ 3. **Use unpacking** instead of indexing (Item 6). Prefer `first, second = my_list` over `my_list[0]`.
172
+
173
+ 4. **Use enumerate** instead of range(len(...)) (Item 7).
174
+
175
+ 5. **Use zip** to iterate over multiple lists in parallel (Item 8). Use `zip_longest` from itertools when lengths differ.
176
+
177
+ 6. **Avoid else blocks** after for/while loops (Item 9).
178
+
179
+ 7. **Use assignment expressions** (:= walrus operator) to reduce repetition when appropriate (Item 10).
180
+
181
+ 8. **Raise exceptions** instead of returning None for failure cases (Item 20).
182
+
183
+ 9. **Use `None` as the default for mutable default arguments** (Item 24). Never use `[]`, `{}`, or any other mutable object as a default argument value; initialize inside the function body.
184
+
185
+ 10. **Use keyword-only arguments** for clarity (Item 25). Use positional-only args to separate API from implementation (Item 25).
186
+
187
+ 11. **Use functools.wraps** on all decorators (Item 26).
188
+
189
+ 12. **Prefer comprehensions** over map/filter (Item 27). Keep them simple — no more than two expressions (Item 28).
190
+
191
+ 13. **Use generators** for large sequences instead of returning lists (Item 30).
192
+
193
+ 14. **Use `@dataclass`** for plain data-holder classes (Items 37–43). A `@dataclass` automatically provides `__init__`, `__repr__`, and `__eq__`, and makes the data-holder intent explicit. Only write a manual `__init__` when you need real logic that a dataclass can't handle. Add `__repr__` to any class that doesn't use `@dataclass`, to make debugging easier.
194
+
195
+ 15. **Prefer composition** over deeply nested classes (Item 37).
196
+
197
+ 16. **Use @classmethod** for polymorphic constructors (Item 39).
198
+
199
+ 17. **Always call super().__init__** (Item 40).
200
+
201
+ 18. **Use plain attributes** instead of getter/setter methods. Use @property for special behavior (Item 44).
202
+
203
+ 19. **Use try/except/else/finally** structure correctly (Item 65). Always catch specific exception types, never bare `except:`.
204
+
205
+ 20. **Write docstrings** for every module, class, and function (Item 84).
206
+ </guidelines>
207
+
208
+ ### Code Structure Template
209
+
210
+ <examples>
211
+ <example id="1" title="Module and class structure template">
212
+
213
+ When writing new modules or classes, follow this structure:
214
+
215
+ ```python
216
+ """Module docstring describing purpose."""
217
+
218
+ # Standard library imports
219
+ # Third-party imports
220
+ # Local imports
221
+
222
+ # Module-level constants
223
+
224
+ class MyClass:
225
+ """Class docstring describing purpose and usage.
226
+
227
+ Attributes:
228
+ attr_name: Description of attribute.
229
+ """
230
+
231
+ def __init__(self, param: type) -> None:
232
+ """Initialize with description of params."""
233
+ self.param = param # Use public attributes (Item 42)
234
+
235
+ @classmethod
236
+ def from_alternative(cls, data):
237
+ """Alternative constructor (Item 39)."""
238
+ return cls(processed_data)
239
+
240
+ def method(self, arg: type) -> return_type:
241
+ """Method docstring.
242
+
243
+ Args:
244
+ arg: Description.
245
+
246
+ Returns:
247
+ Description of return value.
248
+
249
+ Raises:
250
+ ValueError: When arg is invalid (Item 20).
251
+ """
252
+ pass
253
+ ```
254
+ </example>
255
+
256
+ <example id="2" title="Mutable default argument — correct pattern">
257
+
258
+ ```python
259
+ # WRONG — mutable default causes shared state across all calls
260
+ def append_to(element, to=[]):
261
+ to.append(element)
262
+ return to
263
+
264
+ # RIGHT — use None sentinel, initialize inside
265
+ def append_to(element, to=None):
266
+ if to is None:
267
+ to = []
268
+ to.append(element)
269
+ return to
270
+ ```
271
+ </example>
272
+
273
+ <example id="3" title="Plain data holder — use @dataclass, even with @property validation">
274
+
275
+ ```python
276
+ # WRONG — manual __init__ boilerplate for data holder
277
+ class Point:
278
+ def __init__(self, x, y):
279
+ self.x = x
280
+ self.y = y
281
+
282
+ # RIGHT — @dataclass provides __init__, __repr__, __eq__ for free
283
+ from dataclasses import dataclass
284
+
285
+ @dataclass
286
+ class Point:
287
+ x: float
288
+ y: float
289
+ ```
290
+
291
+ **Important:** `@dataclass` and `@property` are compatible. When one field needs validation, use both — the `@dataclass` handles the boilerplate and the `@property` handles validation. Do NOT fall back to a plain class just because one field has a setter.
292
+
293
+ ```python
294
+ # WRONG — abandoning @dataclass because price needs validation
295
+ class Product:
296
+ def __init__(self, name, price, category):
297
+ self.name = name
298
+ self.price = price # validation via set_price()
299
+ self.category = category
300
+
301
+ def set_price(self, value):
302
+ if value < 0:
303
+ raise ValueError("Price cannot be negative")
304
+ self.price = value
305
+
306
+ # RIGHT — @dataclass + @property work together
307
+ from dataclasses import dataclass, field
308
+
309
+ @dataclass
310
+ class Product:
311
+ name: str
312
+ category: str
313
+ in_stock: bool = True
314
+ _price: float = field(default=0.0, repr=False)
315
+
316
+ @property
317
+ def price(self) -> float:
318
+ return self._price
319
+
320
+ @price.setter
321
+ def price(self, value: float) -> None:
322
+ if value < 0:
323
+ raise ValueError("Price cannot be negative")
324
+ self._price = value
325
+ ```
326
+ </example>
327
+
328
+ <example id="4" title="Getter/setter vs plain attribute and @property">
329
+
330
+ ```python
331
+ # WRONG — Java-style getter/setter
332
+ class Temperature:
333
+ def get_celsius(self):
334
+ return self._celsius
335
+
336
+ def set_celsius(self, value):
337
+ if value < -273.15:
338
+ raise ValueError("Temperature below absolute zero")
339
+ self._celsius = value
340
+
341
+ # RIGHT — use @property for validation, direct access otherwise
342
+ class Temperature:
343
+ def __init__(self, celsius: float) -> None:
344
+ self.celsius = celsius # triggers setter on construction
345
+
346
+ @property
347
+ def celsius(self) -> float:
348
+ return self._celsius
349
+
350
+ @celsius.setter
351
+ def celsius(self, value: float) -> None:
352
+ if value < -273.15:
353
+ raise ValueError("Temperature below absolute zero")
354
+ self._celsius = value
355
+ ```
356
+ </example>
357
+
358
+ <example id="5" title="List comprehension vs manual loop">
359
+
360
+ ```python
361
+ # WRONG — manual loop to build list
362
+ result = []
363
+ for order in orders:
364
+ if order['total'] > threshold:
365
+ result.append(order)
366
+
367
+ # RIGHT — list comprehension
368
+ result = [order for order in orders if order['total'] > threshold]
369
+ ```
370
+ </example>
371
+ </examples>
372
+
373
+ ### Concurrency Guidelines
374
+
375
+ - Use `subprocess` for managing child processes (Item 52)
376
+ - Use threads **only** for blocking I/O, never for parallelism (Item 53)
377
+ - Use `threading.Lock` to prevent data races (Item 54)
378
+ - Use `Queue` for coordinating work between threads (Item 55)
379
+ - Use `asyncio` for highly concurrent I/O (Item 60)
380
+ - Never mix blocking calls in async code (Item 62)
381
+
382
+ ### Testing Guidelines
383
+
384
+ - Subclass `TestCase` and use `setUp`/`tearDown` (Item 78)
385
+ - Use `unittest.mock` for complex dependencies (Item 78)
386
+ - Encapsulate dependencies to make code testable (Item 79)
387
+ - Use `pdb.set_trace()` or `breakpoint()` for debugging (Item 80)
388
+ - Use `tracemalloc` for memory debugging (Item 81)
389
+
390
+ ---
391
+
392
+ ## Priority of Items by Impact
393
+
394
+ When time is limited, focus on these highest-impact items first:
395
+
396
+ ### Critical (Correctness & Bugs)
397
+ - Item 20: Raise exceptions instead of returning None
398
+ - Item 24: Use None as default for mutable arguments (never `[]` or `{}`)
399
+ - Item 53: Use threads for I/O only, not parallelism
400
+ - Item 54: Use Lock to prevent data races
401
+ - Item 40: Initialize parent classes with super()
402
+ - Item 65: Use try/except/else/finally correctly; always catch specific exception types
403
+ - Item 73: Use datetime instead of time module for timezone handling
404
+
405
+ ### Important (Maintainability)
406
+ - Item 1: Follow PEP 8 style
407
+ - Item 4: Use f-strings
408
+ - Item 7: Use `for item in seq` or `enumerate`; never `range(len(seq))`
409
+ - Item 19: Never unpack more than 3 variables
410
+ - Item 25: Use keyword-only and positional-only arguments
411
+ - Item 26: Use functools.wraps for decorators
412
+ - Items 37–43: Use `@dataclass` for plain data holders; add `__repr__` to any class without it
413
+ - Item 42: Prefer public attributes over private; use single underscore for internal
414
+ - Item 44: Use plain attributes over getter/setter; use @property for validation
415
+ - Item 66: Use `@contextmanager` for reusable resource management patterns
416
+ - Item 84: Write docstrings for all public APIs
417
+
418
+ ### Suggestions (Polish & Optimization)
419
+ - Item 8: Use zip for parallel iteration
420
+ - Item 10: Use walrus operator to reduce repetition
421
+ - Item 27: Use comprehensions over map/filter and manual loops
422
+ - Item 30: Use generators for large sequences
423
+ - Item 70: Profile before optimizing (cProfile)
424
+
425
+ ---
426
+
427
+ ## Reviewing Already-Good Code
428
+
429
+ When the submitted code is already idiomatic and well-structured, the review must:
430
+
431
+ 1. **Lead with affirmative praise** — say explicitly that the code is idiomatic / well-written.
432
+ 2. **Call out each strong pattern by name and item**, e.g.:
433
+ - `@contextmanager` usage → praise as Item 66
434
+ - Generator functions (`yield`) → praise as Item 30
435
+ - Type annotations on public functions → praise as Item 84
436
+ - Docstrings on public APIs → praise as Item 84
437
+ - `@dataclass` for data holders → praise as Items 37–43
438
+ - List/dict/set comprehensions → praise as Item 27
439
+ 3. **Do not invent problems.** If something is genuinely fine, do not flag it as an issue.
440
+ 4. **Clearly label any suggestion as optional** — use language like "minor suggestion", "stylistic alternative", or "optional improvement", never "issue" or "problem".
441
+ 5. **Keep the tone positive** — the goal is to affirm and explain why the patterns are good, not to find fault.
@@ -0,0 +1,44 @@
1
+ {
2
+ "evals": [
3
+ {
4
+ "id": "eval-01-loop-except-mutable-default",
5
+ "prompt": "Review this Python code:\n\n```python\ndef process_orders(orders, results=[]):\n for i in range(len(orders)):\n order = orders[i]\n try:\n total = order['price'] * order['quantity']\n results.append({'id': order['id'], 'total': total})\n except:\n pass\n\n processed = []\n for item in results:\n processed.append(item['total'])\n return processed\n\n\ndef get_high_value(orders, threshold):\n high = []\n for order in orders:\n if order['total'] > threshold:\n high.append(order)\n return high\n```",
6
+ "expectations": [
7
+ "Flags the mutable default argument `results=[]` as a critical bug (Item 24: Use None and docstrings for dynamic default arguments)",
8
+ "Flags bare `except:` that silently swallows all exceptions including KeyboardInterrupt and SystemExit (Item 65: always catch specific exception types)",
9
+ "Identifies `for i in range(len(orders))` as non-idiomatic; recommends `for order in orders` with enumerate if index is needed (Item 7)",
10
+ "Identifies the manual list-building loop in `process_orders` that should be a list comprehension (Item 27)",
11
+ "Identifies the manual list-building loop in `get_high_value` that should be a list comprehension (Item 27)",
12
+ "Provides a corrected version that uses `None` as default and initializes inside the function",
13
+ "Provides corrected versions using list comprehensions for both loops"
14
+ ]
15
+ },
16
+ {
17
+ "id": "eval-02-class-missing-dataclass",
18
+ "prompt": "Review this Python code:\n\n```python\nclass Product:\n def __init__(self, name, price, category, in_stock=True):\n self.name = name\n self.price = price\n self.category = category\n self.in_stock = in_stock\n\n def get_name(self):\n return self.name\n\n def set_price(self, price):\n if price < 0:\n raise ValueError('Price cannot be negative')\n self.price = price\n\n def is_available(self):\n return self.in_stock == True\n\n\nclass ProductCatalog:\n def __init__(self):\n self.__items = []\n\n def add(self, product):\n self.__items.append(product)\n\n def find_by_category(self, category):\n result = []\n for p in self.__items:\n if p.category == category:\n result.append(p)\n return result\n```",
19
+ "expectations": [
20
+ "Identifies that `Product` is a plain data holder and recommends converting it to a `@dataclass` — eliminates the boilerplate `__init__`, provides automatic `__repr__` and `__eq__`, and makes the data-holder intent explicit (Pythonic class design; Items 37–43: class and interface guidelines)",
21
+ "Flags `get_name()` as a Java-style getter; Pythonic code uses direct attribute access (Item 44: use plain attributes over getter/setter methods)",
22
+ "Flags `set_price()` as a Java-style setter; recommends replacing with `@property` with a setter that includes the validation (Item 44)",
23
+ "Flags `self.in_stock == True` comparison; should be `return self.in_stock` (Item 2: Follow the PEP 8 Style Guide — never compare to True with ==)",
24
+ "Flags `self.__items` name mangling via double underscore; recommends single underscore `_items` for internal use (Item 42: prefer public attributes)",
25
+ "Notes absence of `__repr__` on `Product` making debugging harder; a dataclass provides this automatically",
26
+ "Identifies the manual list-building loop in `find_by_category` as a candidate for a list comprehension (Item 27)",
27
+ "Provides a corrected version using `@dataclass` with `@property` for price validation"
28
+ ]
29
+ },
30
+ {
31
+ "id": "eval-03-idiomatic-python-already-good",
32
+ "prompt": "Review this Python code:\n\n```python\nfrom contextlib import contextmanager\nfrom typing import Generator, Iterator\nimport logging\n\nlogger = logging.getLogger(__name__)\n\n\n@contextmanager\ndef managed_connection(host: str, port: int) -> Generator:\n \"\"\"Open a connection and ensure it is closed on exit.\"\"\"\n conn = _connect(host, port)\n try:\n logger.debug('Opened connection to %s:%d', host, port)\n yield conn\n finally:\n conn.close()\n logger.debug('Closed connection to %s:%d', host, port)\n\n\ndef read_records(filepath: str) -> Iterator[dict]:\n \"\"\"Yield records from a newline-delimited JSON file one at a time.\"\"\"\n with open(filepath, encoding='utf-8') as fh:\n for line in fh:\n line = line.strip()\n if line:\n yield _parse(line)\n\n\ndef process_batch(records: Iterator[dict], batch_size: int = 500) -> Iterator[list]:\n \"\"\"Yield successive fixed-size batches from an iterator.\"\"\"\n batch: list[dict] = []\n for record in records:\n batch.append(record)\n if len(batch) >= batch_size:\n yield batch\n batch = []\n if batch:\n yield batch\n```",
33
+ "expectations": [
34
+ "Recognizes this is already idiomatic, well-structured Python and says so explicitly",
35
+ "Praises the use of `@contextmanager` for resource management (Item 66: use contextlib for reusable try/finally patterns)",
36
+ "Praises the generator function `read_records` for memory-efficient file reading (Item 30: consider generators instead of returning lists)",
37
+ "Praises the generator function `process_batch` for lazy batch production without loading the entire sequence into memory (Item 30)",
38
+ "Praises type annotations and docstrings on all public functions (Item 84: Write docstrings for all public APIs)",
39
+ "Does NOT manufacture issues to appear thorough; any suggestions are explicitly framed as minor optional improvements",
40
+ "May note minor optional suggestions such as using `itertools.islice` for batching, but frames them as stylistic alternatives, not violations"
41
+ ]
42
+ }
43
+ ]
44
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "pass_rate": 0.909,
3
+ "passed": 20,
4
+ "total": 22,
5
+ "baseline_pass_rate": 0.5,
6
+ "baseline_passed": 11,
7
+ "baseline_total": 22,
8
+ "delta": 0.409,
9
+ "model": "default",
10
+ "evals_run": 3,
11
+ "date": "2026-03-29",
12
+ "non_standard_provider": true
13
+ }