# Polylith Migrate Split Component Internals

> [Internal sub-skill of `polylith-migrate-orchestrator`. Do not load directly — load `polylith-migrate-orchestrator` first, which drives all phases.] Split monolithic `core.py` files in shared components into domain-focused modules.

- Skill: `davidvujic/polylith-migrate-split-component-internals` (Agent Skill)
- Install (CLI): `npx skillmds@latest add davidvujic/polylith-migrate-split-component-internals`
- Raw SKILL.md: https://api.skillmd.com/api/skills/davidvujic/polylith-migrate-split-component-internals/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: davidvujic (https://skillmd.com/u/davidvujic)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/davidvujic/polylith-migrate-split-component-internals

---


# Skill: polylith-migrate-split-component-internals

> 📐 **Scope vs sibling skills.** This skill operates **inside one already-extracted component**, splitting its `core.py` into multiple sibling Python files. **No new components are created** — only the internal file layout changes. Don't confuse with:
> - `polylith-migrate-split-big-component` — splits **one component into multiple components**. Use that when the unit being broken up is a component, not a file.
> - `polylith-migrate-isolate-shared-and-project-logic` — separates shared vs project-specific code **across components and projects**; may create new components.
> - `polylith-migrate-extract-standalone-modules` — pulls foundational modules out of the residual big component into new standalone components.

## Goal
Split monolithic `core.py` files in **shared components** (e.g., `models_shared`, `schemas_shared`, or similar) into domain-focused modules. This skill ensures that shared components remain well-organized and maintainable.

## Inputs
From `migration/<PROJECT>/state.md`:
- `TARGET_TOP_NS`
- Verification commands.

From `migration/<PROJECT>/manifest.md`:
- Current component list and structure.

> All inputs from `state.md` are assumed to satisfy the validation rules in `polylith-migrate-discover` (`### Validation rules`). Validate before proceeding.

## Steps

### 1. Identify Candidates
- Scan components for large `core.py` files.
- A component is a candidate if:
  - The file contains definitions from multiple domains.
  - The file contains helper/utility functions alongside class definitions.
  - The file exceeds a reasonable size threshold.

### 2. Group Definitions by Domain
- Group definitions by the domain concept they serve.
- Example domains: ORM models, schema/dataclass clusters, helper functions.

### 3. Create New Modules
- Create domain-focused modules (e.g., `merchant.py`, `transaction.py`).
- Move relevant definitions from `core.py` to the new modules.

### 4. Update `__init__.py`
- Re-export public names from the new modules in `__init__.py`.

### 5. Handle `core.py`
- Delete `core.py` if all definitions have been moved.
- Keep `core.py` if it serves as a composition point.

## Verify
- `RUN_TEST_CMD` succeeds.
- If set, `RUN_LINT_CMD` and `RUN_TYPECHECK_CMD` succeed.

## Common failure modes

| Symptom | Likely cause | Remediation |
|---------|--------------|-------------|
| `core.py` is small (<100 lines) but mixes two domains | The component itself is too small to warrant an internal split. | Leave it. Splitting adds indirection without benefit at this size; revisit when the file grows. |
| After splitting, an import like `from <ns>.<component> import <symbol>` fails | `__init__.py` was not updated to re-export the symbol from its new module. | Add `from <ns>.<component>.<new_module> import <symbol>` to `__init__.py`. The component's public API must remain stable across the split. |
| New files inside the component now circularly import each other (e.g., `models/user.py` ↔ `models/transaction.py`) | Domain split was too aggressive; the two files genuinely share a concept. | Extract the shared concept into a third file (e.g., `models/_base.py`) and have both depend on it. |

## Commit

After verification passes, commit this phase to the migration branch:

```bash
git add -A && git commit -m "migrate(<PROJECT>): phase <N> — split-component-internals"
```

Substitute `<PROJECT>`, `<N>`, and `<phase-name>` from `state.md` and the orchestrator's phase table. Do not proceed to the next phase without a clean commit — the per-phase commit is the rollback point for the next phase's failure-mode tables.
