devflow-kit 1.1.0 → 1.2.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 (107) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +23 -6
  3. package/dist/plugins.js +67 -3
  4. package/package.json +2 -1
  5. package/plugins/devflow-accessibility/.claude-plugin/plugin.json +15 -0
  6. package/plugins/devflow-ambient/.claude-plugin/plugin.json +1 -1
  7. package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +1 -1
  8. package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +4 -0
  9. package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
  10. package/plugins/devflow-code-review/.claude-plugin/plugin.json +1 -4
  11. package/plugins/devflow-code-review/agents/reviewer.md +8 -0
  12. package/plugins/devflow-code-review/commands/code-review-teams.md +11 -1
  13. package/plugins/devflow-code-review/commands/code-review.md +12 -2
  14. package/plugins/devflow-core-skills/.claude-plugin/plugin.json +2 -6
  15. package/plugins/devflow-debug/.claude-plugin/plugin.json +1 -1
  16. package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +15 -0
  17. package/plugins/devflow-go/.claude-plugin/plugin.json +15 -0
  18. package/plugins/devflow-go/skills/go/SKILL.md +187 -0
  19. package/plugins/devflow-go/skills/go/references/concurrency.md +312 -0
  20. package/plugins/devflow-go/skills/go/references/detection.md +129 -0
  21. package/plugins/devflow-go/skills/go/references/patterns.md +232 -0
  22. package/plugins/devflow-go/skills/go/references/violations.md +205 -0
  23. package/plugins/devflow-implement/.claude-plugin/plugin.json +1 -3
  24. package/plugins/devflow-implement/agents/coder.md +11 -6
  25. package/plugins/devflow-java/.claude-plugin/plugin.json +15 -0
  26. package/plugins/devflow-java/skills/java/SKILL.md +183 -0
  27. package/plugins/devflow-java/skills/java/references/detection.md +120 -0
  28. package/plugins/devflow-java/skills/java/references/modern-java.md +270 -0
  29. package/plugins/devflow-java/skills/java/references/patterns.md +235 -0
  30. package/plugins/devflow-java/skills/java/references/violations.md +213 -0
  31. package/plugins/devflow-python/.claude-plugin/plugin.json +15 -0
  32. package/plugins/devflow-python/skills/python/SKILL.md +188 -0
  33. package/plugins/devflow-python/skills/python/references/async.md +220 -0
  34. package/plugins/devflow-python/skills/python/references/detection.md +128 -0
  35. package/plugins/devflow-python/skills/python/references/patterns.md +226 -0
  36. package/plugins/devflow-python/skills/python/references/violations.md +204 -0
  37. package/plugins/devflow-react/.claude-plugin/plugin.json +15 -0
  38. package/plugins/{devflow-core-skills → devflow-react}/skills/react/SKILL.md +1 -1
  39. package/plugins/{devflow-core-skills → devflow-react}/skills/react/references/patterns.md +3 -3
  40. package/plugins/devflow-resolve/.claude-plugin/plugin.json +1 -1
  41. package/plugins/devflow-rust/.claude-plugin/plugin.json +15 -0
  42. package/plugins/devflow-rust/skills/rust/SKILL.md +193 -0
  43. package/plugins/devflow-rust/skills/rust/references/detection.md +131 -0
  44. package/plugins/devflow-rust/skills/rust/references/ownership.md +242 -0
  45. package/plugins/devflow-rust/skills/rust/references/patterns.md +210 -0
  46. package/plugins/devflow-rust/skills/rust/references/violations.md +191 -0
  47. package/plugins/devflow-self-review/.claude-plugin/plugin.json +1 -1
  48. package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
  49. package/plugins/devflow-typescript/.claude-plugin/plugin.json +15 -0
  50. package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md +3 -3
  51. package/shared/agents/coder.md +11 -6
  52. package/shared/agents/reviewer.md +8 -0
  53. package/shared/skills/ambient-router/SKILL.md +1 -1
  54. package/shared/skills/ambient-router/references/skill-catalog.md +4 -0
  55. package/shared/skills/go/SKILL.md +187 -0
  56. package/shared/skills/go/references/concurrency.md +312 -0
  57. package/shared/skills/go/references/detection.md +129 -0
  58. package/shared/skills/go/references/patterns.md +232 -0
  59. package/shared/skills/go/references/violations.md +205 -0
  60. package/shared/skills/java/SKILL.md +183 -0
  61. package/shared/skills/java/references/detection.md +120 -0
  62. package/shared/skills/java/references/modern-java.md +270 -0
  63. package/shared/skills/java/references/patterns.md +235 -0
  64. package/shared/skills/java/references/violations.md +213 -0
  65. package/shared/skills/python/SKILL.md +188 -0
  66. package/shared/skills/python/references/async.md +220 -0
  67. package/shared/skills/python/references/detection.md +128 -0
  68. package/shared/skills/python/references/patterns.md +226 -0
  69. package/shared/skills/python/references/violations.md +204 -0
  70. package/shared/skills/react/SKILL.md +1 -1
  71. package/shared/skills/react/references/patterns.md +3 -3
  72. package/shared/skills/rust/SKILL.md +193 -0
  73. package/shared/skills/rust/references/detection.md +131 -0
  74. package/shared/skills/rust/references/ownership.md +242 -0
  75. package/shared/skills/rust/references/patterns.md +210 -0
  76. package/shared/skills/rust/references/violations.md +191 -0
  77. package/shared/skills/typescript/references/patterns.md +3 -3
  78. package/plugins/devflow-code-review/skills/react/SKILL.md +0 -276
  79. package/plugins/devflow-code-review/skills/react/references/patterns.md +0 -1331
  80. package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +0 -229
  81. package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +0 -171
  82. package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +0 -670
  83. package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +0 -419
  84. package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +0 -254
  85. package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +0 -184
  86. package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +0 -511
  87. package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +0 -453
  88. package/plugins/devflow-core-skills/skills/react/references/violations.md +0 -565
  89. package/plugins/devflow-implement/skills/accessibility/SKILL.md +0 -229
  90. package/plugins/devflow-implement/skills/accessibility/references/detection.md +0 -171
  91. package/plugins/devflow-implement/skills/accessibility/references/patterns.md +0 -670
  92. package/plugins/devflow-implement/skills/accessibility/references/violations.md +0 -419
  93. package/plugins/devflow-implement/skills/frontend-design/SKILL.md +0 -254
  94. package/plugins/devflow-implement/skills/frontend-design/references/detection.md +0 -184
  95. package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +0 -511
  96. package/plugins/devflow-implement/skills/frontend-design/references/violations.md +0 -453
  97. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/SKILL.md +0 -0
  98. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/detection.md +0 -0
  99. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/patterns.md +0 -0
  100. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/violations.md +0 -0
  101. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/SKILL.md +0 -0
  102. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/detection.md +0 -0
  103. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/patterns.md +0 -0
  104. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/violations.md +0 -0
  105. /package/plugins/{devflow-code-review → devflow-react}/skills/react/references/violations.md +0 -0
  106. /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/SKILL.md +0 -0
  107. /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/violations.md +0 -0
