Skip to content

Commit 422c91f

Browse files
authored
Merge pull request #177 from Sagargupta16/feat/tds-schedule
feat(tax): TDS schedule + clean-code & SonarCloud refactor passes
2 parents 9c01d24 + 0a35b3a commit 422c91f

80 files changed

Lines changed: 3899 additions & 1729 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/boy-scout/SKILL.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
name: boy-scout
3+
description: Use when fixing, editing, changing, debugging, or working with any Python code. Applies the Boy Scout Rule—always leave code cleaner than you found it. Orchestrates other clean code skills as needed.
4+
when_to_use: |
5+
Also trigger on: "while you're at it", "any quick wins", "improve this a bit", "anything else obviously wrong", or when editing existing Python and an adjacent small cleanup is possible alongside the asked-for change.
6+
---
7+
8+
# The Boy Scout Rule
9+
10+
> "Always leave the campground cleaner than you found it."
11+
> — Robert Baden-Powell
12+
13+
> "Always check a module in cleaner than when you checked it out."
14+
> — Robert C. Martin, *Clean Code*
15+
16+
## The Philosophy
17+
18+
You don't have to make every module perfect. You simply have to make it **a little bit better** than when you found it.
19+
20+
If we all followed this simple rule:
21+
- Our systems would gradually get better as they evolved
22+
- Teams would care for the system as a whole
23+
- The relentless deterioration of software would end
24+
25+
## When Working on Code
26+
27+
Every time you touch code, look for **at least one small improvement**:
28+
29+
### Quick Wins (Do These Immediately)
30+
- Rename a poorly named variable → triggers `clean-names`
31+
- Delete a redundant comment → triggers `clean-comments`
32+
- Remove dead code or unused imports
33+
- Replace a magic number with a named constant
34+
- Extract a deeply nested block into a well-named function
35+
36+
### Deeper Improvements (When Time Allows)
37+
- Split a function that does multiple things → triggers `clean-functions`
38+
- Remove duplication (DRY) → triggers `clean-general`
39+
- Add missing boundary checks
40+
- Improve test coverage → triggers `clean-tests`
41+
42+
## The Rule in Practice
43+
44+
```python
45+
# You're asked to fix a bug in this function:
46+
def proc(d, x, flag=False):
47+
# process data
48+
for i in d:
49+
if i > 0:
50+
if flag:
51+
x.append(i * 1.0825) # tax
52+
else:
53+
x.append(i)
54+
return x
55+
56+
# Don't just fix the bug and leave.
57+
# Leave it cleaner:
58+
TAX_RATE = 0.0825
59+
60+
def process_positive_values(
61+
values: list[float],
62+
apply_tax: bool = False
63+
) -> list[float]:
64+
"""Filter positive values, optionally applying tax."""
65+
rate = 1 + TAX_RATE if apply_tax else 1
66+
return [v * rate for v in values if v > 0]
67+
```
68+
69+
**What changed:**
70+
- ✅ Descriptive function name (N1)
71+
- ✅ Clear parameter names (N1)
72+
- ✅ Type hints (P3)
73+
- ✅ Named constant for magic number (G25)
74+
- ✅ No output argument mutation (F2)
75+
- ✅ Useful docstring (C4)
76+
77+
## Skill Orchestration
78+
79+
This skill coordinates with specialized skills based on what you're doing:
80+
81+
| Task | Trigger Skill |
82+
|------|---------------|
83+
| Writing/reviewing any Python | `python-clean-code` (master) |
84+
| Naming variables, functions, classes | `clean-names` |
85+
| Writing or editing comments | `clean-comments` |
86+
| Creating or refactoring functions | `clean-functions` |
87+
| Reviewing code quality | `clean-general` |
88+
| Writing or reviewing tests | `clean-tests` |
89+
90+
## The Mindset
91+
92+
**Don't:**
93+
- Leave code worse than you found it
94+
- Say "that's not my code"
95+
- Wait for a dedicated refactoring sprint
96+
- Make massive changes unrelated to your task
97+
98+
**Do:**
99+
- Make one small improvement with every commit
100+
- Fix what you see, even if you didn't break it
101+
- Keep changes proportional to your task
102+
- Leave a trail of quality improvements
103+
104+
## AI Behavior
105+
106+
When working on code:
107+
1. Complete the requested task first
108+
2. Identify at least one small cleanup opportunity
109+
3. Apply the appropriate specialized skill
110+
4. Note the improvement made (e.g., "Also cleaned up: renamed `x` to `results` for clarity")
111+
112+
When reviewing code:
113+
1. Load `python-clean-code` for comprehensive rule checking
114+
2. Flag violations by rule number
115+
3. Suggest incremental improvements, not complete rewrites
116+
117+
## The Boy Scout Promise
118+
119+
Every piece of code you touch gets a little better. Not perfect—just better.
120+
121+
Over time, better compounds into excellent.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
name: clean-comments
3+
description: Use when writing, fixing, editing, or reviewing Python comments and docstrings. Enforces Clean Code principles—no metadata, no redundancy, no commented-out code.
4+
when_to_use: |
5+
Also trigger on: commented-out code blocks, TODO/FIXME banners, author/ticket/date metadata in comments, docstrings that no longer match the code, redundant comments that restate the code (e.g. `i += 1 # increment i`), or asks like "is this comment useful", "why is this block commented".
6+
---
7+
8+
# Clean Comments
9+
10+
## C1: No Inappropriate Information
11+
12+
Comments shouldn't hold metadata. Use Git for author names, change history,
13+
ticket numbers, and dates. Comments are for technical notes about code only.
14+
15+
## C2: Delete Obsolete Comments
16+
17+
If a comment describes code that no longer exists or works differently,
18+
delete it immediately. Stale comments become "floating islands of
19+
irrelevance and misdirection."
20+
21+
## C3: No Redundant Comments
22+
23+
```python
24+
# Bad - the code already says this
25+
i += 1 # increment i
26+
user.save() # save the user
27+
28+
# Good - explains WHY, not WHAT
29+
i += 1 # compensate for zero-indexing in display
30+
```
31+
32+
## C4: Write Comments Well
33+
34+
If a comment is worth writing, write it well:
35+
- Choose words carefully
36+
- Use correct grammar
37+
- Don't ramble or state the obvious
38+
- Be brief
39+
40+
## C5: Never Commit Commented-Out Code
41+
42+
```python
43+
# DELETE THIS - it's an abomination
44+
# def old_calculate_tax(income):
45+
# return income * 0.15
46+
```
47+
48+
Who knows how old it is? Who knows if it's meaningful? Delete it.
49+
Git remembers everything.
50+
51+
## The Goal
52+
53+
The best comment is the code itself. If you need a comment to explain
54+
what code does, refactor first, comment last.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
name: clean-functions
3+
description: Use when writing, fixing, editing, or refactoring Python functions. Enforces Clean Code principles—maximum 3 arguments, single responsibility, no flag parameters.
4+
when_to_use: |
5+
Also trigger on: functions with 4+ parameters, boolean flag parameters like `enabled=True`, functions that mutate their arguments in place, one-off `util`/`helper` functions that are never called, or asks like "too many arguments", "split this function", "is this still used".
6+
---
7+
8+
# Clean Functions
9+
10+
## F1: Too Many Arguments (Maximum 3)
11+
12+
```python
13+
# Bad - too many parameters
14+
def create_user(name, email, age, country, timezone, language, newsletter):
15+
...
16+
17+
# Good - use a dataclass or dict
18+
@dataclass
19+
class UserData:
20+
name: str
21+
email: str
22+
age: int
23+
country: str
24+
timezone: str
25+
language: str
26+
newsletter: bool
27+
28+
def create_user(data: UserData):
29+
...
30+
```
31+
32+
More than 3 arguments means your function is doing too much or needs
33+
a data structure.
34+
35+
## F2: No Output Arguments
36+
37+
Don't modify arguments as side effects. Return values instead.
38+
39+
```python
40+
# Bad - modifies argument
41+
def append_footer(report: Report) -> None:
42+
report.append("\n---\nGenerated by System")
43+
44+
# Good - returns new value
45+
def with_footer(report: Report) -> Report:
46+
return report + "\n---\nGenerated by System"
47+
```
48+
49+
## F3: No Flag Arguments
50+
51+
Boolean flags mean your function does at least two things.
52+
53+
```python
54+
# Bad - function does two different things
55+
def render(is_test: bool):
56+
if is_test:
57+
render_test_page()
58+
else:
59+
render_production_page()
60+
61+
# Good - split into two functions
62+
def render_test_page(): ...
63+
def render_production_page(): ...
64+
```
65+
66+
## F4: Delete Dead Functions
67+
68+
If it's not called, delete it. No "just in case" code. Git preserves history.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
name: clean-general
3+
description: Use when writing, fixing, editing, or reviewing Python code quality. Enforces Clean Code's core principles—DRY, single responsibility, clear intent, no magic numbers, proper abstractions.
4+
when_to_use: |
5+
Also trigger on: duplicated logic across files or branches (G5), magic numbers or hardcoded values (G25), long if/elif chains that should be polymorphism (G23), chained property access like `a.b.c.d` (G36), functions juggling multiple responsibilities (G30), clever one-liners whose intent is not obvious (G16).
6+
---
7+
8+
# General Clean Code Principles
9+
10+
## Critical Rules
11+
12+
**G5: DRY (Don't Repeat Yourself)**
13+
14+
Every piece of knowledge has one authoritative representation.
15+
16+
```python
17+
# Bad - duplication
18+
tax_rate = 0.0825
19+
ca_total = subtotal * 1.0825
20+
ny_total = subtotal * 1.07
21+
22+
# Good - single source of truth
23+
TAX_RATES = {"CA": 0.0825, "NY": 0.07}
24+
def calculate_total(subtotal: float, state: str) -> float:
25+
return subtotal * (1 + TAX_RATES[state])
26+
```
27+
28+
**G16: No Obscured Intent**
29+
30+
Don't be clever. Be clear.
31+
32+
```python
33+
# Bad - what does this do?
34+
return (x & 0x0F) << 4 | (y & 0x0F)
35+
36+
# Good - obvious intent
37+
return pack_coordinates(x, y)
38+
```
39+
40+
**G23: Prefer Polymorphism to If/Else**
41+
42+
```python
43+
# Bad - will grow forever
44+
def calculate_pay(employee):
45+
if employee.type == "SALARIED":
46+
return employee.salary
47+
elif employee.type == "HOURLY":
48+
return employee.hours * employee.rate
49+
elif employee.type == "COMMISSIONED":
50+
return employee.base + employee.commission
51+
52+
# Good - open/closed principle
53+
class SalariedEmployee:
54+
def calculate_pay(self): return self.salary
55+
56+
class HourlyEmployee:
57+
def calculate_pay(self): return self.hours * self.rate
58+
59+
class CommissionedEmployee:
60+
def calculate_pay(self): return self.base + self.commission
61+
```
62+
63+
**G25: Replace Magic Numbers with Named Constants**
64+
65+
```python
66+
# Bad
67+
if elapsed_time > 86400:
68+
...
69+
70+
# Good
71+
SECONDS_PER_DAY = 86400
72+
if elapsed_time > SECONDS_PER_DAY:
73+
...
74+
```
75+
76+
**G30: Functions Should Do One Thing**
77+
78+
If you can extract another function, your function does more than one thing.
79+
80+
**G36: Law of Demeter (Avoid Train Wrecks)**
81+
82+
```python
83+
# Bad - reaching through multiple objects
84+
output_dir = context.options.scratch_dir.absolute_path
85+
86+
# Good - one dot
87+
output_dir = context.get_scratch_dir()
88+
```
89+
90+
## Enforcement Checklist
91+
92+
When reviewing AI-generated code, verify:
93+
- [ ] No duplication (G5)
94+
- [ ] Clear intent, no magic numbers (G16, G25)
95+
- [ ] Polymorphism over conditionals (G23)
96+
- [ ] Functions do one thing (G30)
97+
- [ ] No Law of Demeter violations (G36)
98+
- [ ] Boundary conditions handled (G3)
99+
- [ ] Dead code removed (G9)

0 commit comments

Comments
 (0)