Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .agents/skills/polylith/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@

> **Note for contributors:** this README is a **human reference**. The agent loads each `*/SKILL.md` independently via the skill loader; this file is **not** auto-loaded with any skill. Anything an agent must know to act has to live in the relevant `SKILL.md` itself, not here.

## Available Skills
## Skill loading model

Two kinds of skill live under this directory; the distinction matters when picking an entry point:

- **Atomic skills (`polylith-*`).** Each maps to one `poly` CLI command (or one focused concept). Safe to load in isolation; individually composable. These cover everyday Polylith workflows — creating bricks, syncing, checking, inspecting, and so on.
- **Orchestrated skill set (`migrate-project/migrate-*`).** A multi-phase workflow with shared state (`migration/<PROJECT>/state.md`) and a git safety net. **Never load an individual `migrate-*` skill directly** — always load `migrate-orchestrator` and let it drive the phases in order. See [`migrate-project/README.md`](./migrate-project/README.md). This is an advanced, explicit-opt-in workflow used for migrating a **non-Polylith** project into a Polylith workspace, **not** part of daily Polylith use.

## Available Skills (daily Polylith workflows)

| Skill | Command | Purpose |
|---------------------------|--------------------|----------------------------------------------------------------------------------------------------------|
Expand All @@ -15,8 +22,13 @@
| [Sync](./polylith-sync/SKILL.md) | `poly sync` | Update each project's brick list to match actual imports. |
| [Workspace Inspection](./polylith-workspace-inspection/SKILL.md) | `poly info` | Show brick × project usage (which projects use which bricks). |
| [Dependency Visualization](./polylith-dependency-visualization/SKILL.md) | `poly deps` | Show brick × brick dependencies and interface compliance. |
| [Dependency Management](./polylith-dependency-management/SKILL.md) | — | Add or manage third-party libraries for a brick or project. |
| [Testing](./polylith-testing/SKILL.md) | `poly test diff` | List bricks/projects affected by **test-code** changes since a tag. |
| [Diff](./polylith-diff/SKILL.md) | `poly diff` | List bricks whose **implementation** changed since a tag. |
| [Check](./polylith-check/SKILL.md) | `poly check` | Validate the workspace (CI gate; exits 1 on failure). |
| [Libs](./polylith-libs/SKILL.md) | `poly libs` | Inspect third-party libraries per project. |
| [Concepts](./polylith-concepts/SKILL.md) | — | Provides foundational knowledge about Polylith architecture and terminology. |
| [Concepts](./polylith-concepts/SKILL.md) | — | Foundational knowledge about Polylith architecture and terminology. |

## Advanced workflow

For migrating an existing **non-Polylith** Python project into a Polylith workspace, see [`migrate-project/README.md`](./migrate-project/README.md). This is a destructive, multi-phase, explicit-opt-in workflow — start with the `migrate-orchestrator` skill, not any individual `migrate-*` sub-skill.
111 changes: 111 additions & 0 deletions .agents/skills/polylith/migrate-project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Project Migration Skills

> **Note for contributors:** this README is a **human reference** and a skill **index**. Agents load each `migrate-*/SKILL.md` independently via the skill loader; this README is **not** auto-loaded with any skill. Anything an agent must know to act has to live in the relevant `SKILL.md` itself, not here.

This directory contains skills for migrating **non-Polylith Python projects** into a Polylith workspace. They cooperate via two artifacts under `migration/<PROJECT>/`:

- `state.md` — a flat `KEY=value` file. Canonical schema lives in [`migrate-discover/SKILL.md`](./migrate-discover/SKILL.md).
- `manifest.md` — a human-readable structural inventory of the source project.

---

## ⚠️ When to use these skills

**Only** when:
1. A human has **explicitly instructed** to migrate a specific project (e.g., "migrate `projects/my-app` to Polylith").
2. The target project lives under `projects/<PROJECT>/` of this Polylith workspace.
3. The goal is to refactor the project into Polylith bricks (bases and components).

**Do not use** for:
- Automated or unattended migrations.
- Projects that are already structured as Polylith bricks.
- Daily Polylith development tasks — for those, see the sibling `polylith-*` skills.

---

## How to invoke

Load the orchestrator and let it drive the rest:

```
Load the `migrate-orchestrator` skill and migrate `projects/<project-name>`.
```

The orchestrator will:
1. Ask the user for explicit confirmation.
2. Establish a git safety net (dedicated branch + per-phase commits).
3. Load and execute each phase skill in order, verifying after each.

> **Why every sub-skill says "do not load directly".** Each `migrate-<phase>` skill's `description:` starts with a redirect to `migrate-orchestrator`. This is intentional: it makes the orchestrator the only valid entry point regardless of which sub-skill the agent's fuzzy-match initially favours. The sub-skills depend on state (`migration/<PROJECT>/state.md`) and a git safety net that only the orchestrator sets up.

---

## Downstream installation

When this skill set is installed into another Polylith workspace (e.g. via a skills package), the in-skill `[ENTRY POINT]` / `[Internal sub-skill of migrate-orchestrator …]` markers in each `description:` are the primary routing signal — they ship with the package.

For an extra-strong signal, downstream consumers should add the following snippet to their own repo-level `AGENTS.md` (or equivalent agent-routing file). It is **not** required — the in-skill markers are usually sufficient — but it removes any ambiguity for agents that read `AGENTS.md` before scanning skill descriptions.

```markdown
## Polylith migration instructions

When the user asks to migrate a non-Polylith Python project to Polylith
(e.g. "migrate `projects/<name>` to Polylith"), load the
`migrate-orchestrator` skill first and let it drive the workflow.

Never load `migrate-discover`, `migrate-extract-to-base`, or any other
`migrate-*` sub-skill directly — they are phases the orchestrator
invokes in order, with per-phase verification and git checkpoints
between them.
```

---

## Workflow at a glance

| # | Phase | Skill | Depends on |
|---|----------------------------------------|------------------------------------------------|---------------------------------------------------------------------|
| — | Orchestration | [`migrate-orchestrator`](./migrate-orchestrator/SKILL.md) | — |
| 1 | Discover | [`migrate-discover`](./migrate-discover/SKILL.md) | — |
| 2 | Extract to base | [`migrate-extract-to-base`](./migrate-extract-to-base/SKILL.md) | `migrate-discover` |
| 3 | Prepare project | [`migrate-prepare-project`](./migrate-prepare-project/SKILL.md) | `migrate-extract-to-base` |
| 4 | Isolate base and big component | [`migrate-isolate-base-and-big-component`](./migrate-isolate-base-and-big-component/SKILL.md) | `migrate-prepare-project` |
| 5 | Split big component | [`migrate-split-big-component`](./migrate-split-big-component/SKILL.md) | `migrate-isolate-base-and-big-component` |
| 6 | Extract standalone modules | [`migrate-extract-standalone-modules`](./migrate-extract-standalone-modules/SKILL.md) | `migrate-split-big-component` |
| 7 | Isolate shared and project logic | [`migrate-isolate-shared-and-project-logic`](./migrate-isolate-shared-and-project-logic/SKILL.md) | `migrate-extract-standalone-modules`, `migrate-split-big-component` |
| 8 | Distribute wiring | [`migrate-distribute-wiring`](./migrate-distribute-wiring/SKILL.md) | `migrate-isolate-shared-and-project-logic` |
| 9 | Split component internals | [`migrate-split-component-internals`](./migrate-split-component-internals/SKILL.md) | `migrate-distribute-wiring` |
|10 | Refactor tests | [`migrate-refactor-tests`](./migrate-refactor-tests/SKILL.md) | `migrate-split-component-internals` |
|11 | Definition of done | [`migrate-definition-of-done`](./migrate-definition-of-done/SKILL.md) | `migrate-refactor-tests` |

### Optional skills (triggered during `migrate-discover`)

| Skill | Purpose | Trigger / dependency |
|-------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
| [`migrate-convert-linter`](./migrate-convert-linter/SKILL.md) | Align the project's linter/formatter with the **workspace's** configured tool. | `CONVERT_LINTER=yes` in `state.md`. Runs between phase 1 and phase 2. |
| [`migrate-convert-type-checker`](./migrate-convert-type-checker/SKILL.md) | Align the project's type checker with the **workspace's** configured tool. | `CONVERT_TYPE_CHECKER=yes` in `state.md`. Runs between phase 1 and phase 2. |
| [`migrate-convert-package-manager`](./migrate-convert-package-manager/SKILL.md) | Convert the project's `pyproject.toml` to uv workspaces. **Opinionated about uv** — only run when the workspace itself uses uv. | `CONVERT_PACKAGE_MANAGER=yes` in `state.md`. Runs between phase 1 and phase 2. |
| [`migrate-dedupe`](./migrate-dedupe/SKILL.md) | Identify and apply controlled deduplication discovered during refactoring. | User approval. Runs after phase 5 or phase 6. |

---

## Scope of the four "splitting" skills

These skills overlap in vocabulary but address different scopes. Use this matrix to decide which one applies:

| Skill | Scope | Trigger |
|---------------------------------------------|------------------------------------------------|---------------------------------------------------------------------------|
| `migrate-split-big-component` | Within one project; component → multiple components. | The temporary big component from phase 4 is too large. |
| `migrate-extract-standalone-modules` | Within one project; pulls foundational modules out of the residual. | Residual still contains `consts.py`/`exceptions.py`/`models.py`. |
| `migrate-split-component-internals` | Within one already-extracted shared component; `core.py` → multiple files. | A component's `core.py` mixes multiple domains internally. |
| `migrate-isolate-shared-and-project-logic` | Cross-project; separate shared vs project-specific in components used by ≥ 2 projects. | Migrating a 2nd+ project that overlaps with an already-extracted one. |

> 💡 In a fresh migration of a single project, you usually run `migrate-split-big-component` → `migrate-extract-standalone-modules` → `migrate-split-component-internals`, and skip `migrate-isolate-shared-and-project-logic` until a second project is migrated.

---

## Files in this directory

- `README.md` — this file (human reference + index).
- `migrate-orchestrator/SKILL.md` — entry point; defines the phase order and the git safety net.
- `migrate-<phase>/SKILL.md` — one per phase listed above.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: migrate-analyze-imports
description: Analyze the project's import graph to identify files importing from the original namespace, potential circular imports, and symbols exported by the original namespace.
---

# Skill: migrate-analyze-imports

## Goal
Analyze the project's import graph to identify:
1. All files importing from the original namespace
2. Potential circular imports
3. Symbols exported by the original namespace

This information is used to guide the namespace migration and generate a compatibility shim.

## Inputs
- Project name (from `migration/<project-name>/state.md`)
- Original namespace (from `migration/<project-name>/state.md`)

## Steps

### 1. Identify files importing from the original namespace
1. Search for `from ${ORIG_TOP_NS} import` and `import ${ORIG_TOP_NS}` in all Python files in the project.
2. Record the file paths and import statements in `migration/${PROJECT}/import_analysis.md`.

### 2. Identify potential circular imports
1. Manually inspect the import graph to detect circular dependencies between the original namespace and the new base location.
2. Record any circular import chains in `migration/${PROJECT}/import_analysis.md`.

### 3. List symbols exported by the original namespace
1. Inspect the original namespace's `__init__.py` (typically at `projects/${PROJECT}/src/${ORIG_TOP_NS}/__init__.py` or `projects/${PROJECT}/${ORIG_TOP_NS}/__init__.py`) to list all public symbols (those not starting with `_`).
2. Record the exported symbols in `migration/${PROJECT}/import_analysis.md`.

## Output
- A report file: `migration/<project-name>/import_analysis.md` with:
- Files importing from the original namespace
- Circular import chains (if any)
- Symbols exported by the original namespace

## Verify
1. Confirm that `migration/<project-name>/import_analysis.md` exists and is not empty.
2. Verify that the report includes:
- A list of files importing from the original namespace
- Any circular import chains
- Symbols exported by the original namespace

## Commit
```bash
git add migration/${PROJECT}/import_analysis.md
git commit -m "migrate(${PROJECT}): phase 2 — analyze-imports"
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: migrate-automate-import-updates
description: Update imports in the new base location to reference the new namespace instead of the original namespace.
---

# Skill: migrate-automate-import-updates

## Goal
Update imports in the new base location to reference the new namespace instead of the original namespace, ensuring that the codebase remains functional after the namespace migration.

## Inputs
- Project name (from `migration/<project-name>/state.md`)
- Original namespace (from `migration/<project-name>/state.md`)
- New namespace (from `migration/<project-name>/state.md`)
- Import analysis report (from `migration/<project-name>/import_analysis.md`)

## Steps

### 1. Identify files in the new base location importing from the original namespace
1. Review the import analysis report to identify files in the new base location (at `bases/${TARGET_TOP_NS}/${INITIAL_BASE_NAME}/`) that import from the original namespace.

### 2. Update imports to reference the new namespace
1. For each file in the new base location that imports from the original namespace:
- Replace `from ${ORIG_TOP_NS} import ...` with `from ${TARGET_TOP_NS}.${INITIAL_BASE_NAME}.<module> import ...`
- Replace `import ${ORIG_TOP_NS}` with `import ${TARGET_TOP_NS}.${INITIAL_BASE_NAME}`

Example:
```python
# Before
from myproject.core import MyClass
import myproject.utils

# After
from mynamespace.mybase.core import MyClass
import mynamespace.mybase.utils
```

### 3. Record updated files
1. Record all updated files in `migration/${PROJECT}/import_updates.md`.

## Output
- Updated files in the new base location
- A report file: `migration/<project-name>/import_updates.md` listing all updated files

## Verify
1. Confirm that all files listed in `migration/<project-name>/import_updates.md` have been updated.
2. Check that no files in the new base location import from the original namespace.
3. Verify that the codebase remains functional by running the test command from `migration/<project-name>/state.md`.

## Commit
```bash
git add bases/${TARGET_TOP_NS}/${INITIAL_BASE_NAME}/
git add migration/${PROJECT}/import_updates.md
git commit -m "migrate(${PROJECT}): phase 5 — automate-import-updates"
```
Loading