Search

PythonReactSEOPDF
GitHub Skill

duplicate-detector

Detects duplicate implementations, SSoT violations, and banned patterns. Use before any code change that adds new logic, config, or constants.

gotekna☆ 0 Repository stars0 Repository forks

Installation

Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.

View source ↗Guides

Skill instructions

Duplicate Detector

Note: This skill focuses on finding duplicated code patterns and SSoT violations. For Rails method validation (NoMethodError prevention), see the method-auditor agent.

When Claude Should Use This

  • Adding a new constant or config value
  • Implementing business logic
  • Creating a new component or service
  • Adding environment variables
  • Defining routes or endpoints
  • Adding UI features (fullscreen, loading states, modals)
  • Before writing any new code - check if pattern exists

Process

Step 1: Check Component Registry FIRST
# Always check if component/pattern exists in registry
grep -i "FEATURE_NAME" frontend-next/lib/component-registry.ts
Step 2: Search for Existing Implementations
# Search both frontend and backend
grep -ri "SEARCH_TERM" backend/ frontend-next/ --include="*.rb" --include="*.ts" --include="*.tsx" --include="*.yml" --include="*.json" | grep -v node_modules | head -20
Step 3: If Found in Multiple Places
  1. List all locations with file:line
  2. Show the user both implementations
  3. Ask: "Which is the source of truth?"
  4. Wait for user response
  5. Consolidate to one location after user confirms
Step 4: If Not Found
  • Proceed with implementation
  • Add to SSoT component if it's a reusable pattern
  • Register in component-registry.ts if new component

UI Component SSoT Checks

Run These Before ANY UI Work
1. Lucide Loader Violations (Should use Spinner)
echo "=== LUCIDE LOADER VIOLATIONS ==="
grep -rn "Loader.*from.*lucide-react\|from.*lucide-react.*Loader" frontend-next/app frontend-next/components --include="*.tsx" | grep -v "spinner.tsx"

Fix: Replace with import { Spinner } from "@/components/ui/spinner"

2. router.back() Violations (Should use BackButton)
echo "=== ROUTER.BACK() VIOLATIONS ==="
grep -rn "router\.back()" frontend-next/app frontend-next/components --include="*.tsx" | grep -v "back-button.tsx"

Fix: Replace with <BackButton fallbackHref="/parent-route" />

3. Custom Spinner Patterns (Should use Spinner)
echo "=== CUSTOM SPINNER PATTERNS ==="
grep -rn "animate-spin" frontend-next/app frontend-next/components --include="*.tsx" | grep -v "spinner.tsx" | head -20

Fix: Replace with <Spinner /> component

4. Fullscreen Pattern Duplication
echo "=== FULLSCREEN DUPLICATIONS ==="
grep -rn "Fullscreen\|setFullscreen\|isFullscreen" frontend-next/app frontend-next/components --include="*.tsx" | grep -v "component-registry"

SSoT: TeeemTableView has enableFullscreen prop for tables

5. Escape Key Handler Duplication
echo "=== ESCAPE HANDLER DUPLICATIONS ==="
grep -rn "Escape.*=>\|key.*Escape" frontend-next/app frontend-next/components --include="*.tsx" | head -20

Check: Should escape handling be in a shared component?