@@ -0,0 +1,226 @@
1
+ # Python Correct Patterns
2
+
3
+ Extended correct patterns for Python development. Reference from main SKILL.md.
4
+
5
+ ## Dependency Injection
6
+
7
+ ### Constructor Injection
8
+
9
+ ```python
10
+ from typing import Protocol
11
+
12
+ class EmailSender(Protocol):
13
+ def send(self, to: str, subject: str, body: str) -> None: ...
14
+
15
+ class UserService:
16
+ def __init__(self, repo: UserRepository, emailer: EmailSender) -> None:
17
+ self._repo = repo
18
+ self._emailer = emailer
19
+
20
+ def create_user(self, request: CreateUserRequest) -> User:
21
+ user = User(name=request.name, email=request.email)
22
+ saved = self._repo.save(user)
23
+ self._emailer.send(user.email, "Welcome", f"Hello {user.name}")
24
+ return saved
25
+
26
+ # Easy to test — inject fakes
27
+ service = UserService(repo=FakeUserRepo(), emailer=FakeEmailSender())
28
+ ```
29
+
30
+ ### Factory Functions
31
+
32
+ ```python
33
+ def create_app(config: AppConfig) -> Flask:
34
+ app = Flask(__name__)
35
+ db = Database(config.database_url)
36
+ cache = RedisCache(config.redis_url)
37
+ user_service = UserService(repo=SqlUserRepo(db), emailer=SmtpSender(config.smtp))
38
+ register_routes(app, user_service)
39
+ return app
40
+ ```
41
+
42
+ ## Decorator Patterns
43
+
44
+ ### Retry Decorator
45
+
46
+ ```python
47
+ import functools
48
+ import time
49
+ from typing import TypeVar, Callable, ParamSpec
50
+
51
+ P = ParamSpec("P")
52
+ R = TypeVar("R")
53
+
54
+ def retry(
55
+ max_attempts: int = 3,
56
+ delay: float = 1.0,
57
+ exceptions: tuple[type[Exception], ...] = (Exception,),
58
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
59
+ def decorator(func: Callable[P, R]) -> Callable[P, R]:
60
+ @functools.wraps(func)
61
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
62
+ last_error: Exception | None = None
63
+ for attempt in range(max_attempts):
64
+ try:
65
+ return func(*args, **kwargs)
66
+ except exceptions as e:
67
+ last_error = e
68
+ if attempt < max_attempts - 1:
69
+ time.sleep(delay * (2 ** attempt))
70
+ raise last_error # type: ignore[misc]
71
+ return wrapper
72
+ return decorator
73
+
74
+ @retry(max_attempts=3, delay=0.5, exceptions=(ConnectionError, TimeoutError))
75
+ def fetch_data(url: str) -> dict[str, Any]:
76
+ ...
77
+ ```
78
+
79
+ ### Validation Decorator
80
+
81
+ ```python
82
+ def validate_input(schema: type[BaseModel]):
83
+ def decorator(func: Callable[P, R]) -> Callable[P, R]:
84
+ @functools.wraps(func)
85
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
86
+ # Validate first positional arg after self/cls
87
+ data = args[1] if len(args) > 1 else args[0]
88
+ schema.model_validate(data)
89
+ return func(*args, **kwargs)
90
+ return wrapper
91
+ return decorator
92
+ ```
93
+
94
+ ## Context Manager Patterns
95
+
96
+ ### Database Transaction
97
+
98
+ ```python
99
+ from contextlib import contextmanager
100
+ from typing import Generator
101
+
102
+ @contextmanager
103
+ def transaction(session: Session) -> Generator[Session, None, None]:
104
+ try:
105
+ yield session
106
+ session.commit()
107
+ except Exception:
108
+ session.rollback()
109
+ raise
110
+ finally:
111
+ session.close()
112
+
113
+ # Usage
114
+ with transaction(db.session()) as session:
115
+ session.add(user)
116
+ session.add(audit_log)
117
+ ```
118
+
119
+ ### Temporary Directory
120
+
121
+ ```python
122
+ from contextlib import contextmanager
123
+ from pathlib import Path
124
+ import tempfile
125
+ import shutil
126
+
127
+ @contextmanager
128
+ def temp_workspace() -> Generator[Path, None, None]:
129
+ path = Path(tempfile.mkdtemp())
130
+ try:
131
+ yield path
132
+ finally:
133
+ shutil.rmtree(path, ignore_errors=True)
134
+ ```
135
+
136
+ ## Pytest Fixture Patterns
137
+
138
+ ### Service Fixtures with DI
139
+
140
+ ```python
141
+ import pytest
142
+
143
+ @pytest.fixture
144
+ def fake_repo() -> FakeUserRepo:
145
+ return FakeUserRepo()
146
+
147
+ @pytest.fixture
148
+ def fake_emailer() -> FakeEmailSender:
149
+ return FakeEmailSender()
150
+
151
+ @pytest.fixture
152
+ def user_service(fake_repo: FakeUserRepo, fake_emailer: FakeEmailSender) -> UserService:
153
+ return UserService(repo=fake_repo, emailer=fake_emailer)
154
+
155
+ def test_create_user_sends_welcome_email(
156
+ user_service: UserService,
157
+ fake_emailer: FakeEmailSender,
158
+ ) -> None:
159
+ user_service.create_user(CreateUserRequest(name="Alice", email="a@b.com"))
160
+ assert fake_emailer.sent_count == 1
161
+ assert fake_emailer.last_to == "a@b.com"
162
+ ```
163
+
164
+ ### Parametrized Tests
165
+
166
+ ```python
167
+ @pytest.mark.parametrize(
168
+ "input_age, expected_valid",
169
+ [
170
+ (25, True),
171
+ (0, True),
172
+ (150, True),
173
+ (-1, False),
174
+ (151, False),
175
+ (None, False),
176
+ ],
177
+ )
178
+ def test_age_validation(input_age: int | None, expected_valid: bool) -> None:
179
+ result = validate_age(input_age)
180
+ assert result.is_valid == expected_valid
181
+ ```
182
+
183
+ ## Structured Logging
184
+
185
+ ```python
186
+ import structlog
187
+
188
+ logger = structlog.get_logger()
189
+
190
+ def process_order(order: Order) -> OrderResult:
191
+ log = logger.bind(order_id=order.id, user_id=order.user_id)
192
+ log.info("processing_order", item_count=len(order.items))
193
+
194
+ try:
195
+ result = fulfill(order)
196
+ log.info("order_fulfilled", total=result.total)
197
+ return result
198
+ except InsufficientStockError as e:
199
+ log.warning("order_failed_stock", item_id=e.item_id)
200
+ raise
201
+ ```
202
+
203
+ ## Enum Patterns
204
+
205
+ ```python
206
+ from enum import Enum, auto
207
+
208
+ class OrderStatus(Enum):
209
+ PENDING = auto()
210
+ PROCESSING = auto()
211
+ SHIPPED = auto()
212
+ DELIVERED = auto()
213
+ CANCELLED = auto()
214
+
215
+ @property
216
+ def is_terminal(self) -> bool:
217
+ return self in (OrderStatus.DELIVERED, OrderStatus.CANCELLED)
218
+
219
+ def can_transition_to(self, target: "OrderStatus") -> bool:
220
+ valid = {
221
+ OrderStatus.PENDING: {OrderStatus.PROCESSING, OrderStatus.CANCELLED},
222
+ OrderStatus.PROCESSING: {OrderStatus.SHIPPED, OrderStatus.CANCELLED},
223
+ OrderStatus.SHIPPED: {OrderStatus.DELIVERED},
224
+ }
225
+ return target in valid.get(self, set())
226
+ ```
@@ -0,0 +1,204 @@
1
+ # Python Violation Examples
2
+
3
+ Extended violation patterns for Python reviews. Reference from main SKILL.md.
4
+
5
+ ## Type Safety Violations
6
+
7
+ ### Missing Type Hints
8
+
9
+ ```python
10
+ # VIOLATION: No type annotations
11
+ def process(data, config):
12
+ result = transform(data)
13
+ return result
14
+
15
+ # VIOLATION: Partial annotations (inconsistent)
16
+ def save(user: User, db): # db missing type
17
+ return db.insert(user)
18
+
19
+ # VIOLATION: Missing return type
20
+ def calculate_total(items: list[Item]):
21
+ return sum(item.price for item in items)
22
+ ```
23
+
24
+ ### Bare Except Clauses
25
+
26
+ ```python
27
+ # VIOLATION: Catches everything including SystemExit and KeyboardInterrupt
28
+ try:
29
+ process_data()
30
+ except:
31
+ pass
32
+
33
+ # VIOLATION: Catches too broadly and silences
34
+ try:
35
+ user = fetch_user(user_id)
36
+ except Exception:
37
+ user = None # Hides real errors (network, auth, parsing)
38
+
39
+ # VIOLATION: Bare except with logging but no re-raise
40
+ try:
41
+ critical_operation()
42
+ except:
43
+ logger.error("Something failed")
44
+ # Swallows the error — caller never knows
45
+ ```
46
+
47
+ ## Data Modeling Violations
48
+
49
+ ### Raw Dicts Instead of Dataclasses
50
+
51
+ ```python
52
+ # VIOLATION: Untyped dict — no IDE support, no validation
53
+ user = {
54
+ "name": "Alice",
55
+ "email": "alice@example.com",
56
+ "age": 30,
57
+ }
58
+
59
+ # VIOLATION: Accessing dict keys without safety
60
+ def get_display_name(user: dict) -> str:
61
+ return f"{user['first_name']} {user['last_name']}" # KeyError risk
62
+
63
+ # VIOLATION: Nested untyped dicts
64
+ config = {
65
+ "database": {
66
+ "host": "localhost",
67
+ "port": 5432,
68
+ },
69
+ "cache": {
70
+ "ttl": 300,
71
+ },
72
+ }
73
+ ```
74
+
75
+ ### Mutable Default Arguments
76
+
77
+ ```python
78
+ # VIOLATION: Mutable default shared across calls
79
+ def add_item(item: str, items: list[str] = []) -> list[str]:
80
+ items.append(item)
81
+ return items
82
+
83
+ # VIOLATION: Dict default mutated in place
84
+ def register(name: str, registry: dict[str, bool] = {}) -> None:
85
+ registry[name] = True
86
+
87
+ # VIOLATION: Set default
88
+ def collect(value: int, seen: set[int] = set()) -> set[int]:
89
+ seen.add(value)
90
+ return seen
91
+ ```
92
+
93
+ ## String Formatting Violations
94
+
95
+ ### Percent Formatting
96
+
97
+ ```python
98
+ # VIOLATION: Old-style % formatting
99
+ message = "Hello %s, you have %d messages" % (name, count)
100
+
101
+ # VIOLATION: % formatting with dict — hard to read, error-prone
102
+ log = "%(timestamp)s - %(level)s - %(message)s" % log_data
103
+ ```
104
+
105
+ ### String Concatenation in Loops
106
+
107
+ ```python
108
+ # VIOLATION: O(n^2) string building
109
+ result = ""
110
+ for line in lines:
111
+ result += line + "\n"
112
+
113
+ # CORRECT: Use join
114
+ result = "\n".join(lines)
115
+ ```
116
+
117
+ ## Global State Violations
118
+
119
+ ### Module-Level Mutable State
120
+
121
+ ```python
122
+ # VIOLATION: Global mutable state
123
+ _cache = {}
124
+ _connections = []
125
+
126
+ def get_cached(key: str) -> Any:
127
+ return _cache.get(key)
128
+
129
+ def add_connection(conn: Connection) -> None:
130
+ _connections.append(conn)
131
+
132
+ # VIOLATION: Global variable modified by functions
133
+ current_user = None
134
+
135
+ def login(username: str) -> None:
136
+ global current_user
137
+ current_user = authenticate(username)
138
+ ```
139
+
140
+ ### Singleton via Module Import
141
+
142
+ ```python
143
+ # VIOLATION: Hard-to-test singleton
144
+ # db.py
145
+ connection = create_connection(os.environ["DATABASE_URL"])
146
+
147
+ # service.py
148
+ from db import connection # Cannot mock or swap for tests
149
+ ```
150
+
151
+ ## Import Violations
152
+
153
+ ### Wildcard Imports
154
+
155
+ ```python
156
+ # VIOLATION: Pollutes namespace, hides dependencies
157
+ from os.path import *
158
+ from utils import *
159
+
160
+ # VIOLATION: Star import in __init__.py
161
+ # mypackage/__init__.py
162
+ from .models import *
163
+ from .services import *
164
+ ```
165
+
166
+ ### Circular Imports
167
+
168
+ ```python
169
+ # VIOLATION: Circular dependency
170
+ # models.py
171
+ from services import UserService # services imports models too
172
+
173
+ # services.py
174
+ from models import User # Circular!
175
+ ```
176
+
177
+ ## Testing Violations
178
+
179
+ ### Assert in Production Code
180
+
181
+ ```python
182
+ # VIOLATION: assert is stripped with -O flag
183
+ def withdraw(account: Account, amount: float) -> None:
184
+ assert amount > 0, "Amount must be positive" # Disabled in production!
185
+ assert account.balance >= amount, "Insufficient funds"
186
+ account.balance -= amount
187
+ ```
188
+
189
+ ### No pytest Fixtures
190
+
191
+ ```python
192
+ # VIOLATION: Repeated setup in every test
193
+ def test_create_user():
194
+ db = Database(":memory:")
195
+ db.create_tables()
196
+ service = UserService(db)
197
+ # ... test logic
198
+
199
+ def test_update_user():
200
+ db = Database(":memory:") # Duplicated setup
201
+ db.create_tables()
202
+ service = UserService(db)
203
+ # ... test logic
204
+ ```
@@ -95,7 +95,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
95
95
  const [user, setUser] = useState<User | null>(null);
