@caddis/cli 0.0.0 → 0.1.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 (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -1
  3. package/bundles/antigravity-plugin/agents/code-reviewer.md +47 -0
  4. package/bundles/antigravity-plugin/agents/preflight.md +53 -0
  5. package/bundles/antigravity-plugin/guard_agy.py +338 -0
  6. package/bundles/antigravity-plugin/hooks.json +36 -0
  7. package/bundles/antigravity-plugin/mcp_config.json +8 -0
  8. package/bundles/antigravity-plugin/mcp_ping_server.py +55 -0
  9. package/bundles/antigravity-plugin/plugin.json +5 -0
  10. package/bundles/antigravity-plugin/session_end_agy.py +57 -0
  11. package/bundles/antigravity-plugin/skills/_registry.md +115 -0
  12. package/bundles/antigravity-plugin/skills/add-rules/SKILL.md +45 -0
  13. package/bundles/antigravity-plugin/skills/api-design/SKILL.md +249 -0
  14. package/bundles/antigravity-plugin/skills/backend-development/SKILL.md +305 -0
  15. package/bundles/antigravity-plugin/skills/best-practices/SKILL.md +500 -0
  16. package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md +263 -0
  17. package/bundles/antigravity-plugin/skills/best-practices/agents/codebase-context-builder.md +326 -0
  18. package/bundles/antigravity-plugin/skills/best-practices/agents/task-intent-analyzer.md +245 -0
  19. package/bundles/antigravity-plugin/skills/best-practices/references/anti-patterns.md +571 -0
  20. package/bundles/antigravity-plugin/skills/best-practices/references/before-after-examples.md +1114 -0
  21. package/bundles/antigravity-plugin/skills/best-practices/references/best-practices-guide.md +513 -0
  22. package/bundles/antigravity-plugin/skills/best-practices/references/common-workflows.md +692 -0
  23. package/bundles/antigravity-plugin/skills/best-practices/references/prompt-patterns.md +547 -0
  24. package/bundles/antigravity-plugin/skills/brainstorming/SKILL.md +57 -0
  25. package/bundles/antigravity-plugin/skills/ci-cd-pipeline/SKILL.md +315 -0
  26. package/bundles/antigravity-plugin/skills/code-documentation/SKILL.md +271 -0
  27. package/bundles/antigravity-plugin/skills/code-review/SKILL.md +122 -0
  28. package/bundles/antigravity-plugin/skills/codebase-audit/SKILL.md +204 -0
  29. package/bundles/antigravity-plugin/skills/context-curator/SKILL.md +157 -0
  30. package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +40 -0
  31. package/bundles/antigravity-plugin/skills/css-architecture/SKILL.md +305 -0
  32. package/bundles/antigravity-plugin/skills/css-architecture/references/RESPONSIVE-DESIGN.md +604 -0
  33. package/bundles/antigravity-plugin/skills/database-design/SKILL.md +177 -0
  34. package/bundles/antigravity-plugin/skills/db-diagram/SKILL.md +148 -0
  35. package/bundles/antigravity-plugin/skills/db-diagram/scripts/sql_to_graph.py +1212 -0
  36. package/bundles/antigravity-plugin/skills/digress/SKILL.md +61 -0
  37. package/bundles/antigravity-plugin/skills/draw-io/SKILL.md +162 -0
  38. package/bundles/antigravity-plugin/skills/draw-io/references/aws-icons.md +677 -0
  39. package/bundles/antigravity-plugin/skills/draw-io/references/layout-guidelines.md +142 -0
  40. package/bundles/antigravity-plugin/skills/draw-io/references/troubleshooting.md +118 -0
  41. package/bundles/antigravity-plugin/skills/draw-io/references/workflows.md +103 -0
  42. package/bundles/antigravity-plugin/skills/draw-io/scripts/convert-drawio-to-png.sh +25 -0
  43. package/bundles/antigravity-plugin/skills/draw-io/scripts/find_aws_icon.py +79 -0
  44. package/bundles/antigravity-plugin/skills/error-handling/SKILL.md +260 -0
  45. package/bundles/antigravity-plugin/skills/excalidraw-db/SKILL.md +38 -0
  46. package/bundles/antigravity-plugin/skills/fastapi-dev/SKILL.md +300 -0
  47. package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +198 -0
  48. package/bundles/antigravity-plugin/skills/frontend-design/SKILL.md +193 -0
  49. package/bundles/antigravity-plugin/skills/frontend-design/references/my-tech-stack.md +127 -0
  50. package/bundles/antigravity-plugin/skills/gh-cli/SKILL.md +195 -0
  51. package/bundles/antigravity-plugin/skills/git-commit/SKILL.md +285 -0
  52. package/bundles/antigravity-plugin/skills/golden-plan/SKILL.md +577 -0
  53. package/bundles/antigravity-plugin/skills/handoff/SKILL.md +100 -0
  54. package/bundles/antigravity-plugin/skills/implement/SKILL.md +114 -0
  55. package/bundles/antigravity-plugin/skills/javascript-typescript/SKILL.md +142 -0
  56. package/bundles/antigravity-plugin/skills/kb/SKILL.md +60 -0
  57. package/bundles/antigravity-plugin/skills/mermaid-db/SKILL.md +33 -0
  58. package/bundles/antigravity-plugin/skills/mermaid-diagrams/SKILL.md +236 -0
  59. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/ENHANCEMENTS.md +264 -0
  60. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/MERMAID-SUMMARY.md +137 -0
  61. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/advanced-features.md +556 -0
  62. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/architecture-diagrams.md +192 -0
  63. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/c4-diagrams.md +410 -0
  64. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/class-diagrams.md +361 -0
  65. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/erd-diagrams.md +510 -0
  66. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/flowcharts.md +450 -0
  67. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/sequence-diagrams.md +394 -0
  68. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/troubleshooting.md +335 -0
  69. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/workflows.md +418 -0
  70. package/bundles/antigravity-plugin/skills/migrate-dir/SKILL.md +68 -0
  71. package/bundles/antigravity-plugin/skills/mockup/SKILL.md +242 -0
  72. package/bundles/antigravity-plugin/skills/particle-art/SKILL.md +243 -0
  73. package/bundles/antigravity-plugin/skills/particle-art/references/canvas-utils.ts +171 -0
  74. package/bundles/antigravity-plugin/skills/particle-art/references/dot-field.template.tsx +203 -0
  75. package/bundles/antigravity-plugin/skills/particle-art/references/flow-field.template.tsx +263 -0
  76. package/bundles/antigravity-plugin/skills/particle-art/references/node-shape.template.tsx +261 -0
  77. package/bundles/antigravity-plugin/skills/particle-art/references/shape-sampler.ts +281 -0
  78. package/bundles/antigravity-plugin/skills/particle-art/references/stipple-morph.template.tsx +167 -0
  79. package/bundles/antigravity-plugin/skills/particle-art/references/stipple.template.tsx +175 -0
  80. package/bundles/antigravity-plugin/skills/particle-art/references/trail-ghost.template.tsx +266 -0
  81. package/bundles/antigravity-plugin/skills/particle-art/references/usage-examples.md +320 -0
  82. package/bundles/antigravity-plugin/skills/playwright/API_REFERENCE.md +653 -0
  83. package/bundles/antigravity-plugin/skills/playwright/SKILL.md +454 -0
  84. package/bundles/antigravity-plugin/skills/playwright/lib/helpers.js +441 -0
  85. package/bundles/antigravity-plugin/skills/playwright/package.json +26 -0
  86. package/bundles/antigravity-plugin/skills/playwright/run.js +228 -0
  87. package/bundles/antigravity-plugin/skills/prd/SKILL.md +107 -0
  88. package/bundles/antigravity-plugin/skills/preflight/SKILL.md +435 -0
  89. package/bundles/antigravity-plugin/skills/python/SKILL.md +388 -0
  90. package/bundles/antigravity-plugin/skills/react-best-practices/SKILL.md +269 -0
  91. package/bundles/antigravity-plugin/skills/react-dev/README.md +404 -0
  92. package/bundles/antigravity-plugin/skills/react-dev/SKILL.md +459 -0
  93. package/bundles/antigravity-plugin/skills/react-dev/examples/generic-components.md +579 -0
  94. package/bundles/antigravity-plugin/skills/react-dev/examples/server-components.md +579 -0
  95. package/bundles/antigravity-plugin/skills/react-dev/references/event-handlers.md +574 -0
  96. package/bundles/antigravity-plugin/skills/react-dev/references/hooks.md +456 -0
  97. package/bundles/antigravity-plugin/skills/react-dev/references/react-19-patterns.md +638 -0
  98. package/bundles/antigravity-plugin/skills/react-dev/references/react-router.md +1002 -0
  99. package/bundles/antigravity-plugin/skills/react-dev/references/tanstack-router.md +587 -0
  100. package/bundles/antigravity-plugin/skills/refactoring/SKILL.md +486 -0
  101. package/bundles/antigravity-plugin/skills/resume/SKILL.md +36 -0
  102. package/bundles/antigravity-plugin/skills/security-review/SKILL.md +196 -0
  103. package/bundles/antigravity-plugin/skills/setup-project-ai/SKILL.md +61 -0
  104. package/bundles/antigravity-plugin/skills/ship/SKILL.md +107 -0
  105. package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +103 -0
  106. package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +102 -0
  107. package/bundles/antigravity-plugin/skills/skill-creator/LICENSE.txt +202 -0
  108. package/bundles/antigravity-plugin/skills/skill-creator/SKILL.md +491 -0
  109. package/bundles/antigravity-plugin/skills/skill-creator/agents/analyzer.md +274 -0
  110. package/bundles/antigravity-plugin/skills/skill-creator/agents/comparator.md +202 -0
  111. package/bundles/antigravity-plugin/skills/skill-creator/agents/grader.md +223 -0
  112. package/bundles/antigravity-plugin/skills/skill-creator/assets/eval_review.html +146 -0
  113. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  114. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  115. package/bundles/antigravity-plugin/skills/skill-creator/references/schemas.md +430 -0
  116. package/bundles/antigravity-plugin/skills/skill-creator/scripts/__init__.py +0 -0
  117. package/bundles/antigravity-plugin/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  118. package/bundles/antigravity-plugin/skills/skill-creator/scripts/generate_report.py +326 -0
  119. package/bundles/antigravity-plugin/skills/skill-creator/scripts/improve_description.py +247 -0
  120. package/bundles/antigravity-plugin/skills/skill-creator/scripts/package_skill.py +136 -0
  121. package/bundles/antigravity-plugin/skills/skill-creator/scripts/quick_validate.py +103 -0
  122. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_eval.py +310 -0
  123. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_loop.py +328 -0
  124. package/bundles/antigravity-plugin/skills/skill-creator/scripts/utils.py +47 -0
  125. package/bundles/antigravity-plugin/skills/sql/SKILL.md +321 -0
  126. package/bundles/antigravity-plugin/skills/tdd/SKILL.md +37 -0
  127. package/bundles/antigravity-plugin/skills/tdd-workflow/SKILL.md +188 -0
  128. package/bundles/antigravity-plugin/skills/technical-writing/SKILL.md +286 -0
  129. package/bundles/antigravity-plugin/skills/test-strategy/SKILL.md +155 -0
  130. package/bundles/antigravity-plugin/skills/ui-brief/SKILL.md +84 -0
  131. package/bundles/antigravity-plugin/skills/ui-review/SKILL.md +176 -0
  132. package/bundles/antigravity-plugin/skills/ui-review/references/framework-fixes.md +471 -0
  133. package/bundles/antigravity-plugin/skills/ui-review/references/visual-checklist.md +236 -0
  134. package/bundles/antigravity-plugin/skills/usage-review/SKILL.md +77 -0
  135. package/bundles/antigravity-plugin/skills/use-model/SKILL.md +64 -0
  136. package/bundles/antigravity-plugin/skills/using-git-worktrees/SKILL.md +217 -0
  137. package/bundles/antigravity-plugin/skills/version/SKILL.md +18 -0
  138. package/bundles/antigravity-plugin/skills/warm-editorial-ui/DESIGN_TOKENS.md +487 -0
  139. package/bundles/antigravity-plugin/skills/warm-editorial-ui/IMPLEMENTATION_GUIDE.md +177 -0
  140. package/bundles/antigravity-plugin/skills/warm-editorial-ui/SKILL.md +732 -0
  141. package/bundles/antigravity-plugin/skills/webapp-testing/LICENSE.txt +202 -0
  142. package/bundles/antigravity-plugin/skills/webapp-testing/SKILL.md +97 -0
  143. package/bundles/antigravity-plugin/skills/webapp-testing/examples/console_logging.py +35 -0
  144. package/bundles/antigravity-plugin/skills/webapp-testing/examples/element_discovery.py +40 -0
  145. package/bundles/antigravity-plugin/skills/webapp-testing/examples/static_html_automation.py +33 -0
  146. package/bundles/antigravity-plugin/skills/webapp-testing/scripts/with_server.py +106 -0
  147. package/bundles/antigravity-plugin/skills/windows-deployment/SKILL.md +880 -0
  148. package/bundles/antigravity-plugin/skills/writing-plans/SKILL.md +384 -0
  149. package/bundles/antigravity-plugin/statusline-command-agy.sh +91 -0
  150. package/bundles/antigravity-plugin/warm_start_agy.py +149 -0
  151. package/bundles/manifest.json +6 -0
  152. package/dist/cli.js +5363 -0
  153. package/package.json +61 -4
@@ -0,0 +1,486 @@
1
+ ---
2
+ name: refactoring
3
+ context: fork
4
+ description: Safely refactor code while maintaining behavior. Use when improving code structure, reducing duplication, extracting functions, or modernizing legacy code.
5
+ ---
6
+
7
+ # Refactoring Skill
8
+
9
+ Systematically refactor code to improve quality while preserving functionality.
10
+
11
+ ## Trigger
12
+
13
+ Activate when:
14
+ - User asks to "refactor" or "clean up" code
15
+ - Code review identifies structural issues
16
+ - User wants to improve maintainability
17
+ - Technical debt needs to be addressed
18
+
19
+ ---
20
+
21
+ ## Refactoring Principles
22
+
23
+ 1. **Never change behavior** during refactoring
24
+ 2. **Small steps** - one change at a time
25
+ 3. **Tests first** - ensure coverage before changing
26
+ 4. **Commit often** - after each successful refactoring
27
+ 5. **One thing at a time** - don't mix refactoring with feature changes
28
+
29
+ ### When NOT to Refactor
30
+
31
+ - Code that works and won't change again (if it ain't broke...)
32
+ - Critical production code without tests (add tests first)
33
+ - When under a tight deadline (schedule it for later)
34
+ - "Just because" - always have a clear purpose
35
+
36
+ ---
37
+
38
+ ## Phase 1: Assessment
39
+
40
+ ### Objectives
41
+ - Understand current code structure
42
+ - Identify refactoring opportunities
43
+ - Assess test coverage
44
+
45
+ ### Actions
46
+
47
+ 1. **Read and understand the code**
48
+ - What does this code do?
49
+ - What are the inputs/outputs?
50
+ - Where are the dependencies?
51
+
52
+ 2. **Identify code smells**
53
+
54
+ | Smell | Signs | Refactoring |
55
+ |-------|-------|-------------|
56
+ | Long Method | >20 lines | Extract Method |
57
+ | Large Class | >200 lines, multiple concerns | Extract Class |
58
+ | Duplicated Code | Same logic in multiple places | Extract Method/Class |
59
+ | Long Parameter List | >3-4 parameters | Parameter Object |
60
+ | Deep Nesting | >3 levels of indentation | Guard Clauses, Extract Method |
61
+ | Magic Numbers | Hardcoded values | Named Constants |
62
+ | Dead Code | Unused functions/variables | Delete |
63
+ | Feature Envy | Method uses another class's data more | Move Method |
64
+
65
+ 3. **Check test coverage**
66
+ ```bash
67
+ pytest --cov=module_name --cov-report=term-missing
68
+ ```
69
+
70
+ ### Output
71
+
72
+ ```markdown
73
+ ## Refactoring Assessment
74
+
75
+ ### Current State
76
+ - File: [filename]
77
+ - Lines: [count]
78
+ - Test Coverage: [percentage]
79
+
80
+ ### Code Smells Identified
81
+ 1. [Smell]: [Location] - [Description]
82
+ 2. [Smell]: [Location] - [Description]
83
+
84
+ ### Recommended Refactorings
85
+ 1. [Refactoring]: [Expected improvement]
86
+ 2. [Refactoring]: [Expected improvement]
87
+
88
+ ### Risk Assessment
89
+ - Test coverage: [adequate/needs improvement]
90
+ - Complexity: [low/medium/high]
91
+ - Dependencies: [list affected areas]
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Phase 2: Preparation
97
+
98
+ ### Objectives
99
+ - Ensure adequate test coverage
100
+ - Set up for safe refactoring
101
+
102
+ ### Actions
103
+
104
+ 1. **Write missing tests** (if coverage < 80%)
105
+ ```python
106
+ def test_existing_behavior():
107
+ """Capture current behavior before refactoring."""
108
+ result = function_to_refactor(input_data)
109
+ assert result == expected_output
110
+ ```
111
+
112
+ 2. **Create characterization tests** (for legacy code)
113
+ ```python
114
+ def test_characterization():
115
+ """Document current behavior, even if unexpected."""
116
+ # Run function and record actual output
117
+ result = legacy_function(test_input)
118
+ # Assert against actual output (not expected)
119
+ assert result == actual_observed_output
120
+ ```
121
+
122
+ 3. **Run all tests** and ensure they pass
123
+ ```bash
124
+ pytest -v
125
+ ```
126
+
127
+ 4. **Commit current state**
128
+ ```bash
129
+ git add .
130
+ git commit -m "chore: add tests before refactoring"
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Phase 3: Execute Refactoring
136
+
137
+ ### Common Refactoring Patterns
138
+
139
+ #### Extract Method
140
+
141
+ ```python
142
+ # Before: Long method with mixed concerns
143
+ def process_complaint(complaint):
144
+ # Validation (10 lines)
145
+ if not complaint.customer_id:
146
+ raise ValueError("Customer ID required")
147
+ if not complaint.description:
148
+ raise ValueError("Description required")
149
+ # ... more validation
150
+
151
+ # Processing (15 lines)
152
+ complaint.status = "processing"
153
+ # ... processing logic
154
+
155
+ # Notification (10 lines)
156
+ send_email(complaint.customer_email, "...")
157
+ # ... notification logic
158
+
159
+ # After: Extracted methods
160
+ def process_complaint(complaint):
161
+ validate_complaint(complaint)
162
+ process_complaint_logic(complaint)
163
+ send_complaint_notification(complaint)
164
+
165
+ def validate_complaint(complaint):
166
+ if not complaint.customer_id:
167
+ raise ValueError("Customer ID required")
168
+ if not complaint.description:
169
+ raise ValueError("Description required")
170
+
171
+ def process_complaint_logic(complaint):
172
+ complaint.status = "processing"
173
+ # ... processing logic
174
+
175
+ def send_complaint_notification(complaint):
176
+ send_email(complaint.customer_email, "...")
177
+ ```
178
+
179
+ #### Extract Class
180
+
181
+ ```python
182
+ # Before: Class doing too much
183
+ class ComplaintHandler:
184
+ def __init__(self):
185
+ self.db_connection = create_connection()
186
+
187
+ def create_complaint(self, data):
188
+ # 20 lines of complaint logic
189
+ pass
190
+
191
+ def send_email(self, to, subject, body):
192
+ # 15 lines of email logic
193
+ pass
194
+
195
+ def generate_report(self, date_range):
196
+ # 25 lines of reporting logic
197
+ pass
198
+
199
+ # After: Separated concerns
200
+ class ComplaintHandler:
201
+ def __init__(self, notifier, reporter):
202
+ self.notifier = notifier
203
+ self.reporter = reporter
204
+
205
+ def create_complaint(self, data):
206
+ # Complaint logic only
207
+ pass
208
+
209
+ class EmailNotifier:
210
+ def send_email(self, to, subject, body):
211
+ pass
212
+
213
+ class ComplaintReporter:
214
+ def generate_report(self, date_range):
215
+ pass
216
+ ```
217
+
218
+ #### Replace Conditionals with Polymorphism
219
+
220
+ ```python
221
+ # Before: Switch-like conditionals
222
+ def calculate_priority_score(complaint):
223
+ if complaint.type == "billing":
224
+ return complaint.amount * 0.1
225
+ elif complaint.type == "technical":
226
+ return 50 + complaint.severity * 10
227
+ elif complaint.type == "service":
228
+ return 30 + complaint.wait_time * 2
229
+ else:
230
+ return 10
231
+
232
+ # After: Strategy pattern
233
+ class PriorityCalculator(Protocol):
234
+ def calculate(self, complaint) -> float: ...
235
+
236
+ class BillingPriorityCalculator:
237
+ def calculate(self, complaint) -> float:
238
+ return complaint.amount * 0.1
239
+
240
+ class TechnicalPriorityCalculator:
241
+ def calculate(self, complaint) -> float:
242
+ return 50 + complaint.severity * 10
243
+
244
+ CALCULATORS = {
245
+ "billing": BillingPriorityCalculator(),
246
+ "technical": TechnicalPriorityCalculator(),
247
+ "service": ServicePriorityCalculator(),
248
+ }
249
+
250
+ def calculate_priority_score(complaint):
251
+ calculator = CALCULATORS.get(complaint.type, DefaultCalculator())
252
+ return calculator.calculate(complaint)
253
+ ```
254
+
255
+ #### Guard Clauses
256
+
257
+ ```python
258
+ # Before: Deep nesting
259
+ def process(data):
260
+ if data is not None:
261
+ if data.is_valid:
262
+ if data.has_permission:
263
+ # Actual logic here
264
+ result = do_something(data)
265
+ return result
266
+ else:
267
+ raise PermissionError()
268
+ else:
269
+ raise ValueError("Invalid data")
270
+ else:
271
+ raise ValueError("Data required")
272
+
273
+ # After: Guard clauses
274
+ def process(data):
275
+ if data is None:
276
+ raise ValueError("Data required")
277
+ if not data.is_valid:
278
+ raise ValueError("Invalid data")
279
+ if not data.has_permission:
280
+ raise PermissionError()
281
+
282
+ # Actual logic at main level
283
+ return do_something(data)
284
+ ```
285
+
286
+ #### Duplicated Code
287
+
288
+ ```python
289
+ # Before: Same logic in multiple places
290
+ def get_user_discount(user):
291
+ if user.membership == "gold": return user.total * 0.2
292
+ if user.membership == "silver": return user.total * 0.1
293
+ return 0
294
+
295
+ def get_order_discount(order):
296
+ if order.user.membership == "gold": return order.total * 0.2
297
+ if order.user.membership == "silver": return order.total * 0.1
298
+ return 0
299
+
300
+ # After: Extract common logic
301
+ DISCOUNT_RATES = {"gold": 0.2, "silver": 0.1}
302
+
303
+ def get_membership_rate(membership: str) -> float:
304
+ return DISCOUNT_RATES.get(membership, 0)
305
+ ```
306
+
307
+ #### Long Parameter List → Parameter Object
308
+
309
+ ```python
310
+ # Before: Too many parameters
311
+ def create_user(email, password, name, age, address, city, country, phone):
312
+ ...
313
+
314
+ # After: Group into a dataclass
315
+ @dataclass
316
+ class UserData:
317
+ email: str
318
+ password: str
319
+ name: str
320
+ age: int | None = None
321
+ address: str | None = None
322
+ phone: str | None = None
323
+
324
+ def create_user(data: UserData):
325
+ ...
326
+ ```
327
+
328
+ #### Feature Envy → Move Method
329
+
330
+ ```python
331
+ # Before: Method uses another object's data more than its own
332
+ class Order:
333
+ def calculate_discount(self, user):
334
+ if user.membership_level == "gold":
335
+ return self.total * 0.2
336
+ if user.account_age > 365:
337
+ return self.total * 0.1
338
+ return 0
339
+
340
+ # After: Move logic to the object that owns the data
341
+ class User:
342
+ def get_discount_rate(self) -> float:
343
+ if self.membership_level == "gold": return 0.2
344
+ if self.account_age > 365: return 0.1
345
+ return 0
346
+
347
+ class Order:
348
+ def calculate_discount(self, user):
349
+ return self.total * user.get_discount_rate()
350
+ ```
351
+
352
+ #### Primitive Obsession → Value Objects
353
+
354
+ ```python
355
+ # Before: Using raw strings for domain concepts
356
+ def send_email(to: str, subject: str, body: str): ...
357
+ send_email("user@example.com", "Hello", "...")
358
+
359
+ # After: Domain types with validation
360
+ class Email:
361
+ def __init__(self, value: str):
362
+ if "@" not in value:
363
+ raise ValueError(f"Invalid email: {value}")
364
+ self.value = value
365
+
366
+ def send_email(to: Email, subject: str, body: str): ...
367
+ ```
368
+
369
+ #### Dead Code → Delete It
370
+
371
+ ```python
372
+ # Before: Unused code lingers
373
+ def old_implementation(): ... # Nobody calls this
374
+ DEPRECATED_VALUE = 5 # Not referenced
375
+ # def commented_out_code(): ... # Noise
376
+
377
+ # After: Remove it — git has history if you need it back
378
+ ```
379
+
380
+ ### After Each Refactoring
381
+
382
+ 1. **Run tests**
383
+ ```bash
384
+ pytest -v
385
+ ```
386
+
387
+ 2. **If tests pass, commit**
388
+ ```bash
389
+ git commit -m "refactor: extract validation to separate method"
390
+ ```
391
+
392
+ 3. **If tests fail, revert**
393
+ ```bash
394
+ git checkout -- .
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Phase 4: Validation
400
+
401
+ ### Objectives
402
+ - Verify behavior unchanged
403
+ - Confirm quality improved
404
+ - Document changes
405
+
406
+ ### Actions
407
+
408
+ 1. **Run full test suite**
409
+ ```bash
410
+ pytest --cov=module_name
411
+ ```
412
+
413
+ 2. **Compare before/after metrics**
414
+ - Lines of code
415
+ - Cyclomatic complexity
416
+ - Test coverage
417
+ - Method/class sizes
418
+
419
+ 3. **Manual smoke test**
420
+ - Test key user flows
421
+ - Verify edge cases
422
+
423
+ ---
424
+
425
+ ## Phase 5: Documentation
426
+
427
+ ### Output
428
+
429
+ ```markdown
430
+ ## Refactoring Summary
431
+
432
+ ### Changes Made
433
+ 1. **[Refactoring 1]**: [What was changed and why]
434
+ 2. **[Refactoring 2]**: [What was changed and why]
435
+
436
+ ### Files Modified
437
+ - `path/to/file.py`: [Summary of changes]
438
+
439
+ ### Metrics Comparison
440
+ | Metric | Before | After |
441
+ |--------|--------|-------|
442
+ | Lines of Code | [x] | [y] |
443
+ | Methods >20 lines | [x] | [y] |
444
+ | Test Coverage | [x]% | [y]% |
445
+
446
+ ### Behavioral Changes
447
+ None (refactoring only)
448
+
449
+ ### Tests Added
450
+ - `test_function_name`: [What it tests]
451
+
452
+ ### Follow-up Recommendations
453
+ - [ ] [Future improvement 1]
454
+ - [ ] [Future improvement 2]
455
+ ```
456
+
457
+ ---
458
+
459
+ ## Common Refactoring Operations Reference
460
+
461
+ | Operation | Description |
462
+ |-----------|-------------|
463
+ | Extract Method | Turn code fragment into a method |
464
+ | Extract Class | Move behavior to a new class |
465
+ | Inline Method | Move method body back to caller |
466
+ | Introduce Parameter Object | Group related parameters |
467
+ | Replace Conditional with Polymorphism | Use strategy/polymorphism instead of switch/if |
468
+ | Replace Magic Number with Constant | Named constants for clarity |
469
+ | Decompose Conditional | Break complex conditions into named functions |
470
+ | Replace Nested Conditional with Guard Clauses | Early returns |
471
+ | Introduce Null Object | Eliminate null checks |
472
+ | Replace Type Code with Enum | Strong typing for categories |
473
+ | Replace Inheritance with Delegation | Composition over inheritance |
474
+
475
+ ---
476
+
477
+ ## Safety Checklist
478
+
479
+ - [ ] Tests exist for code being refactored
480
+ - [ ] All tests pass before starting
481
+ - [ ] Refactoring in small, atomic steps
482
+ - [ ] Tests run after each change
483
+ - [ ] Commits after each successful refactoring
484
+ - [ ] No behavior changes introduced
485
+ - [ ] All tests pass after completion
486
+ - [ ] Changes documented
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: resume
3
+ description: Pop the most recently parked workstream off the stack and resume it at its exact resume point
4
+ ---
5
+
6
+ # /caddis:resume — pop the parked task and pick it back up
7
+
8
+ A digression is finished; return to the task you parked with `/digress`. This pops the top frame off the
9
+ workstream stack, restates where you were, realigns `relay.md`, and immediately continues the work — the
10
+ user should not have to remember or re-state anything.
11
+
12
+ ## Step 1 — read the stack
13
+ Read `.caddis/workstreams.json`. If it is **absent, unparseable, `version != 1`, or `stack` is empty**,
14
+ say exactly `Nothing is parked.` and stop. Do nothing else.
15
+
16
+ ## Step 2 — pop the top frame
17
+ The top of stack is the **last** element of `stack` (LIFO — most recently parked). Remove it and write the
18
+ rest of the file back (preserve `version` and any other frames + unknown fields). This is the one write
19
+ this command makes to the state file.
20
+
21
+ ## Step 3 — restate + realign relay.md
22
+ Restate the popped frame to the user: its `plan`, `phase`, and `resumePointer` (and `repo` if set — the
23
+ parked task lives in another repo, so say which). Then edit `.caddis/relay.md`'s `## Next step` section
24
+ **in place** so it matches the popped frame's `resumePointer` — preserve every other section of relay.md
25
+ untouched. (If relay.md or that section is absent, skip this edit silently; the restatement above is enough.)
26
+
27
+ ## Step 4 — resume the work
28
+ Begin executing the `resumePointer` immediately. Ask nothing — the frame already carries the next action.
29
+ If the parked plan lives in another `repo`, note that the user may need to open that repo first, then
30
+ proceed there.
31
+
32
+ ## Rules
33
+ - **Never** run a destructive or history-rewriting git action (no `git checkout`, `git reset`, `git stash`,
34
+ branch switches). Resuming is metadata-only.
35
+ - Pop exactly one frame per invocation (the LIFO top). Run `/resume` again to pop the next.
36
+ - Only real paths and verified facts — restate the frame as written; do not embellish the resume point.
@@ -0,0 +1,196 @@
1
+ ---
2
+ name: security-review
3
+ context: fork
4
+ description: "Security review workflow — OWASP, code scanning, cloud infrastructure"
5
+ ---
6
+
7
+ # Security Review
8
+
9
+ Security review workflow covering OWASP Top 10, code scanning, and cloud infrastructure.
10
+
11
+ ## When to Use
12
+
13
+ - Implementing authentication or authorization
14
+ - Handling user input or file uploads
15
+ - Creating or modifying API endpoints
16
+ - Working with secrets, deploying to cloud, or configuring CI/CD
17
+
18
+ ## Phase 1: OWASP Top 10 Checks
19
+
20
+ ### A01 — Broken Access Control
21
+
22
+ ```python
23
+ # BAD — no auth check
24
+ @app.route("/admin/users")
25
+ def list_users():
26
+ return db.query(User).all()
27
+
28
+ # GOOD
29
+ @app.route("/admin/users")
30
+ @require_role("admin")
31
+ def list_users():
32
+ return db.query(User).all()
33
+ ```
34
+
35
+ - [ ] Every endpoint checks authentication
36
+ - [ ] Role-based access control enforced
37
+ - [ ] Users cannot access other users' data (IDOR)
38
+
39
+ ### A02 — Cryptographic Failures
40
+
41
+ ```python
42
+ # BAD: password_hash = hashlib.md5(password.encode()).hexdigest()
43
+ # GOOD:
44
+ from passlib.hash import argon2
45
+ password_hash = argon2.hash(password)
46
+ ```
47
+
48
+ - [ ] Passwords hashed with bcrypt/argon2
49
+ - [ ] Sensitive data encrypted at rest and in transit
50
+ - [ ] No secrets in source code or logs
51
+
52
+ ### A03 — Injection
53
+
54
+ ```python
55
+ # BAD: cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")
56
+ # GOOD:
57
+ cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
58
+ ```
59
+
60
+ - [ ] All queries parameterized or use ORM
61
+ - [ ] No `eval()`, `exec()`, or `os.system()` with user input
62
+
63
+ ### A05 — Security Misconfiguration
64
+
65
+ - [ ] Debug mode disabled in production
66
+ - [ ] Default credentials changed
67
+ - [ ] Unnecessary endpoints disabled
68
+
69
+ ### A06 — Vulnerable Components
70
+
71
+ ```bash
72
+ pip audit # Python
73
+ npm audit # JavaScript
74
+ trivy image app # Container
75
+ ```
76
+
77
+ - [ ] No known vulnerabilities; lock files committed
78
+
79
+ ### A07 — Authentication Failures
80
+
81
+ - [ ] Session tokens in httpOnly cookies (not localStorage)
82
+ - [ ] Account lockout after failed attempts
83
+ - [ ] MFA for privileged accounts
84
+
85
+ ### A09 — Logging Failures
86
+
87
+ ```python
88
+ # BAD: logger.info(f"Login: user={email}, password={password}")
89
+ # GOOD: logger.info(f"Login: user={email}, success={is_valid}")
90
+ ```
91
+
92
+ - [ ] Auth events logged; no PII or secrets in logs
93
+
94
+ ### A10 — SSRF
95
+
96
+ ```python
97
+ ALLOWED_HOSTS = {"api.example.com"}
98
+ parsed = urlparse(user_url)
99
+ if parsed.hostname not in ALLOWED_HOSTS:
100
+ raise ValueError("URL not allowed")
101
+ ```
102
+
103
+ ## Phase 2: Input Validation
104
+
105
+ ```python
106
+ from pydantic import BaseModel, EmailStr, constr, conint
107
+
108
+ class CreateUserRequest(BaseModel):
109
+ email: EmailStr
110
+ name: constr(min_length=1, max_length=100)
111
+ age: conint(ge=0, le=150)
112
+
113
+ # Validate
114
+ try:
115
+ data = CreateUserRequest(**request_json)
116
+ except ValidationError as e:
117
+ return {"error": e.errors()}, 400
118
+ ```
119
+
120
+ File uploads: check size, extension, and magic bytes.
121
+
122
+ ## Phase 3: Security Headers
123
+
124
+ ```python
125
+ @app.after_request
126
+ def add_security_headers(response):
127
+ response.headers["X-Content-Type-Options"] = "nosniff"
128
+ response.headers["X-Frame-Options"] = "DENY"
129
+ response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
130
+ response.headers["Content-Security-Policy"] = (
131
+ "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
132
+ )
133
+ return response
134
+ ```
135
+
136
+ ## Phase 4: Cloud Infrastructure
137
+
138
+ ### IAM — Least Privilege
139
+
140
+ ```yaml
141
+ # GOOD: specific permissions on specific resources
142
+ permissions: [s3:GetObject, s3:ListBucket]
143
+ resources: [arn:aws:s3:::my-bucket/*]
144
+
145
+ # BAD: permissions: [s3:*], resources: ["*"]
146
+ ```
147
+
148
+ - [ ] No root account in production; MFA on privileged accounts
149
+ - [ ] Service accounts use roles, not long-lived keys
150
+
151
+ ### Secrets Management
152
+
153
+ - [ ] Secrets in a manager (AWS SM, Vault) with rotation
154
+ - [ ] No secrets in env vars without rotation policy
155
+
156
+ ### CI/CD Security
157
+
158
+ ```yaml
159
+ jobs:
160
+ deploy:
161
+ permissions: { contents: read }
162
+ steps:
163
+ - uses: actions/checkout@v4
164
+ - uses: trufflesecurity/trufflehog@main # Secret scanning
165
+ - run: pip audit # Dep audit
166
+ - run: pytest --cov=myapp --cov-fail-under=80
167
+ ```
168
+
169
+ - [ ] OIDC instead of long-lived credentials
170
+ - [ ] Branch protection and code review required
171
+
172
+ ### Network
173
+
174
+ - [ ] Database not publicly accessible
175
+ - [ ] Security groups follow least privilege
176
+ - [ ] WAF enabled
177
+
178
+ ## Pre-Deployment Checklist
179
+
180
+ - [ ] No hardcoded secrets
181
+ - [ ] All user inputs validated server-side
182
+ - [ ] All queries parameterized
183
+ - [ ] Auth + authz on every endpoint
184
+ - [ ] Rate limiting enabled
185
+ - [ ] HTTPS enforced
186
+ - [ ] Security headers configured
187
+ - [ ] No sensitive data in error responses or logs
188
+ - [ ] Dependencies audited
189
+ - [ ] Cloud IAM least-privilege applied
190
+ - [ ] Backups automated with tested recovery
191
+
192
+ ## Resources
193
+
194
+ - [OWASP Top 10](https://owasp.org/www-project-top-ten/)
195
+ - [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
196
+ - [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks)