Skip to main content

ADR-187: Lowercase Naming Migration

Status

ACCEPTED - 2026-01-27

Context

CODITECT has accumulated files with inconsistent naming conventions across 97 submodules. The codebase contains:

  • 18,915 files with uppercase characters in filenames
  • 71 submodules requiring migration
  • Multiple naming patterns: PascalCase, camelCase, SCREAMING_SNAKE_CASE, mixed

Problems with Current State

  1. Inconsistency - No standard naming convention across repositories
  2. Git Case Sensitivity - macOS case-insensitive filesystem causes issues with renames
  3. Cross-Repository References - Links between documents may break on rename
  4. Import Statements - Code imports need updating after file renames
  5. Batch Operations - Git index.lock conflicts during bulk operations

Previous Attempts

Initial migration (2026-01-26) successfully renamed 2,387 files in coditect-core but revealed:

  • macOS requires two-step rename (file → temp → lowercase)
  • Git statusline polling creates index.lock conflicts
  • Cross-repository references need separate handling

Decision

Implement a staged multi-submodule migration with the following components:

1. Naming Standard

Target Convention: lowercase-kebab-case

PatternExample BeforeExample After
PascalCaseMyComponent.tsxmy-component.tsx
camelCasemyFunction.jsmy-function.js
SCREAMING_SNAKEAPI_CONFIG.pyapi-config.py
MixedUser_Settings.jsonuser-settings.json

Preserved Uppercase (Conventional):

  • README.md, LICENSE, CHANGELOG.md
  • Makefile, Dockerfile, Jenkinsfile
  • CLAUDE.md, SKILL.md (CODITECT conventions)
  • CONTRIBUTING.md, CODE_OF_CONDUCT.md

2. Migration Architecture

┌─────────────────────────────────────────────────────────────────┐
│ ORCHESTRATION LAYER │
│ orchestrate-full-migration.py │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Submodule │ │Submodule │ │Submodule │ ... │
│ │ A │ │ B │ │ C │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ execute-submodule-migration.py │ │
│ │ 1. Inventory 2. Rename 3. Commit │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ update-cross-repo-references.py │ │
│ │ Fix links between repositories │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

3. Script Components

ScriptPurposeLocation
inventory-all-submodules.pyGenerate comprehensive inventoryscripts/lowercase-migration/
execute-submodule-migration.pyMigrate single submodulescripts/lowercase-migration/
orchestrate-full-migration.pyCoordinate staged rolloutscripts/lowercase-migration/
update-cross-repo-references.pyFix inter-repo linksscripts/lowercase-migration/
execute-rename.pyCore git mv logicscripts/lowercase-migration/
update-references.pyInternal reference updatesscripts/lowercase-migration/
validate-migration.pyValidation checksscripts/lowercase-migration/

4. macOS Case-Insensitive Workaround

# Problem: git mv UPPERCASE.md uppercase.md fails on macOS

# Solution: Two-step rename via temporary file
def git_mv_case_change(old_path, new_path):
temp_path = f"_temp_{old_path}_{timestamp}"

# Step 1: UPPERCASE.md → _temp_UPPERCASE.md_12345
git_mv(old_path, temp_path)

# Step 2: _temp_UPPERCASE.md_12345 → uppercase.md
git_mv(temp_path, new_path)

5. Git Index Lock Handling

# Problem: Statusline git polling creates index.lock

# Solution: Retry with lock removal
def git_mv_with_retry(old, new, max_retries=3):
for attempt in range(max_retries):
remove_lock_file()
time.sleep(0.1)
try:
subprocess.run(['git', 'mv', old, new], check=True)
return True
except CalledProcessError:
continue
return False

6. Staged Rollout Strategy (Option A)

Priority Order:

  1. docs category (documentation, low risk)
  2. tools category (utilities)
  3. gtm category (marketing, non-critical)
  4. ops category (operations)
  5. cloud category (infrastructure)
  6. core category (critical, most complex)
  7. products category (production code)
  8. labs category (experimental, archive last)

Validation Between Stages:

  • Git status clean
  • No uncommitted changes
  • Remaining uppercase files < 10 (exceptions allowed)

Consequences

Positive

  • Consistency - All files follow same naming convention
  • Portability - Works across all OS filesystems
  • Predictability - Developers can guess filenames
  • URL Friendly - Kebab-case works in URLs
  • Searchability - Easier to find files with consistent naming

Negative

  • Breaking Changes - External references may break temporarily
  • Git History - Renames create new git history entries
  • Time Investment - Full migration requires significant coordination
  • Import Updates - Code imports need updating across codebase

Mitigations

  • Cross-Reference Updater - Automated tool to fix links
  • Staged Rollout - One submodule at a time, validate between
  • Dry Run Mode - Preview all changes before execution
  • State Persistence - Resume from last successful submodule
  • Validation - Automated checks after each migration

Implementation

Phase 1: Preparation (Complete)

  • Create inventory script
  • Analyze scope (18,915 files, 71 submodules)
  • Create migration scripts
  • Document process (this ADR)

Phase 2: Pilot Test

  • Run on smallest submodule (e.g., coditect-docs-training)
  • Validate results
  • Fix any issues discovered

Phase 3: Category Rollout

  • Migrate docs category
  • Migrate tools category
  • Migrate gtm category
  • Migrate ops category
  • Migrate cloud category
  • Migrate core category
  • Migrate products category
  • Migrate labs category

Phase 4: Cross-Reference Update

  • Run cross-repository reference updater
  • Validate all links
  • Manual fixes for edge cases

Phase 5: Verification

  • Full codebase scan for uppercase
  • Documentation update
  • Announcement to team

Usage

Generate Inventory

python3 scripts/lowercase-migration/inventory-all-submodules.py
# Output: context-storage/lowercase-migration/inventory-all-submodules.json

Migrate Single Submodule

# Dry run first
python3 scripts/lowercase-migration/execute-submodule-migration.py \
submodules/docs/coditect-docs-training --dry-run

# Execute
python3 scripts/lowercase-migration/execute-submodule-migration.py \
submodules/docs/coditect-docs-training --yes

Full Staged Rollout

# Dry run
python3 scripts/lowercase-migration/orchestrate-full-migration.py --dry-run

# Execute with prompts
python3 scripts/lowercase-migration/orchestrate-full-migration.py

# Automated execution
python3 scripts/lowercase-migration/orchestrate-full-migration.py --yes

# Resume from specific submodule
python3 scripts/lowercase-migration/orchestrate-full-migration.py \
--start-from coditect-cloud-infra

# Single category
python3 scripts/lowercase-migration/orchestrate-full-migration.py \
--category cloud --yes

Update Cross-References

python3 scripts/lowercase-migration/update-cross-repo-references.py --dry-run
python3 scripts/lowercase-migration/update-cross-repo-references.py

Script Locations

All scripts located in: scripts/lowercase-migration/

FileLinesPurpose
inventory-all-submodules.py~275Comprehensive inventory generation
execute-submodule-migration.py~350Single submodule migration
orchestrate-full-migration.py~380Staged rollout orchestration
update-cross-repo-references.py~220Cross-repository link updates
execute-rename.py~250Core rename logic with retry
update-references.py~180Internal reference updates
validate-migration.py~150Migration validation

Changelog

  • 2026-01-27 - Initial ADR created
  • 2026-01-27 - Scripts created and documented

Author: CODITECT Framework Team Track: AM.2 (Lowercase Migration) Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com