96
96
  const login = async (creds: Credentials) => setUser(await authApi.login(creds));
97
97
  const logout = () => { authApi.logout(); setUser(null); };
98
- return <AuthContext.Provider value={{ user, login, logout }}>{children}</AuthContext.Provider>;
98
+ return <AuthContext value={{ user, login, logout }}>{children}</AuthContext>;
99
99
  }
100
100
 
101
101
  export function useAuth() {
@@ -429,9 +429,9 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
429
429
  };
430
430
 
431
431
  return (
432
- <AuthContext.Provider value={{ user, login, logout, isLoading }}>
432
+ <AuthContext value={{ user, login, logout, isLoading }}>
433
433
  {children}
434
- </AuthContext.Provider>
434
+ </AuthContext>
435
435
  );
436
436
  }
437
437
 
@@ -590,7 +590,7 @@ function SearchInput() {
590
590
  ```tsx
591
591
  // CORRECT: Track previous value for comparisons
592
592
  function usePrevious<T>(value: T): T | undefined {
593
- const ref = useRef<T>();
593
+ const ref = useRef<T | undefined>(undefined);
594
594
 
595
595
  useEffect(() => {
596
596
  ref.current = value;
@@ -0,0 +1,193 @@
1
+ ---
2
+ name: rust
3
+ description: This skill should be used when the user works with Rust files (.rs), asks about "ownership", "borrowing", "lifetimes", "Result/Option", "traits", or discusses memory safety and type-driven design. Provides patterns for ownership, error handling, type system usage, and safe concurrency.
4
+ user-invocable: false
5
+ allowed-tools: Read, Grep, Glob
6
+ activation:
7
+ file-patterns:
8
+ - "**/*.rs"
9
+ exclude:
10
+ - "**/target/**"
11
+ ---
12
+
13
+ # Rust Patterns
14
+
15
+ Reference for Rust-specific patterns, ownership model, and type-driven design.
16
+
17
+ ## Iron Law
18
+
19
+ > **MAKE ILLEGAL STATES UNREPRESENTABLE**
20
+ >
21
+ > Encode invariants in the type system. If a function can fail, return `Result`. If a value
22
+ > might be absent, return `Option`. If a state transition is invalid, make it uncompilable.
23
+ > Runtime checks are a fallback, not a strategy.
24
+
25
+ ## When This Skill Activates
26
+
27
+ - Working with Rust codebases
28
+ - Designing type-safe APIs
29
+ - Managing ownership and borrowing
30
+ - Implementing error handling
31
+ - Writing concurrent code
32
+
33
+ ---
34
+
35
+ ## Ownership & Borrowing
36
+
37
+ ### Prefer Borrowing Over Cloning
38
+
39
+ ```rust
40
+ // BAD: fn process(data: String) — takes ownership unnecessarily
41
+ // GOOD: fn process(data: &str) — borrows, caller keeps ownership
42
+
43
+ fn process(data: &str) -> usize {
44
+ data.len()
45
+ }
46
+ ```
47
+
48
+ ### Lifetime Annotations When Needed
49
+
50
+ ```rust
51
+ // Return reference tied to input lifetime
52
+ fn first_word(s: &str) -> &str {
53
+ s.split_whitespace().next().unwrap_or("")
54
+ }
55
+
56
+ // Explicit when compiler can't infer
57
+ struct Excerpt<'a> {
58
+ text: &'a str,
59
+ }
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Error Handling
65
+
66
+ ### Use Result and the ? Operator
67
+
68
+ ```rust
69
+ use std::fs;
70
+ use std::io;
71
+
72
+ fn read_config(path: &str) -> Result<Config, AppError> {
73
+ let content = fs::read_to_string(path)
74
+ .map_err(|e| AppError::Io { path: path.into(), source: e })?;
75
+ let config: Config = toml::from_str(&content)
76
+ .map_err(|e| AppError::Parse { source: e })?;
77
+ Ok(config)
78
+ }
79
+ ```
80
+
81
+ ### Custom Error Types with thiserror
82
+
83
+ ```rust
84
+ use thiserror::Error;
85
+
86
+ #[derive(Error, Debug)]
87
+ pub enum AppError {
88
+ #[error("IO error reading {path}")]
89
+ Io { path: String, #[source] source: io::Error },
90
+ #[error("parse error")]
91
+ Parse { #[from] source: toml::de::Error },
92
+ #[error("{entity} with id {id} not found")]
93
+ NotFound { entity: String, id: String },
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Type System
100
+
101
+ ### Newtype Pattern
102
+
103
+ ```rust
104
+ // Prevent mixing up IDs
105
+ struct UserId(String);
106
+ struct OrderId(String);
107
+
108
+ fn get_order(user_id: &UserId, order_id: &OrderId) -> Result<Order, AppError> {
109
+ // Can't accidentally swap parameters
110
+ todo!()
111
+ }
112
+ ```
113
+
114
+ ### Enums for State Machines
115
+
116
+ ```rust
117
+ enum Connection {
118
+ Disconnected,
119
+ Connecting { attempt: u32 },
120
+ Connected { session: Session },
121
+ }
122
+
123
+ // Each state carries only its relevant data
124
+ // Invalid transitions are uncompilable
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Patterns
130
+
131
+ ### Builder Pattern
132
+
133
+ ```rust
134
+ pub struct ServerBuilder {
135
+ port: u16,
136
+ host: String,
137
+ }
138
+
139
+ impl ServerBuilder {
140
+ pub fn new() -> Self { Self { port: 8080, host: "localhost".into() } }
141
+ pub fn port(mut self, port: u16) -> Self { self.port = port; self }
142
+ pub fn host(mut self, host: impl Into<String>) -> Self { self.host = host.into(); self }
143
+ pub fn build(self) -> Server { Server { port: self.port, host: self.host } }
144
+ }
145
+ ```
146
+
147
+ ### Iterator Chains Over Loops
148
+
149
+ ```rust
150
+ // BAD: manual loop with push
151
+ // GOOD:
152
+ let active_names: Vec<&str> = users.iter()
153
+ .filter(|u| u.is_active)
154
+ .map(|u| u.name.as_str())
155
+ .collect();
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Anti-Patterns
161
+
162
+ | Pattern | Bad | Good |
163
+ |---------|-----|------|
164
+ | Unwrap in library | `.unwrap()` | `?` operator or `.ok_or()` |
165
+ | Clone to satisfy borrow checker | `.clone()` everywhere | Restructure ownership |
166
+ | String for everything | `HashMap<String, String>` | Typed structs and enums |
167
+ | Ignoring Result | `let _ = write(...)` | Handle or propagate error |
168
+ | Mutex<Vec> for message passing | Shared mutable state | Channels (`mpsc`) |
169
+
170
+ ---
171
+
172
+ ## Extended References
173
+
174
+ For additional patterns and examples:
175
+ - `references/violations.md` - Common Rust violations
176
+ - `references/patterns.md` - Extended Rust patterns
177
+ - `references/detection.md` - Detection patterns for Rust issues
178
+ - `references/ownership.md` - Advanced ownership and lifetime patterns
179
+
180
+ ---
181
+
182
+ ## Checklist
183
+
184
+ - [ ] No `.unwrap()` in library/application code (ok in tests)
185
+ - [ ] Custom error types with `thiserror`
186
+ - [ ] `?` operator for error propagation
187
+ - [ ] Borrow instead of clone where possible
188
+ - [ ] Newtype pattern for type-safe IDs
189
+ - [ ] Enums for state machines
190
+ - [ ] Iterator chains over manual loops
191
+ - [ ] `#[must_use]` on Result-returning functions
192
+ - [ ] No `unsafe` without safety comment
193
+ - [ ] Clippy clean (`cargo clippy -- -D warnings`)