polylith-cli 1.47.1__tar.gz → 1.48.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/PKG-INFO +1 -1
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/README.md +12 -14
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/README.md +111 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-analyze-imports/SKILL.md +99 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-automate-import-updates/SKILL.md +76 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-convert-linter/SKILL.md +85 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-convert-package-manager/SKILL.md +104 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-convert-type-checker/SKILL.md +83 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-dedupe/SKILL.md +118 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-definition-of-done/SKILL.md +95 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-detect-circular-imports/SKILL.md +48 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-discover/SKILL.md +274 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-distribute-wiring/SKILL.md +79 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-extract-standalone-modules/SKILL.md +65 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-extract-to-base/SKILL.md +84 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-generate-shim/SKILL.md +63 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-isolate-base-and-big-component/SKILL.md +103 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-isolate-shared-and-project-logic/SKILL.md +93 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-orchestrator/SKILL.md +188 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-prepare-project/SKILL.md +107 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-refactor-tests/SKILL.md +121 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-resolve-circular-imports/SKILL.md +57 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-split-big-component/SKILL.md +193 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-split-component-internals/SKILL.md +70 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-update-tests/SKILL.md +69 -0
- polylith_cli-1.48.0/polylith_cli/.agents/skills/polylith/migrate-project/migrate-verify-stability/SKILL.md +58 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/pyproject.toml +1 -1
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/README.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-base-creation/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-brick-removal/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-check/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-component-creation/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-concepts/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-dependency-management/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-dependency-visualization/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-diff/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-libs/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-project-management/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-sync/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-testing/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-workspace-inspection/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/.agents/skills/polylith/polylith-workspace-setup/SKILL.md +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/alias/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/alias/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/bricks/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/bricks/base.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/bricks/brick.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/bricks/component.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/building/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/building/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/building/paths.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/check/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/check/collect.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/check/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/__main__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/build.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/create.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/env.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/options.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/cli/test.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/check.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/create.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/deps.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/diff.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/info.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/libs.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/sync.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/commands/test.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/configuration/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/configuration/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/deps/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/deps/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/deps/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/development/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/development/development.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/diff/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/diff/collect.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/diff/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/dirs/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/dirs/dirs.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/distributions/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/distributions/caching.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/distributions/collect.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/distributions/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/environment/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/environment/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/files/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/files/files.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/imports/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/imports/grouping.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/imports/parser.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/imports/usages.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/info/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/info/collect.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/info/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interactive/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interactive/project.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interface/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interface/collect.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interface/interfaces.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interface/parser.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interface/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/interface/usage.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/libs/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/libs/grouping.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/libs/lock_files.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/libs/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/libs/stdlib.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/output/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/output/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/parsing/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/parsing/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/parsing/rewrite.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/project/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/project/create.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/project/get.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/project/parser.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/project/templates.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/readme/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/readme/readme.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/repo/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/repo/get.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/repo/repo.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/reporting/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/reporting/theme.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/sync/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/sync/collect.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/sync/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/sync/update.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/test/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/test/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/test/report.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/test/tests.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/toml/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/toml/core.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/workspace/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/workspace/create.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/workspace/paths.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/yaml/__init__.py +0 -0
- {polylith_cli-1.47.1 → polylith_cli-1.48.0}/polylith_cli/polylith/yaml/core.py +0 -0
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
> **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.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Skill loading model
|
|
7
|
+
|
|
8
|
+
Two kinds of skill live under this directory; the distinction matters when picking an entry point:
|
|
9
|
+
|
|
10
|
+
- **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.
|
|
11
|
+
- **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.
|
|
12
|
+
|
|
13
|
+
## Available Skills (daily Polylith workflows)
|
|
7
14
|
|
|
8
15
|
| Skill | Command | Purpose |
|
|
9
16
|
|---------------------------|--------------------|----------------------------------------------------------------------------------------------------------|
|
|
@@ -15,22 +22,13 @@
|
|
|
15
22
|
| [Sync](./polylith-sync/SKILL.md) | `poly sync` | Update each project's brick list to match actual imports. |
|
|
16
23
|
| [Workspace Inspection](./polylith-workspace-inspection/SKILL.md) | `poly info` | Show brick × project usage (which projects use which bricks). |
|
|
17
24
|
| [Dependency Visualization](./polylith-dependency-visualization/SKILL.md) | `poly deps` | Show brick × brick dependencies and interface compliance. |
|
|
25
|
+
| [Dependency Management](./polylith-dependency-management/SKILL.md) | — | Add or manage third-party libraries for a brick or project. |
|
|
18
26
|
| [Testing](./polylith-testing/SKILL.md) | `poly test diff` | List bricks/projects affected by **test-code** changes since a tag. |
|
|
19
27
|
| [Diff](./polylith-diff/SKILL.md) | `poly diff` | List bricks whose **implementation** changed since a tag. |
|
|
20
28
|
| [Check](./polylith-check/SKILL.md) | `poly check` | Validate the workspace (CI gate; exits 1 on failure). |
|
|
21
29
|
| [Libs](./polylith-libs/SKILL.md) | `poly libs` | Inspect third-party libraries per project. |
|
|
22
|
-
| [Concepts](./polylith-concepts/SKILL.md) | — |
|
|
23
|
-
|
|
24
|
-
---
|
|
30
|
+
| [Concepts](./polylith-concepts/SKILL.md) | — | Foundational knowledge about Polylith architecture and terminology. |
|
|
25
31
|
|
|
26
|
-
##
|
|
32
|
+
## Advanced workflow
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
2. **Understand the basics** — [Concepts](./concepts/SKILL.md).
|
|
30
|
-
3. **Create bricks** — [Component Creation](./component_creation/SKILL.md) and [Base Creation](./base_creation/SKILL.md).
|
|
31
|
-
4. **Create deployable projects** — [Project Management](./project_management/SKILL.md).
|
|
32
|
-
5. **Remove bricks safely** — [Brick Removal](./brick_removal/SKILL.md).
|
|
33
|
-
6. **Sync brick usage** — [Sync](./sync/SKILL.md).
|
|
34
|
-
7. **Inspect** — [Workspace Inspection](./workspace_inspection/SKILL.md) (brick × project) and [Dependency Visualization](./dependency_visualization/SKILL.md) (brick × brick).
|
|
35
|
-
8. **Validate** — [Check](./check/SKILL.md) (CI gate) and [Libs](./libs/SKILL.md) (library inspection).
|
|
36
|
-
9. **Diff between releases** — [Diff](./diff/SKILL.md) and [Testing](./testing/SKILL.md).
|
|
34
|
+
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.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Project Migration Skills
|
|
2
|
+
|
|
3
|
+
> **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.
|
|
4
|
+
|
|
5
|
+
This directory contains skills for migrating **non-Polylith Python projects** into a Polylith workspace. They cooperate via two artifacts under `migration/<PROJECT>/`:
|
|
6
|
+
|
|
7
|
+
- `state.md` — a flat `KEY=value` file. Canonical schema lives in [`migrate-discover/SKILL.md`](./migrate-discover/SKILL.md).
|
|
8
|
+
- `manifest.md` — a human-readable structural inventory of the source project.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ⚠️ When to use these skills
|
|
13
|
+
|
|
14
|
+
**Only** when:
|
|
15
|
+
1. A human has **explicitly instructed** to migrate a specific project (e.g., "migrate `projects/my-app` to Polylith").
|
|
16
|
+
2. The target project lives under `projects/<PROJECT>/` of this Polylith workspace.
|
|
17
|
+
3. The goal is to refactor the project into Polylith bricks (bases and components).
|
|
18
|
+
|
|
19
|
+
**Do not use** for:
|
|
20
|
+
- Automated or unattended migrations.
|
|
21
|
+
- Projects that are already structured as Polylith bricks.
|
|
22
|
+
- Daily Polylith development tasks — for those, see the sibling `polylith-*` skills.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## How to invoke
|
|
27
|
+
|
|
28
|
+
Load the orchestrator and let it drive the rest:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Load the `migrate-orchestrator` skill and migrate `projects/<project-name>`.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The orchestrator will:
|
|
35
|
+
1. Ask the user for explicit confirmation.
|
|
36
|
+
2. Establish a git safety net (dedicated branch + per-phase commits).
|
|
37
|
+
3. Load and execute each phase skill in order, verifying after each.
|
|
38
|
+
|
|
39
|
+
> **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.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Downstream installation
|
|
44
|
+
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
## Polylith migration instructions
|
|
51
|
+
|
|
52
|
+
When the user asks to migrate a non-Polylith Python project to Polylith
|
|
53
|
+
(e.g. "migrate `projects/<name>` to Polylith"), load the
|
|
54
|
+
`migrate-orchestrator` skill first and let it drive the workflow.
|
|
55
|
+
|
|
56
|
+
Never load `migrate-discover`, `migrate-extract-to-base`, or any other
|
|
57
|
+
`migrate-*` sub-skill directly — they are phases the orchestrator
|
|
58
|
+
invokes in order, with per-phase verification and git checkpoints
|
|
59
|
+
between them.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Workflow at a glance
|
|
65
|
+
|
|
66
|
+
The **authoritative** phase order, numbering, and dependencies live in
|
|
67
|
+
[`migrate-orchestrator/SKILL.md`](./migrate-orchestrator/SKILL.md) — it is the
|
|
68
|
+
**single source of truth**. This README intentionally does **not** repeat the
|
|
69
|
+
table, to avoid drift (sub-skills must not hardcode phase numbers either; they
|
|
70
|
+
reference `<N>` from the orchestrator table).
|
|
71
|
+
|
|
72
|
+
At a glance, the flow is:
|
|
73
|
+
|
|
74
|
+
> **discover → analyze-imports** (choose `shim`/`shimless`) **→ extract-to-base →
|
|
75
|
+
> update-imports →** *[optional shim sub-track, only when `SHIM_STRATEGY=shim`]* **→
|
|
76
|
+
> prepare-project → verify-stability → isolate-base-and-big-component →
|
|
77
|
+
> split-big-component → extract-standalone-modules →
|
|
78
|
+
> isolate-shared-and-project-logic → distribute-wiring → split-component-internals →
|
|
79
|
+
> refactor-tests → definition-of-done**
|
|
80
|
+
|
|
81
|
+
### Optional skills (triggered during `migrate-discover`)
|
|
82
|
+
|
|
83
|
+
| Skill | Purpose | Trigger / dependency |
|
|
84
|
+
|-------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
|
|
85
|
+
| [`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 `migrate-discover` and `migrate-analyze-imports`. |
|
|
86
|
+
| [`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 `migrate-discover` and `migrate-analyze-imports`. |
|
|
87
|
+
| [`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 `migrate-discover` and `migrate-analyze-imports`. |
|
|
88
|
+
| [`migrate-dedupe`](./migrate-dedupe/SKILL.md) | Identify and apply controlled deduplication discovered during refactoring. | User approval. Runs after `migrate-split-big-component` or `migrate-extract-standalone-modules`. |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Scope of the four "splitting" skills
|
|
93
|
+
|
|
94
|
+
These skills overlap in vocabulary but address different scopes. Use this matrix to decide which one applies:
|
|
95
|
+
|
|
96
|
+
| Skill | Scope | Trigger |
|
|
97
|
+
|---------------------------------------------|------------------------------------------------|---------------------------------------------------------------------------|
|
|
98
|
+
| `migrate-split-big-component` | Within one project; component → multiple components. | The temporary big component (from `migrate-isolate-base-and-big-component`) is too large. |
|
|
99
|
+
| `migrate-extract-standalone-modules` | Within one project; pulls foundational modules out of the residual. | Residual still contains `consts.py`/`exceptions.py`/`models.py`. |
|
|
100
|
+
| `migrate-split-component-internals` | Within one already-extracted shared component; `core.py` → multiple files. | A component's `core.py` mixes multiple domains internally. |
|
|
101
|
+
| `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. |
|
|
102
|
+
|
|
103
|
+
> 💡 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.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Files in this directory
|
|
108
|
+
|
|
109
|
+
- `README.md` — this file (human reference + index).
|
|
110
|
+
- `migrate-orchestrator/SKILL.md` — entry point; defines the phase order and the git safety net.
|
|
111
|
+
- `migrate-<phase>/SKILL.md` — one per phase referenced in the orchestrator table.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-analyze-imports
|
|
3
|
+
description: "[Internal sub-skill of `migrate-orchestrator`. Do not load directly — load `migrate-orchestrator` first, which drives all phases.] Analyze the project's import graph to find how the original namespace is referenced, choose the namespace-rewrite strategy (shim vs shimless), detect circular imports, and list symbols exported by the original namespace."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: migrate-analyze-imports
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
Analyze the project's import graph to:
|
|
10
|
+
1. Find **every** reference to the original namespace (in all three forms — see below).
|
|
11
|
+
2. Choose the namespace-rewrite strategy: `SHIM_STRATEGY=shim|shimless`.
|
|
12
|
+
3. List symbols exported by the original namespace's `__init__.py`.
|
|
13
|
+
4. Detect potential circular imports.
|
|
14
|
+
|
|
15
|
+
This drives the namespace rewrite (phase 4) and, when `SHIM_STRATEGY=shim`, the
|
|
16
|
+
shim sub-track (phase 4b). See the `migrate-orchestrator` table for phase numbers.
|
|
17
|
+
|
|
18
|
+
## Inputs
|
|
19
|
+
- Project name (from `migration/<project-name>/state.md`)
|
|
20
|
+
- Original namespace `ORIG_TOP_NS` (from `migration/<project-name>/state.md`)
|
|
21
|
+
|
|
22
|
+
## The three reference forms (cover all of them)
|
|
23
|
+
A namespace rewrite is **incomplete** unless it covers every form below. A naive
|
|
24
|
+
"replace `from <ns>.` " misses forms 2 and 3:
|
|
25
|
+
|
|
26
|
+
1. **Dotted import** — `from ${ORIG_TOP_NS}.<sub> import …`, `import ${ORIG_TOP_NS}.<sub>`.
|
|
27
|
+
2. **Bare submodule import** — `from ${ORIG_TOP_NS} import <sub>` — single, multi-name
|
|
28
|
+
(`a, b, c`), and **mixed** lines where only some names move. Easy to miss: there is
|
|
29
|
+
no dot after the namespace.
|
|
30
|
+
3. **Quoted string module paths** — `mock.patch("${ORIG_TOP_NS}.x.Y")`, logging
|
|
31
|
+
dict-config `"${ORIG_TOP_NS}.logging.HealthFilter"`, `importlib` / `getattr`
|
|
32
|
+
targets. Not import statements, but they must be rewritten too.
|
|
33
|
+
|
|
34
|
+
> ⚠ Do **not** rewrite unquoted local variables that merely share a name with the
|
|
35
|
+
> namespace (e.g. a FastAPI `app = FastAPI()` instance's `app.include_router(...)`).
|
|
36
|
+
> Target import statements and quoted module paths only.
|
|
37
|
+
|
|
38
|
+
## Steps
|
|
39
|
+
|
|
40
|
+
### 1. Identify references to the original namespace
|
|
41
|
+
1. Search for all three forms above across **all** `.py` files in the project (and
|
|
42
|
+
`pyproject.toml` / config files for string paths).
|
|
43
|
+
2. Record the paths and statements in `migration/${PROJECT}/import_analysis.md`,
|
|
44
|
+
grouped as: **internal** (inside `${ORIG_TOP_NS}/`), **external consumers**
|
|
45
|
+
(entrypoints, `alembic`, scripts), and **tests**. The external + test groups are
|
|
46
|
+
what the strategy decision below hinges on.
|
|
47
|
+
|
|
48
|
+
### 2. List symbols exported by the original namespace
|
|
49
|
+
1. Inspect `${ORIG_TOP_NS}/__init__.py` (typically `projects/${PROJECT}/src/${ORIG_TOP_NS}/__init__.py`
|
|
50
|
+
or `projects/${PROJECT}/${ORIG_TOP_NS}/__init__.py`) and list public symbols
|
|
51
|
+
(not starting with `_`).
|
|
52
|
+
2. Record them, and **note whether `__init__.py` is effectively empty** (docstring only).
|
|
53
|
+
|
|
54
|
+
### 3. Decide the rewrite strategy (`SHIM_STRATEGY`)
|
|
55
|
+
Choose based on the findings and record it in `state.md`:
|
|
56
|
+
|
|
57
|
+
- **`shimless`** — when imports are predominantly **submodule-qualified**
|
|
58
|
+
(`from ${ORIG_TOP_NS}.<sub> import …` / `from ${ORIG_TOP_NS} import <sub>`) and
|
|
59
|
+
`${ORIG_TOP_NS}/__init__.py` exports little or nothing. A single top-level
|
|
60
|
+
re-export shim would resolve **none** of those submodule paths, and a full package
|
|
61
|
+
shim mirroring every module is high-effort/high-risk. Phase 4 rewrites **all**
|
|
62
|
+
references (internal + external + tests) directly to the new namespace, and the
|
|
63
|
+
**phase 4b sub-track is skipped**.
|
|
64
|
+
- **`shim`** — when consumers import top-level symbols (`from ${ORIG_TOP_NS} import X`)
|
|
65
|
+
that a single `${ORIG_TOP_NS}/__init__.py` re-export can satisfy, and you want to
|
|
66
|
+
defer rewriting external consumers. Run the phase 4b sub-track after phase 4.
|
|
67
|
+
- **When in doubt, prefer `shimless`** — it leaves no transitional shim to remove
|
|
68
|
+
later (the definition-of-done forbids undocumented shims), at the cost of a wider
|
|
69
|
+
but mechanical rewrite. Confirm with the user if the consumer surface is large.
|
|
70
|
+
|
|
71
|
+
Record:
|
|
72
|
+
```
|
|
73
|
+
SHIM_STRATEGY=<shim|shimless>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 4. Detect potential circular imports
|
|
77
|
+
1. Inspect the import graph for cycles — especially base ↔ shim once a shim is in
|
|
78
|
+
place (`shim` strategy only).
|
|
79
|
+
2. Record any chains in `import_analysis.md`. A pure namespace rename (shimless)
|
|
80
|
+
preserves the original graph, so cycles there usually mean the project already had
|
|
81
|
+
them.
|
|
82
|
+
|
|
83
|
+
## Output
|
|
84
|
+
- `migration/<project-name>/import_analysis.md` with: references by form & group,
|
|
85
|
+
exported symbols, the chosen strategy + rationale, and circular-import chains (if any).
|
|
86
|
+
- `SHIM_STRATEGY` set in `migration/<project-name>/state.md`.
|
|
87
|
+
|
|
88
|
+
## Verify
|
|
89
|
+
1. `migration/<project-name>/import_analysis.md` exists and is not empty.
|
|
90
|
+
2. It records all three reference forms, the exported symbols, and any cycles.
|
|
91
|
+
3. `SHIM_STRATEGY` is set in `state.md` (`shim` or `shimless`) with a recorded rationale.
|
|
92
|
+
|
|
93
|
+
## Commit
|
|
94
|
+
```bash
|
|
95
|
+
git add migration/${PROJECT}/import_analysis.md migration/${PROJECT}/state.md
|
|
96
|
+
git commit -m "migrate(${PROJECT}): phase <N> — analyze-imports"
|
|
97
|
+
```
|
|
98
|
+
> `<N>` is this phase's number from the `migrate-orchestrator` table (the single
|
|
99
|
+
> source of truth) — do not hardcode it.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-automate-import-updates
|
|
3
|
+
description: "[Internal sub-skill of `migrate-orchestrator`. Do not load directly — load `migrate-orchestrator` first, which drives all phases.] Update imports in the new base location to reference the new namespace instead of the original namespace."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: migrate-automate-import-updates
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
Update imports to reference the new namespace instead of the original namespace, ensuring that the codebase remains functional after the namespace migration.
|
|
10
|
+
|
|
11
|
+
> **Scope depends on `SHIM_STRATEGY`** (set by `migrate-analyze-imports`):
|
|
12
|
+
> - `shim`: rewrite imports **in the new base location only** — external consumers keep
|
|
13
|
+
> using the original namespace via the shim (phase 4b).
|
|
14
|
+
> - `shimless`: rewrite **every** reference to the original namespace — base internals,
|
|
15
|
+
> entrypoints / run-scripts, infra (e.g. `alembic/env.py`), and tests — so nothing
|
|
16
|
+
> imports the old namespace and no shim is needed.
|
|
17
|
+
>
|
|
18
|
+
> Cover **all three reference forms** (see `migrate-analyze-imports`): dotted
|
|
19
|
+
> `from <ns>.<sub> import …`, bare-submodule `from <ns> import <sub>` (incl. multi-name
|
|
20
|
+
> and **mixed** lines), and quoted string paths (`mock.patch("<ns>.x.Y")`, logging
|
|
21
|
+
> dict-config). A naive "`from <ns>.`" replace silently misses the bare and quoted forms.
|
|
22
|
+
>
|
|
23
|
+
> 💡 **Script the rewrite for anything non-trivial.** A small text-in → text-out helper
|
|
24
|
+
> (a pure function: file text + an `{old → new}` mapping → rewritten text) handles all
|
|
25
|
+
> three forms — including splitting a mixed bare-import line into moved vs. not-moved
|
|
26
|
+
> names — far more reliably than ad-hoc edits across dozens of files. Keep it as plain
|
|
27
|
+
> functions (no classes), run it over `bases/`, `components/`, `test/`, and the project
|
|
28
|
+
> dir, then verify by grepping for any residual `<ns>` reference. The same helper is
|
|
29
|
+
> reusable for the component-extraction rewrites in `migrate-split-big-component`.
|
|
30
|
+
|
|
31
|
+
## Inputs
|
|
32
|
+
- Project name (from `migration/<project-name>/state.md`)
|
|
33
|
+
- Original namespace (from `migration/<project-name>/state.md`)
|
|
34
|
+
- New namespace (from `migration/<project-name>/state.md`)
|
|
35
|
+
- Import analysis report (from `migration/<project-name>/import_analysis.md`)
|
|
36
|
+
|
|
37
|
+
## Steps
|
|
38
|
+
|
|
39
|
+
### 1. Identify files in the new base location importing from the original namespace
|
|
40
|
+
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.
|
|
41
|
+
|
|
42
|
+
### 2. Update imports to reference the new namespace
|
|
43
|
+
1. For each file in the new base location that imports from the original namespace:
|
|
44
|
+
- Replace `from ${ORIG_TOP_NS} import ...` with `from ${TARGET_TOP_NS}.${INITIAL_BASE_NAME}.<module> import ...`
|
|
45
|
+
- Replace `import ${ORIG_TOP_NS}` with `import ${TARGET_TOP_NS}.${INITIAL_BASE_NAME}`
|
|
46
|
+
|
|
47
|
+
Example:
|
|
48
|
+
```python
|
|
49
|
+
# Before
|
|
50
|
+
from myproject.core import MyClass
|
|
51
|
+
import myproject.utils
|
|
52
|
+
|
|
53
|
+
# After
|
|
54
|
+
from mynamespace.mybase.core import MyClass
|
|
55
|
+
import mynamespace.mybase.utils
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. Record updated files
|
|
59
|
+
1. Record all updated files in `migration/${PROJECT}/import_updates.md`.
|
|
60
|
+
|
|
61
|
+
## Output
|
|
62
|
+
- Updated files in the new base location
|
|
63
|
+
- A report file: `migration/<project-name>/import_updates.md` listing all updated files
|
|
64
|
+
|
|
65
|
+
## Verify
|
|
66
|
+
1. Confirm that all files listed in `migration/<project-name>/import_updates.md` have been updated.
|
|
67
|
+
2. Check that no files in the new base location import from the original namespace.
|
|
68
|
+
3. Verify that the codebase remains functional by running the test command from `migration/<project-name>/state.md`.
|
|
69
|
+
|
|
70
|
+
## Commit
|
|
71
|
+
```bash
|
|
72
|
+
git add bases/${TARGET_TOP_NS}/${INITIAL_BASE_NAME}/
|
|
73
|
+
git add migration/${PROJECT}/import_updates.md
|
|
74
|
+
git commit -m "migrate(${PROJECT}): phase <N> — automate-import-updates"
|
|
75
|
+
```
|
|
76
|
+
> `<N>` is this phase's number from the `migrate-orchestrator` table (the single source of truth) — do not hardcode it.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-convert-linter
|
|
3
|
+
description: "[Internal sub-skill of `migrate-orchestrator` (optional, runs only when opted in during `migrate-discover`). 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."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: migrate-convert-linter
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
## When to Skip
|
|
12
|
+
Skip this step if the project's `LINTER` and `FORMATTER` in `migration/<PROJECT>/state.md` already match the workspace's tools.
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
From `migration/<PROJECT>/state.md`:
|
|
16
|
+
- `PROJECT_DIR`
|
|
17
|
+
- `LINTER`, `FORMATTER`
|
|
18
|
+
- `RUN_TEST_CMD` (optional: `RUN_LINT_CMD`, `RUN_TYPECHECK_CMD`)
|
|
19
|
+
|
|
20
|
+
> All inputs from `state.md` are assumed to satisfy the validation rules in `migrate-discover` (`### Validation rules`). Validate before proceeding.
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
### 0. Identify the workspace's tool
|
|
25
|
+
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.
|
|
26
|
+
|
|
27
|
+
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?).
|
|
28
|
+
|
|
29
|
+
### 1. Remove Project-Specific Configs and Dependencies
|
|
30
|
+
- Remove the following sections from the project's `pyproject.toml`:
|
|
31
|
+
- `[tool.black]`, `[tool.isort]`, `[tool.flake8]`, `[tool.pylint.*]`, `[tool.autopep8]`, `[tool.pycodestyle]`
|
|
32
|
+
- Remove standalone config files: `.flake8`, `.pylintrc`, `.isort.cfg`, and lint sections in `setup.cfg` or `tox.ini`.
|
|
33
|
+
- Remove old linter/formatter dependencies from the project's `pyproject.toml`:
|
|
34
|
+
- `flake8`, `flake8-*` plugins, `pylint`, `pylint-*` plugins, `black`, `isort`, `autopep8`, `pyflakes`, `pycodestyle`, `bandit`
|
|
35
|
+
|
|
36
|
+
### 2. Assess Workspace Linting Config
|
|
37
|
+
- Review the workspace root's linting and formatting configuration.
|
|
38
|
+
- Identify any project-specific rules or ignores that differ from the workspace's standards.
|
|
39
|
+
|
|
40
|
+
### 3. Merge Project-Specific Rules
|
|
41
|
+
- If the project has unique linting rules or ignores, merge them into the workspace root's linting configuration (e.g., `[tool.ruff]`).
|
|
42
|
+
- For conflicts (e.g., stricter rules in the project), ask the user to provide guidance on whether to:
|
|
43
|
+
- Adopt the project's rules in the workspace.
|
|
44
|
+
- Suppress the project's rules in favor of the workspace's.
|
|
45
|
+
- Defer the decision and document the conflict in `migration/<PROJECT>/state.md`.
|
|
46
|
+
|
|
47
|
+
### 4. Run Workspace Linting and Formatting Tools
|
|
48
|
+
- Run the workspace's linting tool to assess violations:
|
|
49
|
+
- **Few new violations**: Fix them now.
|
|
50
|
+
- **Many new violations**: Ask the user whether to fix, suppress, or defer.
|
|
51
|
+
- Run the workspace's formatting tool to reformat the code.
|
|
52
|
+
|
|
53
|
+
### 5. Update `state.md`
|
|
54
|
+
- Set `LINTER` and `FORMATTER` to the workspace's tool(s).
|
|
55
|
+
- Update `RUN_LINT_CMD` to use the workspace's linting and formatting commands.
|
|
56
|
+
|
|
57
|
+
## Verify
|
|
58
|
+
- The workspace's linting tool passes (or remaining violations are user-approved).
|
|
59
|
+
- The workspace's formatting tool passes.
|
|
60
|
+
- `RUN_TEST_CMD` succeeds.
|
|
61
|
+
- If set, `RUN_TYPECHECK_CMD` succeeds.
|
|
62
|
+
|
|
63
|
+
## Common failure modes
|
|
64
|
+
|
|
65
|
+
| Symptom | Likely cause | Remediation |
|
|
66
|
+
|---------|--------------|-------------|
|
|
67
|
+
| 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`. |
|
|
68
|
+
| 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. |
|
|
69
|
+
| 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. |
|
|
70
|
+
|
|
71
|
+
## Done When
|
|
72
|
+
- No project-specific linter/formatter config files or dependencies remain.
|
|
73
|
+
- Project-specific linting rules are merged into the workspace root's configuration.
|
|
74
|
+
- `LINTER` and `FORMATTER` in `migration/<PROJECT>/state.md` match the workspace's tools.
|
|
75
|
+
- Tests pass via the workspace's tooling.
|
|
76
|
+
|
|
77
|
+
## Commit
|
|
78
|
+
|
|
79
|
+
After verification passes, commit this phase to the migration branch:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git add -A && git commit -m "migrate(<PROJECT>): phase optional — convert-linter"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Substitute `<PROJECT>` from `state.md`. This is an **optional** skill off the numbered main line, so the commit uses the literal `phase optional` label (no `<N>`). Do not proceed without a clean commit — the per-phase commit is the rollback point for the next phase's failure-mode tables.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-convert-package-manager
|
|
3
|
+
description: "[Internal sub-skill of `migrate-orchestrator` (optional, runs only when opted in during `migrate-discover`). Do not load directly — load `migrate-orchestrator` first.] Convert the project's `pyproject.toml` to PEP 621/uv-workspaces format and register it as a uv-workspace member. **Opinionated about uv** — only applies when the workspace itself uses uv. Skip otherwise."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: migrate-convert-package-manager
|
|
7
|
+
|
|
8
|
+
> ⚠ **Opinionation gate.** This skill is **explicitly opinionated about uv**. It does not generalize to Poetry, PDM, or Hatch workspaces. If your Polylith workspace uses one of those, **do not run this skill** — align the project to the workspace's manager via a manual step instead, and leave `CONVERT_PACKAGE_MANAGER=no` in `state.md`.
|
|
9
|
+
|
|
10
|
+
## Goal
|
|
11
|
+
Convert the project's `pyproject.toml` to PEP 621/uv format and register it as a uv-workspace member. This makes the project share the workspace's single lock file and virtual environment, preventing version skew.
|
|
12
|
+
|
|
13
|
+
## When to Skip
|
|
14
|
+
Skip this skill if **any** of the following holds:
|
|
15
|
+
- `PACKAGE_MANAGER=uv` already in `migration/<PROJECT>/state.md` (nothing to convert).
|
|
16
|
+
- The workspace root does **not** use uv (this skill does not apply — see the opinionation gate above).
|
|
17
|
+
- `CONVERT_PACKAGE_MANAGER=no` in `state.md` (user opted out during `migrate-discover`).
|
|
18
|
+
|
|
19
|
+
### Verify the workspace uses uv before proceeding
|
|
20
|
+
Open the **workspace root** `pyproject.toml` and look for `[tool.uv.workspace]` and/or a sibling `uv.lock`. If neither is present, **stop**: this skill does not apply.
|
|
21
|
+
|
|
22
|
+
## Inputs
|
|
23
|
+
From `migration/<PROJECT>/state.md`:
|
|
24
|
+
- `PROJECT_DIR`
|
|
25
|
+
- `PACKAGE_MANAGER`
|
|
26
|
+
- `RUN_TEST_CMD` (optional: `RUN_LINT_CMD`, `RUN_TYPECHECK_CMD`)
|
|
27
|
+
|
|
28
|
+
> All inputs from `state.md` are assumed to satisfy the validation rules in `migrate-discover` (`### Validation rules`). Validate before proceeding.
|
|
29
|
+
|
|
30
|
+
## Steps
|
|
31
|
+
|
|
32
|
+
### 1. Ask for User Approval
|
|
33
|
+
- Ask the user if they want to convert the project's `pyproject.toml` to PEP 621/uv format.
|
|
34
|
+
- Record their choice in `state.md`:
|
|
35
|
+
```text
|
|
36
|
+
CONVERT_PACKAGE_MANAGER=<yes|no>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Rewrite `pyproject.toml` to PEP 621/uv Format
|
|
40
|
+
- Move `[tool.poetry.dependencies]` to `[project] dependencies`. Keep only **runtime** (non-dev, non-test) dependencies in the project, listed **without version constraints**.
|
|
41
|
+
- Remove Poetry-specific sections: `[tool.poetry]`, `[tool.poetry.group.*]`, `[[tool.poetry.source]]`, and `[build-system]` with `poetry-core`.
|
|
42
|
+
- Add a `[build-system]` with `hatchling` (or the workspace's build backend).
|
|
43
|
+
- Preserve `[tool.*]` sections for other tools (e.g., pytest, ruff, mypy).
|
|
44
|
+
- Add `[tool.uv]` only if project-level uv configuration is needed.
|
|
45
|
+
|
|
46
|
+
### 3. Register as a Workspace Member
|
|
47
|
+
- Add the project path to the workspace root `pyproject.toml` under `[tool.uv.workspace] members`.
|
|
48
|
+
Example:
|
|
49
|
+
```toml
|
|
50
|
+
members = ["projects/example-service-b"]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 4. Consolidate Dependencies
|
|
54
|
+
- Add all **third-party runtime dependencies with version constraints** to the workspace root `pyproject.toml` `[project] dependencies`.
|
|
55
|
+
- Move all dev/test/tooling dependencies to the workspace root `[dependency-groups]` (e.g., `dev = [...]`, `test = [...]`).
|
|
56
|
+
- Ensure the project's `pyproject.toml` lists runtime dependencies **without version numbers**.
|
|
57
|
+
|
|
58
|
+
### 5. Lock and Sync
|
|
59
|
+
- Run `uv lock` from the workspace root to regenerate `uv.lock` with the new member.
|
|
60
|
+
- Run `uv sync` to install all dependencies into the shared `.venv`.
|
|
61
|
+
- Resolve any version conflicts that arise during `uv lock`.
|
|
62
|
+
|
|
63
|
+
### 6. Delete Old Lock Files
|
|
64
|
+
- Remove `poetry.lock`, `Pipfile.lock`, and generated `requirements*.txt` from the project directory.
|
|
65
|
+
|
|
66
|
+
### 7. Update Verification Commands
|
|
67
|
+
- Replace any `poetry run`, `pipenv run`, or bare commands with `uv run` equivalents in `migration/<PROJECT>/state.md`.
|
|
68
|
+
Example:
|
|
69
|
+
```text
|
|
70
|
+
RUN_TEST_CMD=uv run pytest <test-dirs>
|
|
71
|
+
RUN_LINT_CMD=uv run ruff check <dirs>
|
|
72
|
+
```
|
|
73
|
+
- Update `PACKAGE_MANAGER=uv` in `state.md`.
|
|
74
|
+
|
|
75
|
+
## Verify
|
|
76
|
+
- Run the updated `RUN_TEST_CMD` and confirm the same pass/fail counts as before the conversion.
|
|
77
|
+
- If set, run `RUN_LINT_CMD` and `RUN_TYPECHECK_CMD`.
|
|
78
|
+
- Ensure `uv lock` and `uv sync` succeed from the workspace root.
|
|
79
|
+
|
|
80
|
+
## Common failure modes
|
|
81
|
+
|
|
82
|
+
| Symptom | Likely cause | Remediation |
|
|
83
|
+
|---------|--------------|-------------|
|
|
84
|
+
| Workspace root does not use uv (no `[tool.uv.workspace]`, no `uv.lock`) | This skill does not apply — the opinionation gate at the top of this file rules it out. | Stop. Set `CONVERT_PACKAGE_MANAGER=no` in `state.md`. Align the project to the workspace's actual manager (Poetry/PDM/Hatch) via a manual step instead. |
|
|
85
|
+
| `uv lock` fails with "no version satisfies …" after adding the project as a workspace member | Project's old version constraints conflict with the workspace root's pins. | Relax the workspace root's range, or, if the project legitimately needs a different version, pin it explicitly in the project's `pyproject.toml`. As a last resort, exclude the project from the workspace and use a separate environment. |
|
|
86
|
+
| Project depends on a private/internal package that the workspace root doesn't know about | Private index or path-dependency not declared at the root. | Add the dependency (and its source — `[tool.uv.sources]` or `[[tool.uv.index]]`) to the workspace root `pyproject.toml`. |
|
|
87
|
+
|
|
88
|
+
## Done When
|
|
89
|
+
- The project is listed as a workspace member in the root `pyproject.toml`.
|
|
90
|
+
- `uv lock` and `uv sync` succeed from the workspace root.
|
|
91
|
+
- Old lock files (`poetry.lock`, `Pipfile.lock`, generated `requirements*.txt`) are deleted from the project directory.
|
|
92
|
+
- `PACKAGE_MANAGER=uv` is recorded in `migration/<PROJECT>/state.md`.
|
|
93
|
+
- Verification commands in `state.md` use `uv run`.
|
|
94
|
+
- Tests pass via `uv run`.
|
|
95
|
+
|
|
96
|
+
## Commit
|
|
97
|
+
|
|
98
|
+
After verification passes, commit this phase to the migration branch:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
git add -A && git commit -m "migrate(<PROJECT>): phase optional — convert-package-manager"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Substitute `<PROJECT>` from `state.md`. This is an **optional** skill off the numbered main line, so the commit uses the literal `phase optional` label (no `<N>`). Do not proceed without a clean commit — the per-phase commit is the rollback point for the next phase's failure-mode tables.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-convert-type-checker
|
|
3
|
+
description: "[Internal sub-skill of `migrate-orchestrator` (optional, runs only when opted in during `migrate-discover`). Do not load directly — load `migrate-orchestrator` first.] Align the project's type checker with the **workspace's** configured tool (whatever it is — mypy, pyright, ty, etc.). Removes project-specific config and consolidates settings into the workspace root."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: migrate-convert-type-checker
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
Align the project with the **workspace's** type checker. This skill is **not** opinionated about ty — it reads the workspace's configured tool from the root `pyproject.toml` and aligns the project to that.
|
|
10
|
+
|
|
11
|
+
## When to Skip
|
|
12
|
+
Skip this step if the project's `TYPE_CHECKER` in `migration/<PROJECT>/state.md` already matches the workspace's type-checking tool.
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
From `migration/<PROJECT>/state.md`:
|
|
16
|
+
- `PROJECT_DIR`
|
|
17
|
+
- `TYPE_CHECKER`
|
|
18
|
+
- `RUN_TEST_CMD` (optional: `RUN_LINT_CMD`, `RUN_TYPECHECK_CMD`)
|
|
19
|
+
|
|
20
|
+
> All inputs from `state.md` are assumed to satisfy the validation rules in `migrate-discover` (`### Validation rules`). Validate before proceeding.
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
### 0. Identify the workspace's tool
|
|
25
|
+
Open the **workspace root** `pyproject.toml` and identify the configured type checker using the same detection table as `migrate-discover` (`[tool.mypy]` or `mypy.ini` → mypy, `[tool.pyright]` or `pyrightconfig.json` → pyright, `[tool.ty]` → ty). Record what you found — every step below refers to "the workspace's type checker" and means **this** tool, not necessarily ty.
|
|
26
|
+
|
|
27
|
+
If the workspace has no type checker configured at all, stop and ask the user how to proceed (introduce one? skip type-check alignment? abort the conversion?).
|
|
28
|
+
|
|
29
|
+
### 1. Remove Old Configs and Dependencies
|
|
30
|
+
- Remove the following sections from `pyproject.toml`:
|
|
31
|
+
- `[tool.mypy]`, `[[tool.mypy.overrides]]`, `[mypy-*]`, `[tool.pyright]`, `[tool.pytype]`
|
|
32
|
+
- Remove standalone config files: `mypy.ini`, `.mypy.ini`, `pyrightconfig.json`.
|
|
33
|
+
- Remove old type checker dependencies from `pyproject.toml`:
|
|
34
|
+
- `mypy`, `mypy-extensions`, `types-*` stub packages, `pyright`, `pytype`, `sqlalchemy-stubs`, `django-stubs`.
|
|
35
|
+
|
|
36
|
+
### 2. Clean Up Type Ignore Comments
|
|
37
|
+
- Remove `# type: ignore[<mypy-code>]` comments that reference mypy-specific error codes.
|
|
38
|
+
- Leave comments that suppress real issues and document them in `state.md`.
|
|
39
|
+
|
|
40
|
+
### 3. Adopt Workspace Type-Checking Config
|
|
41
|
+
- The workspace root `pyproject.toml` may define the type-checking configuration. The project inherits this config.
|
|
42
|
+
- Add project-specific overrides if needed.
|
|
43
|
+
|
|
44
|
+
### 4. Run the Workspace's Type-Checking Tool
|
|
45
|
+
- Run the workspace's type-checking tool to assess errors:
|
|
46
|
+
- **Same or fewer errors**: No action needed.
|
|
47
|
+
- **New errors**: Ask the user whether to fix, suppress, or adjust the config.
|
|
48
|
+
- **Missing stub errors**: Silence with per-module ignores in the workspace's type-checking config.
|
|
49
|
+
|
|
50
|
+
### 5. Update `state.md`
|
|
51
|
+
- Set `TYPE_CHECKER` to the workspace's type-checking tool.
|
|
52
|
+
- Update `RUN_TYPECHECK_CMD` to use the workspace's type-checking command.
|
|
53
|
+
|
|
54
|
+
## Verify
|
|
55
|
+
- The workspace's type-checking tool runs cleanly (or remaining errors are user-approved).
|
|
56
|
+
- `RUN_TEST_CMD` succeeds.
|
|
57
|
+
- If set, `RUN_LINT_CMD` succeeds.
|
|
58
|
+
|
|
59
|
+
## Common failure modes
|
|
60
|
+
|
|
61
|
+
| Symptom | Likely cause | Remediation |
|
|
62
|
+
|---------|--------------|-------------|
|
|
63
|
+
| The workspace's checker surfaces type errors the old checker didn't | Stricter type rules expose real bugs that were always there. | Fix the bugs now where cheap (small handful). For systemic gaps, suppress per-module in the workspace's checker config and document the debt in `state.md`. Do **not** blanket-ignore at file scope. |
|
|
64
|
+
| Stub packages (`types-*`, `django-stubs`, `sqlalchemy-stubs`) were required by the old checker but the new one bundles its own | Dependency carryover. | Remove the stub packages from `pyproject.toml`. Re-run the workspace's checker to confirm it picks up its own stubs. |
|
|
65
|
+
| `# type: ignore[<old-code>]` comments still reference the old checker's error codes | Step 2 missed some. | Strip the `[<code>]` bracket. If the suppression is still needed, leave a bare `# type: ignore` **with a comment explaining why**; otherwise remove the suppression entirely. |
|
|
66
|
+
|
|
67
|
+
## Done When
|
|
68
|
+
- No old type checker config files remain.
|
|
69
|
+
- Old type checker dependencies are removed from `pyproject.toml`.
|
|
70
|
+
- Stale `# type: ignore` comments referencing tool-specific codes are removed (or documented if intentionally kept).
|
|
71
|
+
- `TYPE_CHECKER` in `migration/<PROJECT>/state.md` matches the workspace's type-checking tool.
|
|
72
|
+
- The workspace's type-checking tool runs cleanly or known issues are documented in `state.md`.
|
|
73
|
+
- Tests pass via the workspace's tooling.
|
|
74
|
+
|
|
75
|
+
## Commit
|
|
76
|
+
|
|
77
|
+
After verification passes, commit this phase to the migration branch:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git add -A && git commit -m "migrate(<PROJECT>): phase optional — convert-type-checker"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Substitute `<PROJECT>` from `state.md`. This is an **optional** skill off the numbered main line, so the commit uses the literal `phase optional` label (no `<N>`). Do not proceed without a clean commit — the per-phase commit is the rollback point for the next phase's failure-mode tables.
|