agy-superpowers 5.2.1 → 5.2.3

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 (233) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/patches/skills-patches.md +23 -0
  4. package/template/agent/rules/scratch-scripts.md +37 -0
  5. package/template/agent/rules/superpowers.md +6 -50
  6. package/template/agent/skills/brainstorming/SKILL.md +4 -3
  7. package/template/agent/skills/brainstorming/visual-companion.md +2 -3
  8. package/template/agent/skills/finishing-a-development-branch/SKILL.md +11 -16
  9. package/template/agent/skills/subagent-driven-development/SKILL.md +16 -0
  10. package/template/agent/skills/subagent-driven-development/implementer-prompt.md +4 -3
  11. package/template/agent/skills/using-git-worktrees/SKILL.md +3 -2
  12. package/template/agent/skills/using-superpowers/SKILL.md +8 -6
  13. package/template/agent/skills/using-superpowers/references/copilot-tools.md +52 -0
  14. package/template/agent/skills/writing-plans/SKILL.md +5 -3
  15. package/template/agent/skills/writing-skills/SKILL.md +1 -1
  16. package/template/agent/superpowers-version.json +2 -2
  17. package/template/agent/tmp/agent-config-backup.yml +9 -0
  18. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  19. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  20. package/template/agent/skills/api-design/SKILL.md +0 -193
  21. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  22. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  23. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  24. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  25. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  26. package/template/agent/skills/community-manager/SKILL.md +0 -115
  27. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  28. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  29. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  30. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  31. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  32. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  33. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  34. package/template/agent/skills/game-design/SKILL.md +0 -194
  35. package/template/agent/skills/game-developer/SKILL.md +0 -175
  36. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  37. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  38. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  39. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  40. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  41. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  42. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  43. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  44. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  45. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  46. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  47. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  48. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  49. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  50. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  64. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  79. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  80. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  94. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  95. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  105. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  106. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  117. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  118. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  128. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  129. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  143. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  144. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  159. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  160. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  171. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  172. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  183. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  184. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  194. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  195. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  206. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  218. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  228. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  229. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  230. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  231. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  232. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  233. 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