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,85 @@
---
name: migrate-convert-linter
description: "[Internal sub-skill of `migrate-orchestrator` (optional, runs only when opted in during phase 1). Do not load directly — load `migrate-orchestrator` first.] Align the project's linter and formatter with the **workspace's** configured tool (whatever it is — ruff, black+isort+flake8, pylint, etc.). Removes project-specific config and consolidates rules into the workspace root."
---

# Skill: migrate-convert-linter

## Goal
Align the project with the **workspace's** linter and formatter. This skill is **not** opinionated about ruff — it reads the workspace's configured tool from the root `pyproject.toml` and aligns the project to that.

## When to Skip
Skip this step if the project's `LINTER` and `FORMATTER` in `migration/<PROJECT>/state.md` already match the workspace's tools.

## Inputs
From `migration/<PROJECT>/state.md`:
- `PROJECT_DIR`
- `LINTER`, `FORMATTER`
- `RUN_TEST_CMD` (optional: `RUN_LINT_CMD`, `RUN_TYPECHECK_CMD`)

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

## Steps

### 0. Identify the workspace's tool
Open the **workspace root** `pyproject.toml` and identify the configured linter and formatter using the same detection table as `migrate-discover` (`[tool.ruff]` → ruff, `[tool.black]` → black, `[tool.flake8]` or `.flake8` → flake8, etc.). Record what you found — every step below refers to "the workspace's linter/formatter" and means **this** tool, not necessarily ruff.

If the workspace has no linter configured at all, stop and ask the user how to proceed (introduce ruff? skip linting alignment? abort the conversion?).

### 1. Remove Project-Specific Configs and Dependencies
- Remove the following sections from the project's `pyproject.toml`:
- `[tool.black]`, `[tool.isort]`, `[tool.flake8]`, `[tool.pylint.*]`, `[tool.autopep8]`, `[tool.pycodestyle]`
- Remove standalone config files: `.flake8`, `.pylintrc`, `.isort.cfg`, and lint sections in `setup.cfg` or `tox.ini`.
- Remove old linter/formatter dependencies from the project's `pyproject.toml`:
- `flake8`, `flake8-*` plugins, `pylint`, `pylint-*` plugins, `black`, `isort`, `autopep8`, `pyflakes`, `pycodestyle`, `bandit`

### 2. Assess Workspace Linting Config
- Review the workspace root's linting and formatting configuration.
- Identify any project-specific rules or ignores that differ from the workspace's standards.

### 3. Merge Project-Specific Rules
- If the project has unique linting rules or ignores, merge them into the workspace root's linting configuration (e.g., `[tool.ruff]`).
- For conflicts (e.g., stricter rules in the project), ask the user to provide guidance on whether to:
- Adopt the project's rules in the workspace.
- Suppress the project's rules in favor of the workspace's.
- Defer the decision and document the conflict in `migration/<PROJECT>/state.md`.

### 4. Run Workspace Linting and Formatting Tools
- Run the workspace's linting tool to assess violations:
- **Few new violations**: Fix them now.
- **Many new violations**: Ask the user whether to fix, suppress, or defer.
- Run the workspace's formatting tool to reformat the code.

### 5. Update `state.md`
- Set `LINTER` and `FORMATTER` to the workspace's tool(s).
- Update `RUN_LINT_CMD` to use the workspace's linting and formatting commands.

## Verify
- The workspace's linting tool passes (or remaining violations are user-approved).
- The workspace's formatting tool passes.
- `RUN_TEST_CMD` succeeds.
- If set, `RUN_TYPECHECK_CMD` succeeds.

## Common failure modes

| Symptom | Likely cause | Remediation |
|---------|--------------|-------------|
| The workspace's linter surfaces hundreds of violations the project's old linter didn't catch | Stricter ruleset; not a "fix everything now" situation. | Ask the user: fix now, suppress via `[tool.<linter>]` ignores in the project subsection, or defer in a follow-up branch. Do **not** auto-fix silently — record the decision in `state.md`. |
| Project-specific lint rules are stricter than the workspace's standard | Project had higher discipline; lowering it would regress quality. | Add the project's rule as a per-path override in the workspace's lint config (most linters support per-directory rule overrides). Do not weaken the rule globally. |
| Old linter config file (`.flake8`, `.pylintrc`, etc.) lingers and confuses developers' local editors | Step 1 missed a config file. | Delete it; mention in the commit message so reviewers update their editor configs. |

## Done When
- No project-specific linter/formatter config files or dependencies remain.
- Project-specific linting rules are merged into the workspace root's configuration.
- `LINTER` and `FORMATTER` in `migration/<PROJECT>/state.md` match the workspace's tools.
- Tests pass via the workspace's tooling.

## Commit

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

```bash
git add -A && git commit -m "migrate(<PROJECT>): phase optional — convert-linter"
```

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.
Loading