agy-superpowers 5.2.2 → 5.2.4

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 (231) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/rules/CLAUDE.md +80 -0
  4. package/template/agent/rules/code-styles.md +31 -32
  5. package/template/agent/rules/debug-confirmation-policy.md +2 -0
  6. package/template/agent/rules/file-length-policy.md +2 -0
  7. package/template/agent/rules/git-policy.md +7 -0
  8. package/template/agent/rules/language-matching.md +2 -0
  9. package/template/agent/rules/scratch-scripts.md +39 -0
  10. package/template/agent/rules/superpowers.md +8 -51
  11. package/template/agent/skills/executing-plans/SKILL.md +17 -0
  12. package/template/agent/skills/systematic-debugging/SKILL.md +16 -0
  13. package/template/agent/skills/test-driven-development/SKILL.md +16 -0
  14. package/template/agent/skills/verification-before-completion/SKILL.md +22 -0
  15. package/template/agent/skills/writing-plans/SKILL.md +16 -0
  16. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  17. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  18. package/template/agent/skills/api-design/SKILL.md +0 -193
  19. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  20. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  21. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  22. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  23. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  24. package/template/agent/skills/community-manager/SKILL.md +0 -115
  25. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  26. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  27. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  28. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  29. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  30. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  31. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  32. package/template/agent/skills/game-design/SKILL.md +0 -194
  33. package/template/agent/skills/game-developer/SKILL.md +0 -175
  34. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  35. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  36. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  37. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  38. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  39. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  40. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  41. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  42. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  43. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  44. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  45. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  46. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  47. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  48. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  49. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  50. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  64. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  79. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  80. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  94. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  95. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  105. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  106. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  117. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  118. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  128. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  129. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  143. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  144. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  159. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  160. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  171. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  172. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  183. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  184. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  194. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  195. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  206. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  218. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  228. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  229. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  230. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  231. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -1,130 +0,0 @@
