Docs / Architect Labs / Lab 19

Lab 19 — Codebase Migration Factory

Migración masiva de código legacy a Python moderno: 8 módulos procesados en paralelo con workers aislados en git worktrees, siguiendo reglas estrictas de migración.

Setup

Nivel: Full-Stack

Duración estimada: 40 minutos. Features: parallel, pipeline, .architect.md, guardrails, reports, dry-run.

bash
mkdir -p ~/architect-labs/lab-19 && cd ~/architect-labs/lab-19
git init && mkdir -p src tests

Crear 8 módulos legacy (dict-based, sin type hints, sin dataclasses)

bash
for module in user product order payment inventory notification shipping analytics; do
cat > "src/${module}_legacy.py" << PYEOF
class ${module^}Manager:
    """Legacy ${module} manager — uses dicts, no type hints, no dataclasses."""

    def __init__(self):
        self.items = []
        self.next_id = 1

    def create(self, data):
        item = dict(data)
        item["id"] = self.next_id
        self.next_id = self.next_id + 1
        self.items.append(item)
        return item

    def get(self, id):
        for item in self.items:
            if item["id"] == id:
                return item
        return None

    def update(self, id, data):
        item = self.get(id)
        if item is None:
            return None
        for key in data:
            item[key] = data[key]
        return item

    def delete(self, id):
        item = self.get(id)
        if item is not None:
            self.items.remove(item)
            return True
        return False

    def list_all(self):
        return list(self.items)

    def search(self, field, value):
        results = []
        for item in self.items:
            if field in item and item[field] == value:
                results.append(item)
        return results

    def count(self):
        return len(self.items)
PYEOF
done

Crear tests para cada módulo

bash
for module in user product order payment inventory notification shipping analytics; do
cat > "tests/test_${module}_legacy.py" << PYEOF
from src.${module}_legacy import ${module^}Manager

def test_create():
    m = ${module^}Manager()
    item = m.create({"name": "test", "value": 42})
    assert item["id"] == 1
    assert item["name"] == "test"

def test_get():
    m = ${module^}Manager()
    m.create({"name": "test"})
    assert m.get(1) is not None
    assert m.get(99) is None

def test_update():
    m = ${module^}Manager()
    m.create({"name": "old"})
    updated = m.update(1, {"name": "new"})
    assert updated["name"] == "new"

def test_delete():
    m = ${module^}Manager()
    m.create({"name": "test"})
    assert m.delete(1) == True
    assert m.get(1) is None

def test_search():
    m = ${module^}Manager()
    m.create({"name": "Alice"})
    m.create({"name": "Bob"})
    results = m.search("name", "Alice")
    assert len(results) == 1
PYEOF
done

Verificar tests

bash
export PYTHONPATH=.
pytest tests/ -v
# Todos deben pasar

Configuración

.architect.md

markdown
# Migration Rules: Legacy Dict -> Modern Dataclass

## OBLIGATORIO
- Convertir todos los dict a @dataclass con type hints
- Usar typing (Optional, List, etc.) donde corresponda
- Añadir docstrings Google-style a clase y métodos públicos
- Usar list comprehensions donde haya for loops simples
- Añadir __repr__ y __str__ a las dataclasses
- Usar Optional[T] para valores que pueden ser None
- Mantener la misma API pública (mismos métodos, mismos params)

## PROHIBIDO
- No cambiar nombres de clases ni métodos
- No cambiar la API pública
- No modificar archivos de test
- No añadir dependencias externas

## VERIFICACION
- Los tests existentes deben pasar sin modificación
- El comportamiento debe ser idéntico

.architect.yaml

yaml
llm:
  model: openai/gpt-4.1
  api_base: http://localhost:4000/v1
  api_key_env: LITELLM_API_KEY

guardrails:
  protected_files:
    - "tests/**"
  max_files_modified: 2

skills:
  auto_discover: true

costs:
  budget_usd: 0.50
bash
git add -A && git commit -m "initial: 8 legacy modules"

Paso 1: Crear manifest

bash
find src/ -name "*_legacy.py" > files-to-migrate.txt
echo "Archivos a migrar: $(wc -l < files-to-migrate.txt)"
cat files-to-migrate.txt

Paso 2: Dry run

bash
architect parallel "Migra este módulo legacy a código moderno \
  siguiendo las reglas de .architect.md. Convierte dicts a dataclasses, \
  añade type hints, y mantén la API pública." \
  --manifest files-to-migrate.txt \
  --workers 1 \
  --dry-run

Consejo

Siempre haz dry-run con --workers 1 primero. Esto valida que la migración funciona correctamente con un solo archivo antes de escalar a 4+ workers.

Paso 3: Ejecutar migración

bash
architect parallel "Migra este módulo legacy a código moderno \
  siguiendo las reglas de .architect.md. Convierte dicts a dataclasses, \
  añade type hints y docstrings." \
  --manifest files-to-migrate.txt \
  --workers 4 \
  --config .architect.yaml \
  --confirm-mode yolo \
  --report-file reports/migration.json

Paso 4: Verificar

bash
# Todos los tests deben pasar
pytest tests/ -v

# Verificar que se usan dataclasses
for f in src/*_legacy.py; do
    echo "=== $f ==="
    grep -c "dataclass" "$f" || echo "  sin dataclass"
    grep -c "->" "$f" || echo "  sin type hints"
done

# Ver reporte
python3 -c "
import json
r = json.load(open('reports/migration.json'))
for res in r.get('results', []):
    status = 'OK' if res.get('success') else 'FAIL'
    print(f'{status} {res[\"file\"]}')
"

Importante

Si algún módulo falla la migración, puedes re-ejecutar el parallel solo con los archivos fallidos creando un nuevo manifest con esos archivos específicos.

Paso 5: Crear PR de migración

bash
git checkout -b migration/legacy-to-modern
git add -A
git commit -m "refactor: migrate 8 legacy modules to modern Python

- Dicts to dataclasses with type hints
- Added docstrings (Google-style)
- List comprehensions where applicable
- All tests pass without modification"

Resumen

PasoQué hace
ManifestLista de archivos a procesar
Dry runPreview sin cambios
Parallel4 workers procesan en paralelo
VerifyTests pasan, dataclasses presentes

Siguiente lab

Lab 20: QA Bug Triage Auto-Fix — Bug reportado en issue tracker, Architect lo corrige automáticamente.

END OF DOCUMENT

¿Necesitas más? Volver a la Librería →