Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .claude/hooks/skill-rules.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,53 @@
"gh pr comment"
]
}
},
"feature-toggle-developer": {
"type": "domain",
"priority": "high",
"description": "Smart router to feature toggle removal (→ feature-toggle-developer.md). Systematic toggle removal, automated cleanup detection, unused code identification",
"promptTriggers": {
"keywords": [
"remove toggle",
"delete toggle",
"enable toggle",
"feature flag",
"feature toggle",
"remove feature flag",
"delete feature flag",
"enable feature flag",
"cleanup after toggle",
"unused code",
"orphaned code",
"defaultValue: true",
"defaultValue: false",
"FeatureFlags.",
"toggle removal"
],
"intentPatterns": [
"(remove|delete|eliminate).*?(toggle|feature flag|feature toggle)",
"(enable|activate|turn on).*?(toggle|feature flag|permanently)",
"(cleanup|clean up|remove unused).*?(code|component|class|file)",
"(find|identify|check for).*?(unused|orphaned|dead).*?(code|component)",
"(after|completed).*?(toggle|feature flag).*?(removal|cleanup)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/FeatureDescription+Flags.swift",
"**/FeatureFlags+Flags.swift",
"**/.claude/skills/feature-toggle-developer.md"
],
"contentPatterns": [
"FeatureFlags\\.",
"static let.*=.*FeatureDescription",
"defaultValue: true",
"defaultValue: false",
"if FeatureFlags\\.",
"guard.*FeatureFlags\\.",
"@State.*FeatureFlags"
]
}
}
},
"config": {
Expand Down
309 changes: 309 additions & 0 deletions .claude/skills/feature-toggle-developer/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
# Feature Toggle Developer

**Status**: Active
**Auto-activates on**: Feature flag/toggle removal, cleanup after refactoring toggles
**Related Skills**: `code-generation-developer`, `ios-dev-guidelines`, `code-review-developer`

## Purpose

Guides the systematic removal of feature toggles (feature flags) from the codebase with automated cleanup detection. Ensures no orphaned code, unused components, or forgotten files remain after toggle removal.

## When This Skill Activates

- User mentions: "remove toggle", "delete feature flag", "enable feature toggle permanently"
- User edits: `FeatureDescription+Flags.swift`
- After completing toggle removal: helps identify cleanup opportunities

## Feature Toggle Removal Workflow

### Phase 1: Pre-Removal Analysis

Before removing any toggle, gather complete information:

1. **Find the toggle definition**:
```bash
# Location: Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift
rg "static let toggleName" --type swift
```

2. **Check the defaultValue** to determine which branch to keep:
- `defaultValue: true` → Keep the TRUE branch, remove FALSE branch
- `defaultValue: false` → Keep the FALSE branch, remove TRUE branch

3. **Search for ALL usages**:
```bash
rg "toggleName" --type swift
```

4. **Identify usage patterns**:
- Direct: `if FeatureFlags.toggleName { ... }`
- Inverted: `if !FeatureFlags.toggleName { ... }` or `guard !FeatureFlags.toggleName`
- Compound: `if FeatureFlags.toggleName && otherCondition { ... }`
- Assignment: `let value = FeatureFlags.toggleName ? a : b`
- State: `@State private var toggle = FeatureFlags.toggleName`

5. **List affected files** and present to user for review

### Phase 2: Toggle Removal

Systematic removal process:

1. **Remove conditional checks and simplify**:

**Example 1 - Simple conditional (defaultValue: true)**:
```swift
// BEFORE
if FeatureFlags.toggleName {
// feature code
}

// AFTER (keep true branch)
// feature code
```

**Example 2 - Ternary operator (defaultValue: true)**:
```swift
// BEFORE
VStack(spacing: FeatureFlags.toggleName ? 8 : 0)

// AFTER
VStack(spacing: 8)
```

**Example 3 - Inverted logic (defaultValue: true)**:
```swift
// BEFORE
guard !FeatureFlags.toggleName else { return }
oldCode()

// AFTER (flag is true, so guard fails, remove entire block)
// [entire block deleted]
```

**Example 4 - State variable (defaultValue: true)**:
```swift
// BEFORE
@State private var toggle = FeatureFlags.toggleName
if toggle { newUI() } else { oldUI() }

// AFTER
newUI()
// Note: @State variable removed in cleanup phase
```

2. **Remove feature flag definition**:
```swift
// Delete from: Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift
static let toggleName = FeatureDescription(...)
```

3. **Run code generation**:
```bash
make generate
```
This updates `FeatureFlags+Flags.swift` automatically.

4. **Verify removal**:
```bash
rg "toggleName" --type swift # Should return no results
```

### Phase 3: Automated Cleanup Detection ⭐

**CRITICAL**: After toggle removal, systematically check for orphaned code:

#### 3.1 Unused State Variables

Search for `@State` variables that were only used for the toggle:

```bash
# Look for patterns like: @State private var someToggle = FeatureFlags.toggleName
rg "@State.*=.*FeatureFlags" --type swift
```

**Action**: Remove the entire `@State` variable declaration if it's no longer used.

#### 3.2 Unused View Components

When a toggle controlled which UI component to show, one component may now be unused:

**Detection Pattern**:
- Toggle switched between ComponentA and ComponentB
- After removal, only one is used
- Search for the unused component's name across codebase

**Example from vaultBackToRoots**:
```swift
// BEFORE
if !vaultBackToRootsToggle {
SpaceCardLabel(...) // This became unused
} else {
NewSpaceCardLabel(...)
}

// AFTER
NewSpaceCardLabel(...)

// CLEANUP: SpaceCardLabel is now unused
rg "SpaceCardLabel" --type swift # Check if used anywhere else
# If only in its own file → DELETE the file
```

**Action**:
1. Search for unused component name: `rg "UnusedComponentName" --type swift`
2. If only found in its definition file and comments → DELETE the file
3. Update references in comments

#### 3.3 Unused ViewModels / Service Classes

Toggle removal may leave entire classes unused:

**Detection**:
```bash
# For each major component that was conditionally used:
rg "UnusedViewModel" --type swift
rg "class UnusedViewModel" --type swift
```

**Action**: Delete unused ViewModels, their files, and DI registrations.

#### 3.4 Unused Imports

After simplification, `import AnytypeCore` may only have been needed for `FeatureFlags`:

**Detection**:
- File imports `AnytypeCore`
- Only usage was `FeatureFlags.toggleName`
- After removal, no other `AnytypeCore` usage

**Action**: Remove unused import.

#### 3.5 Orphaned Parameters / Properties

Toggle-gated functionality may have parameters that are no longer needed:

**Example**:
```swift
// BEFORE
func configure(showFeature: Bool) {
if showFeature && FeatureFlags.toggle { ... }
}

// AFTER toggle removal
func configure(showFeature: Bool) {
if showFeature { ... }
}

// POTENTIAL CLEANUP: Is showFeature still needed?
```

**Action**: Review function signatures and remove unnecessary parameters.

#### 3.6 Test Cleanup

Toggle removal affects tests:

**Check**:
1. Mock objects with toggle-related properties
2. Test cases specifically for toggle behavior
3. Test setup code with toggle configurations

**Files to check**:
```bash
rg "toggleName" AnyTypeTests/ --type swift
rg "toggleName" "Anytype/Sources/PreviewMocks/" --type swift
```

**Action**: Update or remove tests for deleted code paths.

### Phase 4: Final Verification

Before committing:

1. **Grep verification**:
```bash
rg "toggleName" --type swift # Should be empty
```

2. **Compilation check**:
- Remind user to verify compilation in Xcode
- Claude cannot verify this due to caching

3. **Generate updated commit message**:
```
IOS-XXXX Removed [toggleName] toggle
```

4. **Review cleanup summary**:
- List all files modified
- List all files deleted
- Note any remaining manual checks needed

## Cleanup Checklist Template

Use this checklist after every toggle removal:

```markdown
## Cleanup Verification for [toggleName]

- [ ] Toggle definition removed from FeatureDescription+Flags.swift
- [ ] `make generate` run successfully
- [ ] All conditional usage removed
- [ ] No grep results for toggle name
- [ ] Unused @State variables removed
- [ ] Unused view components identified and deleted
- [ ] Unused ViewModels/services deleted
- [ ] Unused imports removed (especially AnytypeCore)
- [ ] Orphaned function parameters removed
- [ ] Tests updated (check AnyTypeTests/ and PreviewMocks/)
- [ ] Comments referencing old component updated
- [ ] Xcode compilation verified (by user)
```

## Common Patterns & Pitfalls

### Inverted Logic

**Watch out for** `!FeatureFlags.toggle`:

```swift
// If defaultValue: true
if !FeatureFlags.toggle {
oldCode() // This branch NEVER runs, delete it
}
```

### Compound Conditions

**Simplify** conditions properly:

```swift
// BEFORE (defaultValue: true)
if FeatureFlags.toggle && userHasPermission {
showFeature()
}

// AFTER
if userHasPermission {
showFeature()
}
```

### Guard Statements

**Be careful** with guards:

```swift
// BEFORE (defaultValue: true)
guard !FeatureFlags.toggle else { return }
performOldBehavior()

// AFTER (toggle is true, guard returns, entire block is dead code)
// DELETE ENTIRE BLOCK
```

## Integration with Other Skills

- **code-generation-developer**: References for `make generate` command and troubleshooting
- **ios-dev-guidelines**: Swift refactoring patterns, import management
- **code-review-developer**: Cleanup standards, ensuring no orphaned code in PRs
3 changes: 2 additions & 1 deletion .claude/skills/skills-manager/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,14 @@ echo "Update space settings localization for membership tiers" | .claude/hooks/u

**Location**: `.claude/skills/*/SKILL.md`

**The 6 skills**:
**The 7 skills**:
1. `ios-dev-guidelines` - Swift/iOS patterns
2. `localization-developer` - Localization
3. `code-generation-developer` - Feature flags, make generate
4. `design-system-developer` - Icons, typography, colors
5. `skills-manager` - This skill (meta!)
6. `code-review-developer` - Code review standards
7. `feature-toggle-developer` - Feature toggle removal, cleanup detection

### Configuration

Expand Down