1
- # err-result-over-panic
2
-
3
- > Return `Result<T, E>` instead of panicking for recoverable errors
4
-
5
- ## Why It Matters
6
-
7
- Panics unwind the stack and crash the thread (or program). They're unrecoverable from the caller's perspective. `Result<T, E>` gives callers the ability to decide how to handle errors—retry, fallback, propagate, or log. Libraries should almost never panic; applications should minimize panics to truly unrecoverable situations.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- fn parse_config(path: &str) -> Config {
13
- let content = std::fs::read_to_string(path)
14
- .expect("Failed to read config"); // Crashes on missing file
15
-
16
- serde_json::from_str(&content)
17
- .expect("Invalid config format") // Crashes on bad JSON
18
- }
19
-
20
- fn divide(a: i32, b: i32) -> i32 {
21
- if b == 0 {
22
- panic!("Division by zero!"); // Crashes the program
23
- }
24
- a / b
25
- }
26
- ```
27
-
28
- Caller has no chance to recover or provide a fallback.
29
-
30
- ## Good
31
-
32
- ```rust
33
- use thiserror::Error;
34
-
35
- #[derive(Error, Debug)]
36
- enum ConfigError {
37
- #[error("Failed to read config file: {0}")]
38
- Io(#[from] std::io::Error),
39
- #[error("Invalid config format: {0}")]
40
- Parse(#[from] serde_json::Error),
41
- }
42
-
43
- fn parse_config(path: &str) -> Result<Config, ConfigError> {
44
- let content = std::fs::read_to_string(path)?;
45
- let config = serde_json::from_str(&content)?;
46
- Ok(config)
47
- }
48
-
49
- fn divide(a: i32, b: i32) -> Result<i32, &'static str> {
50
- if b == 0 {
51
- return Err("Division by zero");
52
- }
53
- Ok(a / b)
54
- }
55
-
56
- // Caller decides how to handle
57
- match parse_config("app.json") {
58
- Ok(config) => run_app(config),
59
- Err(e) => {
60
- eprintln!("Using default config: {}", e);
61
- run_app(Config::default())
62
- }
63
- }
64
- ```
65
-
66
- ## When Panic IS Appropriate
67
-
68
- ```rust
69
- // 1. Bug in the program (invariant violation)
70
- fn get_cached_value(&self, key: &str) -> &Value {
71
- self.cache.get(key).expect("BUG: key was verified to exist")
72
- }
73
-
74
- // 2. Setup/initialization that can't reasonably fail
75
- fn main() {
76
- let config = Config::load().expect("Failed to load required config");
77
- // Can't run without config, panic is reasonable
78
- }
79
-
80
- // 3. Tests
81
- #[test]
82
- fn test_parse() {
83
- let result = parse("valid input").unwrap(); // unwrap OK in tests
84
- assert_eq!(result, expected);
85
- }
86
-
87
- // 4. Examples and prototypes
88
- fn main() {
89
- // Quick prototype, panic is fine
90
- let data = fetch_data().unwrap();
91
- }
92
- ```
93
-
94
- ## Panic vs Result Decision Guide
95
-
96
- | Situation | Use |
97
- |-----------|-----|
98
- | File not found | `Result` |
99
- | Network error | `Result` |
100
- | Invalid user input | `Result` |
101
- | Parse error | `Result` |
102
- | Index out of bounds (from user data) | `Result` |
103
- | Index out of bounds (internal bug) | Panic |
104
- | Violated internal invariant | Panic |
105
- | Unimplemented code path | Panic (`unimplemented!()`) |
106
- | Impossible state reached | Panic (`unreachable!()`) |
107
-
108
- ## Library vs Application
109
-
110
- ```rust
111
- // Library: NEVER panic on user input
112
- pub fn parse(input: &str) -> Result<Ast, ParseError> {
113
- // Always return Result
114
- }
115
-
116
- // Application: Can panic at top level for critical failures
117
- fn main() {
118
- if let Err(e) = run() {
119
- eprintln!("Fatal error: {}", e);
120
- std::process::exit(1);
121
- }
122
- }
123
- ```
124
-
125
- ## See Also
126
-
127
- - [err-thiserror-lib](./err-thiserror-lib.md) - Define error types for libraries
128
- - [err-anyhow-app](./err-anyhow-app.md) - Ergonomic errors for applications
129
- - [err-no-unwrap-prod](./err-no-unwrap-prod.md) - Avoid unwrap in production code
130
- - [anti-unwrap-abuse](./anti-unwrap-abuse.md) - When unwrap is acceptable
@@ -1,155 +0,0 @@
1
- # err-source-chain
2
-
3
- > Preserve error chains with `#[source]` or `source()` method
4
-
5
- ## Why It Matters
6
-
7
- Errors often have underlying causes. Preserving the error chain (via `source()` method) allows logging frameworks and error reporters to show the full context: "config parse failed → JSON syntax error at line 5 → unexpected token". Without chaining, you lose valuable debugging information.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- #[derive(Debug)]
13
- enum ConfigError {
14
- ParseFailed(String), // Lost the original serde_json::Error
15
- }
16
-
17
- fn load_config(path: &str) -> Result<Config, ConfigError> {
18
- let content = std::fs::read_to_string(path)
19
- .map_err(|e| ConfigError::ParseFailed(e.to_string()))?; // Chain lost!
20
-
21
- serde_json::from_str(&content)
22
- .map_err(|e| ConfigError::ParseFailed(e.to_string()))? // No source
23
- }
24
-
25
- // Error output: "Parse failed: invalid type: ..."
26
- // Missing: which file? what line? what was the parent error?
27
- ```
28
-
29
- ## Good
30
-
31
- ```rust
32
- use thiserror::Error;
33
-
34
- #[derive(Error, Debug)]
35
- enum ConfigError {
36
- #[error("Failed to read config file '{path}'")]
37
- ReadFailed {
38
- path: String,
39
- #[source] // Preserves the error chain
40
- source: std::io::Error,
41
- },
42
-
43
- #[error("Failed to parse config file '{path}'")]
44
- ParseFailed {
45
- path: String,
46
- #[source] // Original parse error preserved
47
- source: serde_json::Error,
48
- },
49
- }
50
-
51
- fn load_config(path: &str) -> Result<Config, ConfigError> {
52
- let content = std::fs::read_to_string(path)
53
- .map_err(|source| ConfigError::ReadFailed {
54
- path: path.to_string(),
55
- source, // Chain preserved
56
- })?;
57
-
58
- serde_json::from_str(&content)
59
- .map_err(|source| ConfigError::ParseFailed {
60
- path: path.to_string(),
61
- source,
62
- })
63
- }
64
- ```
65
-
66
- ## Manual source() Implementation
67
-
68
- ```rust
69
- use std::error::Error;
70
-
71
- #[derive(Debug)]
72
- struct MyError {
73
- message: String,
74
- source: Option<Box<dyn Error + Send + Sync>>,
75
- }
76
-
77
- impl std::fmt::Display for MyError {
78
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79
- write!(f, "{}", self.message)
80
- }
81
- }
82
-
83
- impl Error for MyError {
84
- fn source(&self) -> Option<&(dyn Error + 'static)> {
85
- self.source.as_ref().map(|e| e.as_ref() as &(dyn Error + 'static))
86
- }
87
- }
88
- ```
89
-
90
- ## Walking the Error Chain
91
-
92
- ```rust
93
- fn print_error_chain(error: &dyn std::error::Error) {
94
- eprintln!("Error: {}", error);
95
-
96
- let mut source = error.source();
97
- while let Some(err) = source {
98
- eprintln!("Caused by: {}", err);
99
- source = err.source();
100
- }
101
- }
102
-
103
- // With anyhow, use {:?} for full chain
104
- let result: anyhow::Result<()> = do_something();
105
- if let Err(e) = result {
106
- eprintln!("{:?}", e); // Prints full chain with backtraces
107
- }
108
- ```
109
-
110
- ## anyhow Context
111
-
112
- ```rust
113
- use anyhow::{Context, Result};
114
-
115
- fn load_config(path: &str) -> Result<Config> {
116
- let content = std::fs::read_to_string(path)
117
- .with_context(|| format!("Failed to read '{}'", path))?;
118
-
119
- let config: Config = serde_json::from_str(&content)
120
- .with_context(|| format!("Failed to parse '{}'", path))?;
121
-
122
- Ok(config)
123
- }
124
-
125
- // Output:
126
- // Error: Failed to parse 'config.json'
127
- // Caused by: expected `:` at line 5 column 10
128
- ```
129
-
130
- ## #[from] vs #[source]
131
-
132
- ```rust
133
- use thiserror::Error;
134
-
135
- #[derive(Error, Debug)]
136
- enum MyError {
137
- // #[from] = implements From + sets source
138
- #[error("IO error")]
139
- Io(#[from] std::io::Error),
140
-
141
- // #[source] = only sets source (no From impl)
142
- #[error("Parse error in file '{path}'")]
143
- Parse {
144
- path: String,
145
- #[source]
146
- source: serde_json::Error,
147
- },
148
- }
149
- ```
150
-
151
- ## See Also
152
-
153
- - [err-thiserror-lib](./err-thiserror-lib.md) - thiserror for error definitions
154
- - [err-context-chain](./err-context-chain.md) - Adding context to errors
155
- - [err-from-impl](./err-from-impl.md) - From implementations for ?
@@ -1,171 +0,0 @@
1
- # err-thiserror-lib
2
-
3
- > Use `thiserror` for library error types
4
-
5
- ## Why It Matters
6
-
7
- Libraries should expose typed, matchable errors so users can handle specific error conditions. `thiserror` generates `Error` trait implementations with minimal boilerplate, creating ergonomic error types that are easy to match against.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // String errors - not matchable
13
- fn parse(input: &str) -> Result<Data, String> {
14
- Err("parse error".to_string())
15
- }
16
-
17
- // Box<dyn Error> - not matchable
18
- fn load(path: &Path) -> Result<Data, Box<dyn std::error::Error>> {
19
- Err(Box::new(std::io::Error::new(std::io::ErrorKind::NotFound, "file not found")))
20
- }
21
-
22
- // Manual implementation - verbose
23
- #[derive(Debug)]
24
- enum MyError {
25
- Io(std::io::Error),
26
- Parse(String),
27
- }
28
-
29
- impl std::fmt::Display for MyError {
30
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31
- match self {
32
- MyError::Io(e) => write!(f, "io error: {}", e),
33
- MyError::Parse(s) => write!(f, "parse error: {}", s),
34
- }
35
- }
36
- }
37
-
38
- impl std::error::Error for MyError {
39
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
40
- match self {
41
- MyError::Io(e) => Some(e),
42
- MyError::Parse(_) => None,
43
- }
44
- }
45
- }
46
- ```
47
-
48
- ## Good
49
-
50
- ```rust
51
- use thiserror::Error;
52
-
53
- #[derive(Error, Debug)]
54
- pub enum ParseError {
55
- #[error("invalid syntax at line {line}: {message}")]
56
- Syntax { line: usize, message: String },
57
-
58
- #[error("unexpected end of file")]
59
- UnexpectedEof,
60
-
61
- #[error("invalid utf-8 encoding")]
62
- Utf8(#[from] std::str::Utf8Error),
63
-
64
- #[error("io error reading input")]
65
- Io(#[from] std::io::Error),
66
- }
67
-
68
- // Usage
69
- fn parse(input: &str) -> Result<Ast, ParseError> {
70
- if input.is_empty() {
71
- return Err(ParseError::UnexpectedEof);
72
- }
73
- // ...
74
- }
75
-
76
- // Users can match specific errors
77
- match parse(input) {
78
- Ok(ast) => process(ast),
79
- Err(ParseError::Syntax { line, message }) => {
80
- eprintln!("Syntax error on line {}: {}", line, message);
81
- }
82
- Err(ParseError::UnexpectedEof) => {
83
- eprintln!("File ended unexpectedly");
84
- }
85
- Err(e) => eprintln!("Error: {}", e),
86
- }
87
- ```
88
-
89
- ## Key Attributes
90
-
91
- ```rust
92
- use thiserror::Error;
93
-
94
- #[derive(Error, Debug)]
95
- pub enum MyError {
96
- // Simple message
97
- #[error("operation failed")]
98
- Failed,
99
-
100
- // Interpolated fields
101
- #[error("invalid value: {0}")]
102
- InvalidValue(String),
103
-
104
- // Named fields
105
- #[error("connection to {host}:{port} failed")]
106
- Connection { host: String, port: u16 },
107
-
108
- // Automatic From impl with #[from]
109
- #[error("database error")]
110
- Database(#[from] sqlx::Error),
111
-
112
- // Source without From (manual conversion needed)
113
- #[error("validation failed")]
114
- Validation {
115
- #[source]
116
- cause: ValidationError,
117
- field: String,
118
- },
119
-
120
- // Transparent - delegates Display and source to inner
121
- #[error(transparent)]
122
- Other(#[from] anyhow::Error),
123
- }
124
- ```
125
-
126
- ## Error Chaining
127
-
128
- ```rust
129
- use thiserror::Error;
130
-
131
- #[derive(Error, Debug)]
132
- pub enum ConfigError {
133
- #[error("failed to read config file")]
134
- Read(#[source] std::io::Error),
135
-
136
- #[error("failed to parse config")]
137
- Parse(#[source] toml::de::Error),
138
-
139
- #[error("invalid config value for '{key}'")]
140
- InvalidValue {
141
- key: String,
142
- #[source]
143
- cause: ValueError,
144
- },
145
- }
146
-
147
- // Error chain is preserved
148
- fn load_config(path: &Path) -> Result<Config, ConfigError> {
149
- let content = std::fs::read_to_string(path)
150
- .map_err(ConfigError::Read)?;
151
-
152
- let config: Config = toml::from_str(&content)
153
- .map_err(ConfigError::Parse)?;
154
-
155
- Ok(config)
156
- }
157
- ```
158
-
159
- ## Library vs Application
160
-
161
- | Context | Crate | Why |
162
- |---------|-------|-----|
163
- | Library | `thiserror` | Typed errors users can match |
164
- | Application | `anyhow` | Easy error handling with context |
165
- | Both | `thiserror` for public API, `anyhow` internally | Best of both |
166
-
167
- ## See Also
168
-
169
- - [err-anyhow-app](err-anyhow-app.md) - Use anyhow for applications
170
- - [err-from-impl](err-from-impl.md) - Use #[from] for automatic conversion
171
- - [err-source-chain](err-source-chain.md) - Use #[source] to chain errors
@@ -1,138 +0,0 @@
1
- # lint-cargo-metadata
2
-
3
- > Enable clippy::cargo for published crates
4
-
5
- ## Why It Matters
6
-
7
- The `clippy::cargo` lint group checks Cargo.toml for issues that affect publishing and dependency management. For crates intended for crates.io, these checks help ensure a professional, well-configured package.
8
-
9
- ## Configuration
10
-
11
- ```toml
12
- # Cargo.toml
13
- [lints.clippy]
14
- cargo = "warn"
15
- ```
16
-
17
- Or in code:
18
-
19
- ```rust
20
- #![warn(clippy::cargo)]
21
- ```
22
-
23
- ## What It Catches
24
-
25
- ### Missing Metadata
26
-
27
- ```toml
28
- # WARN: missing package.description
29
- # WARN: missing package.license or package.license-file
30
- # WARN: missing package.repository
31
- [package]
32
- name = "my-crate"
33
- version = "0.1.0"
34
- ```
35
-
36
- ### Dependency Issues
37
-
38
- ```toml
39
- # WARN: feature used but not defined
40
- # WARN: dependency version not specified
41
- [dependencies]
42
- serde = "*" # Bad: any version
43
- tokio = { git = "..." } # WARN for published crates
44
- ```
45
-
46
- ### Feature Issues
47
-
48
- ```toml
49
- # WARN: negative_feature_names
50
- [features]
51
- no-std = [] # Should be: std = [] (opt-out vs opt-in)
52
-
53
- # WARN: redundant_feature_names
54
- [features]
55
- default = ["feature-a"]
56
- feature-a = [] # Feature name matches crate name
57
- ```
58
-
59
- ## Notable Lints
60
-
61
- | Lint | Issue |
62
- |------|-------|
63
- | `cargo_common_metadata` | Missing description/license/repository |
64
- | `multiple_crate_versions` | Same crate at different versions |
65
- | `negative_feature_names` | Features like `no-std` instead of `std` |
66
- | `redundant_feature_names` | Feature same as crate name |
67
- | `wildcard_dependencies` | Using `*` for version |
68
-
69
- ## Complete Cargo.toml
70
-
71
- ```toml
72
- [package]
73
- name = "my-crate"
74
- version = "0.1.0"
75
- edition = "2021"
76
- rust-version = "1.70"
77
-
78
- # Required for cargo lint satisfaction
79
- description = "A short description of what this crate does"
80
- license = "MIT OR Apache-2.0"
81
- repository = "https://github.com/user/my-crate"
82
-
83
- # Recommended
84
- documentation = "https://docs.rs/my-crate"
85
- readme = "README.md"
86
- keywords = ["keyword1", "keyword2"]
87
- categories = ["category-slug"]
88
-
89
- [dependencies]
90
- # Specific versions, not wildcards
91
- serde = "1.0"
92
- tokio = { version = "1.0", features = ["full"] }
93
-
94
- [features]
95
- default = ["std"]
96
- std = [] # Opt-out, not no-std opt-in
97
-
98
- [lints.clippy]
99
- cargo = "warn"
100
- ```
101
-
102
- ## Multiple Crate Versions
103
-
104
- ```
105
- # WARN: multiple versions of `syn` in dependency tree
106
- # syn v1.0.109
107
- # syn v2.0.48
108
- ```
109
-
110
- Fix by updating dependencies or using `[patch]`:
111
-
112
- ```toml
113
- [patch.crates-io]
114
- old-dep = { git = "...", branch = "syn-2" }
115
- ```
116
-
117
- ## When to Disable
118
-
119
- For internal/unpublished crates:
120
-
121
- ```toml
122
- [lints.clippy]
123
- cargo = "allow" # Not publishing, metadata not needed
124
- ```
125
-
126
- Or selectively:
127
-
128
- ```toml
129
- [lints.clippy]
130
- cargo = "warn"
131
- multiple_crate_versions = "allow" # Acceptable in this project
132
- ```
133
-
134
- ## See Also
135
-
136
- - [doc-cargo-metadata](./doc-cargo-metadata.md) - Cargo.toml metadata
137
- - [proj-workspace-deps](./proj-workspace-deps.md) - Workspace dependencies
138
- - [lint-deny-correctness](./lint-deny-correctness.md) - Correctness lints
@@ -1,107 +0,0 @@
1
- # lint-deny-correctness
2
-
3
- > `#![deny(clippy::correctness)]`
4
-
5
- ## Why It Matters
6
-
7
- Clippy's correctness lints catch code that is outright wrong - logic errors, undefined behavior, or code that doesn't do what you think. These should always be errors, not warnings.
8
-
9
- ## Setup
10
-
11
- ```rust
12
- // At the top of lib.rs or main.rs
13
- #![deny(clippy::correctness)]
14
-
15
- // Or in Cargo.toml for workspace-wide
16
- [lints.clippy]
17
- correctness = "deny"
18
- ```
19
-
20
- ## What It Catches
21
-
22
- ```rust
23
- // Infinite loop (iter::repeat without take)
24
- for x in std::iter::repeat(1) { // ERROR: infinite iterator
25
- println!("{}", x);
26
- }
27
-
28
- // Comparison to NaN (always false)
29
- if x == f64::NAN { // ERROR: NaN != NaN always
30
- // This never executes
31
- }
32
-
33
- // Use after free patterns
34
- let r;
35
- {
36
- let x = 5;
37
- r = &x; // ERROR: x dropped here
38
- }
39
- println!("{}", r);
40
-
41
- // Wrong equality check
42
- if x = 5 { // ERROR: assignment in condition (should be ==)
43
- }
44
-
45
- // Useless comparisons
46
- if x >= 0 && x < 0 { // ERROR: impossible condition
47
- }
48
- ```
49
-
50
- ## Important Correctness Lints
51
-
52
- ```rust
53
- // approx_constant - using imprecise PI, E values
54
- let pi = 3.14; // Use std::f64::consts::PI
55
-
56
- // invalid_regex - regex that won't compile
57
- let re = Regex::new("["); // Invalid regex
58
-
59
- // iter_next_loop - using .next() in for loop incorrectly
60
- for x in iter.next() { // Should be: for x in iter
61
-
62
- // never_loop - loop that never actually loops
63
- loop {
64
- break; // Always breaks immediately
65
- }
66
-
67
- // nonsensical_open_options - impossible file options
68
- File::options().read(false).write(false).open("f");
69
-
70
- // unit_cmp - comparing unit type ()
71
- if foo() == bar() { } // Both return (), always true
72
- ```
73
-
74
- ## Full Recommended Lints
75
-
76
- ```rust
77
- #![deny(clippy::correctness)]
78
- #![warn(clippy::suspicious)]
79
- #![warn(clippy::style)]
80
- #![warn(clippy::complexity)]
81
- #![warn(clippy::perf)]
82
-
83
- // For published crates
84
- #![warn(missing_docs)]
85
- #![warn(clippy::cargo)]
86
- ```
87
-
88
- ## Running Clippy
89
-
90
- ```bash
91
- # Basic check
92
- cargo clippy
93
-
94
- # With all warnings as errors
95
- cargo clippy -- -D warnings
96
-
97
- # Check specific lint category
98
- cargo clippy -- -W clippy::correctness
99
-
100
- # In CI (fail on warnings)
101
- cargo clippy -- -D warnings -D clippy::correctness
102
- ```
103
-
104
- ## See Also
105
-
106
- - [lint-warn-suspicious](lint-warn-suspicious.md) - Warn on suspicious code
107
- - [lint-warn-perf](lint-warn-perf.md) - Warn on performance issues