Orchestrata Ultimate › Plans › codemod-engine-briefs › BRIEF-W0

BRIEF-W0: Scaffold (Haiku Agent)

Source: plans/codemod-engine-briefs/BRIEF-W0.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-27 · 283 lines.

Prose pending.

Plan text

BRIEF-W0: Scaffold (Haiku Agent)

Wave Overview

Wave: W0 (Scaffold)
Agent: Haiku (fast, cheap, mechanical tasks)
Duration: ~15 minutes
Dependencies: None (first wave)
Parallel Execution: No (single agent)

Objective

Generate the foundational skeleton code for the codemod engine using the gen-skeleton tool and the Mermaid class diagram contract. This wave produces the data structures, protocols, and class stubs that all subsequent waves will implement.

Scope

Files to Generate

  1. src/orchestrata_ultimate/refactor/codemod/report.py (~150 LOC)

    • ChangeEntry dataclass
    • ChangeSet dataclass
    • Finding dataclass
    • WorkspaceStats dataclass
    • CommitReport dataclass
    • CodemodEvent dataclass
  2. src/orchestrata_ultimate/refactor/codemod/observability/events.py (~100 LOC)

    • CodemodEventType enum
    • Event type constants
  3. src/orchestrata_ultimate/refactor/codemod/persistence/repository.py (~150 LOC)

    • CodemodGraphRepository Protocol
    • CodemodRun dataclass
    • CodemodPass dataclass
    • CodemodFinding dataclass
    • CodeChange dataclass
  4. src/orchestrata_ultimate/refactor/codemod/__init__.py (~50 LOC)

    • Public API exports
  5. tests/refactor/codemod/conftest.py (~200 LOC)

    • Shared fixtures for all codemod tests
    • codemod_repo fixture (git repo with Python files)
    • sample_workspace fixture (pre-loaded workspace)
    • sample_changes fixture (sample ChangeSet)

Files NOT to Generate

Instructions

Step 1: Add Dependencies

cd ~/workspace/wt-QWEN
uv add libcst xxhash

Verify installation:

uv run python -c "import libcst; import xxhash; print('OK')"

Step 2: Generate Skeletons from Mermaid Contract

uv run python scripts/serialize_codebase_ast.py gen-skeleton \
  --input plans/contracts/spec-110-codemod-engine.mmd \
  --output src/orchestrata_ultimate/refactor/codemod/ \
  --format python

This will generate skeleton files with:

Step 3: Split Monolithic Output

The gen-skeleton tool may produce a single monolithic file. Split it into the module structure:

# If gen-skeleton produces codemod.py, split it:
uv run python scripts/split_skeleton.py \
  --input src/orchestrata_ultimate/refactor/codemod/codemod.py \
  --output-dir src/orchestrata_ultimate/refactor/codemod/ \
  --mapping plans/contracts/skeleton-mapping.json

The skeleton-mapping.json file maps class names to module paths:

{
  "ChangeEntry": "report.py",
  "ChangeSet": "report.py",
  "Finding": "report.py",
  "WorkspaceStats": "report.py",
  "CommitReport": "report.py",
  "CodemodEvent": "report.py",
  "CodemodEventType": "observability/events.py",
  "CodemodGraphRepository": "persistence/repository.py",
  "CodemodRun": "persistence/repository.py",
  "CodemodPass": "persistence/repository.py",
  "CodemodFinding": "persistence/repository.py",
  "CodeChange": "persistence/repository.py"
}

Step 4: Create Package Structure

mkdir -p src/orchestrata_ultimate/refactor/codemod/analysis
mkdir -p src/orchestrata_ultimate/refactor/codemod/observability
mkdir -p src/orchestrata_ultimate/refactor/codemod/persistence

touch src/orchestrata_ultimate/refactor/codemod/analysis/__init__.py
touch src/orchestrata_ultimate/refactor/codemod/observability/__init__.py
touch src/orchestrata_ultimate/refactor/codemod/persistence/__init__.py

Step 5: Write conftest.py

Create tests/refactor/codemod/conftest.py with shared fixtures:

"""Shared fixtures for codemod engine tests."""

import pytest
from pathlib import Path
from orchestrata_ultimate.refactor.codemod.workspace import CodemodWorkspace
from orchestrata_ultimate.refactor.codemod.report import ChangeSet, ChangeEntry
import libcst as cst