6. Unregistered Components
echo "=== UNREGISTERED COMPONENTS ==="
for file in frontend-next/components/ui/*.tsx; do
  component=$(basename "$file" .tsx)
  if ! grep -q "\"$component\"" frontend-next/lib/component-registry.ts 2>/dev/null; then
    count=$(grep -r "from.*ui/$component" frontend-next --include="*.tsx" 2>/dev/null | wc -l)
    if [ "$count" -gt 0 ]; then
      echo "NOT REGISTERED: $component (used $count times)"
    fi
  fi
done

Full Audit Command

Run this to check all SSoT violations at once:

echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║           SSoT COMPONENT AUDITOR                                 ║"
echo "╚══════════════════════════════════════════════════════════════════╝"

echo ""
echo "=== 1. LUCIDE LOADER VIOLATIONS (use Spinner) ==="
grep -rn "Loader.*from.*lucide-react\|from.*lucide-react.*Loader" frontend-next/app frontend-next/components --include="*.tsx" 2>/dev/null | grep -v "spinner.tsx" || echo "None found"

echo ""
echo "=== 2. ROUTER.BACK() VIOLATIONS (use BackButton) ==="
grep -rn "router\.back()" frontend-next/app frontend-next/components --include="*.tsx" 2>/dev/null | grep -v "back-button.tsx" || echo "None found"

echo ""
echo "=== 3. CUSTOM ANIMATE-SPIN (use Spinner) ==="
grep -rn "animate-spin" frontend-next/app frontend-next/components --include="*.tsx" 2>/dev/null | grep -v "spinner.tsx" | head -10 || echo "None found"

echo ""
echo "=== 4. DEPRECATED IMPORTS ==="
grep -rn "from.*@/components/ui/combobox['\"]" frontend-next --include="*.tsx" 2>/dev/null | grep -v "combobox-dropdown" | head -5
grep -rn "from.*@/components/ui/loader" frontend-next --include="*.tsx" 2>/dev/null | head -5
grep -rn "from.*@/components/ui/drawer" frontend-next --include="*.tsx" 2>/dev/null | head -5
echo "(empty = good)"

echo ""
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║           AUDIT COMPLETE                                         ║"
echo "╚══════════════════════════════════════════════════════════════════╝"

Backend Data Model SSoT Checks

The root_path problem: Same concept stored in 3 tables. Catch this BEFORE it happens.

Run Before Adding ANY Database Column
# 1. Does this column already exist?
grep -n "COLUMN_NAME" backend/db/schema.rb

# 2. Is there a similar column?
grep -n "path\|config\|setting" backend/db/schema.rb | grep -i "RELATED_TERM"

Decision Tree:

  • Column exists? → SSoT VIOLATION - use existing column
  • Config/path data? → Goes in StorageConfiguration
  • Credential/auth data? → Goes in appropriate credential table
  • Setting data? → Goes in CompanySetting or CorporateCompanySetting
Full Backend SSoT Audit
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║           BACKEND SSoT AUDITOR                                   ║"
echo "╚══════════════════════════════════════════════════════════════════╝"

echo ""
echo "=== 1. DUPLICATE COLUMN NAMES ACROSS TABLES ==="
for col in root_path site_id drive_id client_id tenant_id endpoint bucket; do
  count=$(grep -c "\"$col\"" backend/db/schema.rb 2>/dev/null || echo 0)
  if [ "$count" -gt 1 ]; then
    echo "⚠️  WARNING: $col appears $count times:"
    grep -n "\"$col\"" backend/db/schema.rb
  fi
done
echo "(empty = good)"

echo ""
echo "=== 2. CONFIG-LIKE COLUMNS IN WRONG TABLES ==="
grep -n "root_path\|site_id\|drive_id" backend/db/schema.rb 2>/dev/null | \
  grep -v "storage_configurations" || echo "None found (good)"

echo ""
echo "=== 3. LEGACY PROVIDER-SPECIFIC COLUMNS ==="
grep -n "sharepoint_\|onedrive_\|outlook_" backend/db/schema.rb 2>/dev/null || echo "None found (good)"

echo ""
echo "=== 4. PATH COLUMNS OUTSIDE StorageConfiguration ==="
grep -n "_path\"" backend/db/schema.rb 2>/dev/null | \
  grep -v "storage_configurations\|file_path\|image_path\|avatar_path" || echo "None found (good)"

echo ""
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║           BACKEND AUDIT COMPLETE                                 ║"
echo "╚══════════════════════════════════════════════════════════════════╝"
Common SSoT Violations to Detect
Pattern SSoT Location Red Flag If Found In
root_path StorageConfiguration Any credential or settings table
site_id, drive_id StorageConfiguration.connection_config MicrosoftCredential
client_id, tenant_id MicrosoftCredential StorageConfiguration
*_path columns StorageConfiguration.paths CorporateCompanySetting
bucket, endpoint S3CompatibleCredential StorageConfiguration
Example Backend SSoT Violation Report
SSoT VIOLATION FOUND

I found `root_path` in 3 different tables:

1. backend/db/schema.rb:156 - s3_compatible_credentials
   t.string "root_path", default: ""

2. backend/db/schema.rb:234 - corporate_company_settings
   t.string "storage_root_path"  (legacy)

3. backend/db/schema.rb:412 - storage_configurations
   t.string "root_path"  ← THIS IS THE SSoT

RECOMMENDATION:
- StorageConfiguration.root_path is THE ONE
- Remove duplicate columns via migration
- Update code to read from StorageConfiguration only

Want me to consolidate?

Red Flags to Watch For

Constants & Logic
  • Same constant defined in multiple files
  • Same validation logic in frontend AND backend (pick one)
  • Config in both .env and config/*.yml
  • Two services doing the same transformation
  • Duplicate route definitions
  • Same helper method in multiple places
UI Patterns (NEW)
  • Fullscreen toggle implemented outside TeeemTableView
  • Loading spinners using Lucide icons instead of Spinner
  • Back navigation using router.back() instead of BackButton
  • Custom escape key handlers (should be in component)
  • Modal patterns not using Dialog/Sheet
  • Table implementations not using TeeemTableView

Example SSoT Violation Report

SSoT VIOLATION FOUND

I found fullscreen toggle implemented in 3 places:

1. frontend-next/app/(app)/admin/system/components/ScheduleMasterTab.tsx:328
   const [dataViewFullscreen, setDataViewFullscreen] = useState(false);

2. frontend-next/components/corporate/CorporateStructureTab.tsx:156
   const [isFullscreen, setIsFullscreen] = useState(false);

3. TeeemTableView.tsx - HAS enableFullscreen PROP (THE SSOT)

RECOMMENDATION:
- Use TeeemTableView's enableFullscreen prop
- Remove duplicate implementations
- Tables should not implement their own fullscreen

Want me to consolidate?

Common SSoT Locations in TEEEM

Frontend
Thing SSoT Location
Column types TEEEM_DOCS/GOLD_STANDARD_TABLE.md
UI components frontend-next/lib/component-registry.ts
Validation rules Backend models
Timezone CompanySetting
Loading indicator Spinner from @/components/ui/spinner
Back navigation BackButton from @/components/ui/back-button
Searchable select ComboboxDropdown from @/components/ui/combobox-dropdown
Data tables TeeemTableView from @/components/table/TeeemTableView
Side panels Sheet from @/components/ui/sheet
Modals Dialog from @/components/ui/dialog
Table fullscreen TeeemTableView with enableFullscreen prop
Backend (Data Model)
Thing SSoT Location ❌ NOT Here
Provider type StorageConfiguration.provider_type Hardcoded or guessed
Storage paths StorageConfiguration.paths CorporateCompanySetting (legacy)
Root path StorageConfiguration.root_path Any credential table
Connection config StorageConfiguration.connection_config Spread across credentials
Auth tokens Provider-specific credential model StorageConfiguration
Company settings CompanySetting CorporateCompanySetting (legacy)

Examples

Read the usage examples in the source repository.

View source ↗

Source history

Indexed on
2026-01-20
Index updated
2026-01-26
Branch
main

Index and sync dates describe this directory. View the source repository for code history.

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!