@pytest.fixture
def codemod_repo(tmp_path: Path) -> Path:
    """Create a git repo with sample Python files."""
    repo = tmp_path / "repo"
    repo.mkdir()
    
    # Create src/ directory with sample modules
    src = repo / "src"
    src.mkdir()
    
    # Create sample Python files
    (src / "module_a.py").write_text("""
def function_a():
    pass

class ClassA:
    def method_a(self):
        pass
""")
    
    (src / "module_b.py").write_text("""
from module_a import function_a, ClassA

def function_b():
    function_a()
    obj = ClassA()
    obj.method_a()
""")
    
    # Initialize git repo
    import subprocess
    subprocess.run(["git", "init"], cwd=repo, check=True, capture_output=True)
    subprocess.run(["git", "config", "user.email", "test@example.com"], cwd=repo, check=True, capture_output=True)
    subprocess.run(["git", "config", "user.name", "Test User"], cwd=repo, check=True, capture_output=True)
    subprocess.run(["git", "add", "."], cwd=repo, check=True, capture_output=True)
    subprocess.run(["git", "commit", "-m", "Initial commit"], cwd=repo, check=True, capture_output=True)
    
    return repo


@pytest.fixture
def sample_workspace(codemod_repo: Path) -> CodemodWorkspace:
    """Create a pre-loaded workspace."""
    return CodemodWorkspace.load(codemod_repo, include=("src",))


@pytest.fixture
def sample_changes(sample_workspace: CodemodWorkspace) -> ChangeSet:
    """Create a sample ChangeSet with one modified file."""
    # Get a module from the workspace
    module_path = "src/module_a.py"
    original_tree = sample_workspace.forest[module_path]
    
    # Create a modified tree (e.g., rename function_a to function_renamed)
    # This is a placeholder - actual implementation will be in W2
    modified_tree = original_tree  # TODO: Apply actual transformation
    
    entry = ChangeEntry(
        path=module_path,
        original_tree=original_tree,
        mutated_tree=modified_tree,
        pass_name="SamplePass"
    )
    
    return ChangeSet(entries=(entry,))

Step 6: Verify Skeleton Code

# Check that all skeleton files exist
ls -la src/orchestrata_ultimate/refactor/codemod/*.py
ls -la src/orchestrata_ultimate/refactor/codemod/*/__init__.py

# Check that skeleton code is syntactically valid
uv run python -m py_compile src/orchestrata_ultimate/refactor/codemod/report.py
uv run python -m py_compile src/orchestrata_ultimate/refactor/codemod/observability/events.py
uv run python -m py_compile src/orchestrata_ultimate/refactor/codemod/persistence/repository.py

# Check that skeleton code can be imported
uv run python -c "from orchestrata_ultimate.refactor.codemod.report import ChangeEntry, ChangeSet, Finding"

# Check that @traces decorators are present
grep -n "@traces" src/orchestrata_ultimate/refactor/codemod/report.py

Step 7: Run Gate 0 (Smoke Test)

# Verify that all skeleton classes can be instantiated (with dummy data)
uv run python -c "
from orchestrata_ultimate.refactor.codemod.report import ChangeEntry, ChangeSet, Finding
from orchestrata_ultimate.refactor.codemod.observability.events import CodemodEventType, CodemodEvent
from orchestrata_ultimate.refactor.codemod.persistence.repository import CodemodRun, CodemodPass

# Try to instantiate each class (will fail if signatures are wrong)
print('ChangeEntry:', ChangeEntry.__init__.__annotations__)
print('ChangeSet:', ChangeSet.__init__.__annotations__)
print('Finding:', Finding.__init__.__annotations__)
print('CodemodEvent:', CodemodEvent.__init__.__annotations__)
print('CodemodRun:', CodemodRun.__init__.__annotations__)
print('All skeleton classes can be instantiated!')
"

Success Criteria

Deliverables

  1. src/orchestrata_ultimate/refactor/codemod/report.py (skeleton)
  2. src/orchestrata_ultimate/refactor/codemod/observability/events.py (skeleton)
  3. src/orchestrata_ultimate/refactor/codemod/persistence/repository.py (skeleton)
  4. src/orchestrata_ultimate/refactor/codemod/__init__.py (exports)
  5. src/orchestrata_ultimate/refactor/codemod/analysis/__init__.py (empty)
  6. src/orchestrata_ultimate/refactor/codemod/observability/__init__.py (empty)
  7. src/orchestrata_ultimate/refactor/codemod/persistence/__init__.py (empty)
  8. tests/refactor/codemod/conftest.py (shared fixtures)

Handoff to W1

W1 (Forest + Sentinel) will implement:

W1 agents will use the skeleton data structures from W0 (ChangeEntry, ChangeSet, Finding, etc.) and implement the actual logic.

Notes