margo-tooling 0.5.1__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.
- margo_tooling-0.5.1/.github/workflows/ci.yml +37 -0
- margo_tooling-0.5.1/.github/workflows/docs.yml +44 -0
- margo_tooling-0.5.1/.github/workflows/publish-pypi.yml +36 -0
- margo_tooling-0.5.1/.github/workflows/release-check.yml +45 -0
- margo_tooling-0.5.1/.github/workflows/release.yml +105 -0
- margo_tooling-0.5.1/.gitignore +44 -0
- margo_tooling-0.5.1/.kiro/agents/docs-writer.json +63 -0
- margo_tooling-0.5.1/.kiro/agents/planner.json +85 -0
- margo_tooling-0.5.1/.kiro/agents/python-dev.json +60 -0
- margo_tooling-0.5.1/.kiro/skills/code-quality-enhancement/SKILL.md +88 -0
- margo_tooling-0.5.1/.kiro/skills/fix-todos/SKILL.md +51 -0
- margo_tooling-0.5.1/.kiro/sprints/sprint-5.md +408 -0
- margo_tooling-0.5.1/.kiro/sprints/sprint-6.md +342 -0
- margo_tooling-0.5.1/.kiro/steering/code-conventions.md +66 -0
- margo_tooling-0.5.1/.kiro/steering/documentation.md +52 -0
- margo_tooling-0.5.1/.kiro/steering/oci-media-types.md +48 -0
- margo_tooling-0.5.1/AGENTS.md +38 -0
- margo_tooling-0.5.1/CONTRIBUTING.md +98 -0
- margo_tooling-0.5.1/Containerfile +22 -0
- margo_tooling-0.5.1/FEATURES.md +691 -0
- margo_tooling-0.5.1/LICENSE +201 -0
- margo_tooling-0.5.1/Makefile +24 -0
- margo_tooling-0.5.1/PKG-INFO +13 -0
- margo_tooling-0.5.1/ROADMAP.md +95 -0
- margo_tooling-0.5.1/TESTING.md +64 -0
- margo_tooling-0.5.1/cliff.toml +51 -0
- margo_tooling-0.5.1/docs/examples/basic-quadlet.md +92 -0
- margo_tooling-0.5.1/docs/examples/full.md +304 -0
- margo_tooling-0.5.1/docs/examples/image-search-replace.md +145 -0
- margo_tooling-0.5.1/docs/examples/minimal.md +70 -0
- margo_tooling-0.5.1/docs/index.md +27 -0
- margo_tooling-0.5.1/docs/margo-yaml.md +217 -0
- margo_tooling-0.5.1/docs/stylesheets/extra.css +5 -0
- margo_tooling-0.5.1/mkdocs.yml +38 -0
- margo_tooling-0.5.1/pyproject.toml +103 -0
- margo_tooling-0.5.1/src/margot/__init__.py +0 -0
- margo_tooling-0.5.1/src/margot/commands/__init__.py +1 -0
- margo_tooling-0.5.1/src/margot/commands/auth.py +117 -0
- margo_tooling-0.5.1/src/margot/commands/build.py +88 -0
- margo_tooling-0.5.1/src/margot/commands/fetch.py +22 -0
- margo_tooling-0.5.1/src/margot/commands/global_options.py +29 -0
- margo_tooling-0.5.1/src/margot/commands/pull.py +56 -0
- margo_tooling-0.5.1/src/margot/commands/push.py +91 -0
- margo_tooling-0.5.1/src/margot/commands/version.py +11 -0
- margo_tooling-0.5.1/src/margot/config.py +75 -0
- margo_tooling-0.5.1/src/margot/console.py +148 -0
- margo_tooling-0.5.1/src/margot/domain/__init__.py +0 -0
- margo_tooling-0.5.1/src/margot/domain/auth.py +81 -0
- margo_tooling-0.5.1/src/margot/domain/layers.py +102 -0
- margo_tooling-0.5.1/src/margot/domain/metadata.py +235 -0
- margo_tooling-0.5.1/src/margot/domain/models.py +49 -0
- margo_tooling-0.5.1/src/margot/domain/tags.py +53 -0
- margo_tooling-0.5.1/src/margot/domain/uri.py +77 -0
- margo_tooling-0.5.1/src/margot/infra/__init__.py +1 -0
- margo_tooling-0.5.1/src/margot/infra/credentials.py +196 -0
- margo_tooling-0.5.1/src/margot/infra/filesystem.py +97 -0
- margo_tooling-0.5.1/src/margot/infra/oci.py +350 -0
- margo_tooling-0.5.1/src/margot/main.py +33 -0
- margo_tooling-0.5.1/src/margot/services/__init__.py +1 -0
- margo_tooling-0.5.1/src/margot/services/auth.py +93 -0
- margo_tooling-0.5.1/src/margot/services/build.py +250 -0
- margo_tooling-0.5.1/src/margot/services/fetch.py +33 -0
- margo_tooling-0.5.1/src/margot/services/pull.py +171 -0
- margo_tooling-0.5.1/src/margot/services/push.py +372 -0
- margo_tooling-0.5.1/tests/__init__.py +0 -0
- margo_tooling-0.5.1/tests/conftest.py +73 -0
- margo_tooling-0.5.1/tests/e2e/__init__.py +1 -0
- margo_tooling-0.5.1/tests/e2e/test_auth_cli.py +285 -0
- margo_tooling-0.5.1/tests/e2e/test_build_cli.py +369 -0
- margo_tooling-0.5.1/tests/e2e/test_fetch_cli.py +162 -0
- margo_tooling-0.5.1/tests/e2e/test_pull_cli.py +451 -0
- margo_tooling-0.5.1/tests/e2e/test_push_cli.py +205 -0
- margo_tooling-0.5.1/tests/integration/__init__.py +1 -0
- margo_tooling-0.5.1/tests/integration/test_auth_service.py +249 -0
- margo_tooling-0.5.1/tests/integration/test_build.py +893 -0
- margo_tooling-0.5.1/tests/integration/test_fetch_service.py +174 -0
- margo_tooling-0.5.1/tests/integration/test_pull_service.py +651 -0
- margo_tooling-0.5.1/tests/integration/test_push_service.py +818 -0
- margo_tooling-0.5.1/tests/test_smoke.py +24 -0
- margo_tooling-0.5.1/tests/unit/__init__.py +1 -0
- margo_tooling-0.5.1/tests/unit/test_config.py +205 -0
- margo_tooling-0.5.1/tests/unit/test_console.py +396 -0
- margo_tooling-0.5.1/tests/unit/test_credentials.py +400 -0
- margo_tooling-0.5.1/tests/unit/test_domain_auth.py +135 -0
- margo_tooling-0.5.1/tests/unit/test_domain_layers.py +282 -0
- margo_tooling-0.5.1/tests/unit/test_domain_models.py +103 -0
- margo_tooling-0.5.1/tests/unit/test_domain_uri.py +127 -0
- margo_tooling-0.5.1/tests/unit/test_filesystem.py +409 -0
- margo_tooling-0.5.1/tests/unit/test_global_options.py +49 -0
- margo_tooling-0.5.1/tests/unit/test_infra_oci.py +234 -0
- margo_tooling-0.5.1/tests/unit/test_infra_oci_push.py +364 -0
- margo_tooling-0.5.1/tests/unit/test_metadata.py +759 -0
- margo_tooling-0.5.1/tests/unit/test_tags.py +90 -0
- margo_tooling-0.5.1/uv.lock +965 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
check:
|
|
10
|
+
name: Lint
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- uses: astral-sh/setup-uv@v6
|
|
16
|
+
with:
|
|
17
|
+
enable-cache: true
|
|
18
|
+
|
|
19
|
+
- name: lint
|
|
20
|
+
run: make lint
|
|
21
|
+
|
|
22
|
+
test:
|
|
23
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
strategy:
|
|
26
|
+
matrix:
|
|
27
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- uses: astral-sh/setup-uv@v6
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
python-version: ${{ matrix.python-version }}
|
|
35
|
+
|
|
36
|
+
- name: pytest
|
|
37
|
+
run: make test
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pages: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: pages
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
name: Build
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- uses: astral-sh/setup-uv@v6
|
|
24
|
+
with:
|
|
25
|
+
enable-cache: true
|
|
26
|
+
|
|
27
|
+
- name: build docs
|
|
28
|
+
run: make docs-check
|
|
29
|
+
|
|
30
|
+
- uses: actions/upload-pages-artifact@v3
|
|
31
|
+
with:
|
|
32
|
+
path: site/
|
|
33
|
+
|
|
34
|
+
deploy:
|
|
35
|
+
name: Deploy
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
environment:
|
|
39
|
+
name: github-pages
|
|
40
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
41
|
+
steps:
|
|
42
|
+
- name: deploy to GitHub Pages
|
|
43
|
+
id: deployment
|
|
44
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
version:
|
|
9
|
+
description: "Git tag of the GitHub release to publish (e.g. 1.2.3)"
|
|
10
|
+
required: true
|
|
11
|
+
type: string
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
publish:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment: pypi
|
|
17
|
+
permissions:
|
|
18
|
+
id-token: write # required for PyPI trusted publishing
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Resolve release tag
|
|
22
|
+
id: tag
|
|
23
|
+
run: echo "version=${{ inputs.version || github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
|
|
24
|
+
|
|
25
|
+
- name: Download release artifacts
|
|
26
|
+
env:
|
|
27
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
28
|
+
run: |
|
|
29
|
+
gh release download ${{ steps.tag.outputs.version }} \
|
|
30
|
+
--repo ${{ github.repository }} \
|
|
31
|
+
--pattern '*.whl' \
|
|
32
|
+
--pattern '*.tar.gz' \
|
|
33
|
+
--dir dist/
|
|
34
|
+
|
|
35
|
+
- name: Publish to PyPI
|
|
36
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Release Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
preview-release-version:
|
|
9
|
+
if: startsWith(github.head_ref, 'release/')
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- name: Extract version from branch name
|
|
14
|
+
id: version
|
|
15
|
+
run: |
|
|
16
|
+
VERSION=${GITHUB_HEAD_REF#release/}
|
|
17
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
18
|
+
|
|
19
|
+
- uses: astral-sh/setup-uv@v6
|
|
20
|
+
|
|
21
|
+
- name: Validate SemVer
|
|
22
|
+
run: uvx --from 'semver>=3.0,<4.0' pysemver check ${{ steps.version.outputs.version }}
|
|
23
|
+
|
|
24
|
+
preview-changelog:
|
|
25
|
+
if: startsWith(github.head_ref, 'release/')
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
|
|
33
|
+
- name: Extract version from branch name
|
|
34
|
+
id: version
|
|
35
|
+
run: |
|
|
36
|
+
VERSION=${GITHUB_HEAD_REF#release/}
|
|
37
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
38
|
+
|
|
39
|
+
- uses: astral-sh/setup-uv@v6
|
|
40
|
+
|
|
41
|
+
- name: Preview release notes
|
|
42
|
+
run: |
|
|
43
|
+
echo "## Release notes preview for ${{ steps.version.outputs.version }}"
|
|
44
|
+
echo ""
|
|
45
|
+
uvx git-cliff --unreleased --strip header
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [closed]
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/')
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
|
|
20
|
+
- name: Extract version from branch name
|
|
21
|
+
id: version
|
|
22
|
+
run: |
|
|
23
|
+
VERSION=${GITHUB_HEAD_REF#release/}
|
|
24
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
25
|
+
|
|
26
|
+
- uses: astral-sh/setup-uv@v6
|
|
27
|
+
|
|
28
|
+
- name: Validate SemVer
|
|
29
|
+
run: uvx --from 'semver>=3.0,<4.0' pysemver check ${{ steps.version.outputs.version }}
|
|
30
|
+
|
|
31
|
+
- name: Tag the release commit
|
|
32
|
+
env:
|
|
33
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
34
|
+
run: |
|
|
35
|
+
git config user.name "github-actions[bot]"
|
|
36
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
37
|
+
git tag ${{ steps.version.outputs.version }}
|
|
38
|
+
git push origin ${{ steps.version.outputs.version }}
|
|
39
|
+
|
|
40
|
+
- name: Build
|
|
41
|
+
run: uv build
|
|
42
|
+
|
|
43
|
+
- name: Generate changelog
|
|
44
|
+
run: uvx git-cliff --latest --strip header -o RELEASE_NOTES.md
|
|
45
|
+
|
|
46
|
+
- name: Upload artifacts
|
|
47
|
+
uses: actions/upload-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: build-artifacts
|
|
50
|
+
path: dist/
|
|
51
|
+
retention-days: 1
|
|
52
|
+
|
|
53
|
+
- name: Create release and upload artifacts
|
|
54
|
+
env:
|
|
55
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
56
|
+
run: |
|
|
57
|
+
gh release create ${{ steps.version.outputs.version }} dist/* \
|
|
58
|
+
--title "${{ steps.version.outputs.version }}" \
|
|
59
|
+
--notes-file RELEASE_NOTES.md \
|
|
60
|
+
--target main
|
|
61
|
+
|
|
62
|
+
container:
|
|
63
|
+
needs: release
|
|
64
|
+
if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/')
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
permissions:
|
|
67
|
+
packages: write
|
|
68
|
+
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v4
|
|
71
|
+
|
|
72
|
+
- name: Extract version from branch name
|
|
73
|
+
id: version
|
|
74
|
+
run: |
|
|
75
|
+
VERSION=${GITHUB_HEAD_REF#release/}
|
|
76
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
77
|
+
|
|
78
|
+
- name: Compute container image tag
|
|
79
|
+
id: image
|
|
80
|
+
run: |
|
|
81
|
+
IMAGE_NAME=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
|
|
82
|
+
echo "name=$IMAGE_NAME" >> $GITHUB_OUTPUT
|
|
83
|
+
|
|
84
|
+
- name: Download artifacts
|
|
85
|
+
uses: actions/download-artifact@v4
|
|
86
|
+
with:
|
|
87
|
+
name: build-artifacts
|
|
88
|
+
path: dist/
|
|
89
|
+
|
|
90
|
+
- name: Log in to GHCR
|
|
91
|
+
uses: docker/login-action@v3
|
|
92
|
+
with:
|
|
93
|
+
registry: ghcr.io
|
|
94
|
+
username: ${{ github.actor }}
|
|
95
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
96
|
+
|
|
97
|
+
- name: Build and push container image
|
|
98
|
+
uses: docker/build-push-action@v6
|
|
99
|
+
with:
|
|
100
|
+
context: .
|
|
101
|
+
file: ./Containerfile
|
|
102
|
+
push: true
|
|
103
|
+
tags: |
|
|
104
|
+
ghcr.io/${{ steps.image.outputs.name }}:${{ steps.version.outputs.version }}
|
|
105
|
+
ghcr.io/${{ steps.image.outputs.name }}:latest
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.egg-info/
|
|
7
|
+
*.egg
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
wheels/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# uv
|
|
18
|
+
.uv/
|
|
19
|
+
|
|
20
|
+
# Test / coverage
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
coverage.xml
|
|
25
|
+
|
|
26
|
+
# Build output
|
|
27
|
+
.dist/
|
|
28
|
+
.run/
|
|
29
|
+
|
|
30
|
+
# Git worktrees checked out inside the repo
|
|
31
|
+
.wk-*/
|
|
32
|
+
|
|
33
|
+
# MkDocs
|
|
34
|
+
site/
|
|
35
|
+
|
|
36
|
+
# Editors
|
|
37
|
+
.idea/
|
|
38
|
+
.vscode/
|
|
39
|
+
*.swp
|
|
40
|
+
*.swo
|
|
41
|
+
|
|
42
|
+
# OS
|
|
43
|
+
.DS_Store
|
|
44
|
+
Thumbs.db
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "docs-writer",
|
|
3
|
+
"description": "Maintains the MkDocs documentation site under docs/. Writes and edits doc content, mkdocs.yml nav, and verifies builds. Never touches Python source.",
|
|
4
|
+
"model": "claude-sonnet-4.6",
|
|
5
|
+
"prompt": "You are a technical writer maintaining the margot MkDocs site under docs/. FEATURES.md is the authoritative source of truth for behavior, architecture, commands, config, and OCI media types — docs must never contradict it. .kiro/steering/documentation.md governs doc style, audience separation, and structure; follow it exactly. When a doc page and FEATURES.md disagree, FEATURES.md wins — fix the doc, don't work around it. New user-facing behavior belongs in FEATURES.md first; you follow, you don't lead. Before writing or editing a page, read FEATURES.md and the relevant steering files. After any change under docs/ or to mkdocs.yml, run `make docs-check` (strict build, warnings as errors) and fix any failures before considering the change done. Never modify Python source, tests, or non-doc config — if a doc gap reveals a product or code issue, report it instead of fixing code. You must never edit pyproject.toml or uv.lock directly (the write tool blocks this). If a docs dependency is needed (e.g. an mkdocs plugin), add it with `uv add <package> --group docs` — never hand-edit the dependency group.",
|
|
6
|
+
"mcpServers": {},
|
|
7
|
+
"tools": [
|
|
8
|
+
"read",
|
|
9
|
+
"write",
|
|
10
|
+
"grep",
|
|
11
|
+
"glob",
|
|
12
|
+
"code",
|
|
13
|
+
"shell",
|
|
14
|
+
"todo"
|
|
15
|
+
],
|
|
16
|
+
"allowedTools": [
|
|
17
|
+
"read",
|
|
18
|
+
"grep",
|
|
19
|
+
"glob",
|
|
20
|
+
"code",
|
|
21
|
+
"todo"
|
|
22
|
+
],
|
|
23
|
+
"toolsSettings": {
|
|
24
|
+
"read": {
|
|
25
|
+
"allowedPaths": [
|
|
26
|
+
"**"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"write": {
|
|
30
|
+
"allowedPaths": [
|
|
31
|
+
"docs/**",
|
|
32
|
+
"mkdocs.yml",
|
|
33
|
+
"*.md",
|
|
34
|
+
".kiro/steering/documentation.md"
|
|
35
|
+
],
|
|
36
|
+
"deniedPaths": [
|
|
37
|
+
"**/*.py",
|
|
38
|
+
"src/**",
|
|
39
|
+
"tests/**",
|
|
40
|
+
"pyproject.toml",
|
|
41
|
+
"uv.lock"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"shell": {
|
|
45
|
+
"autoAllowReadonly": true,
|
|
46
|
+
"denyByDefault": true,
|
|
47
|
+
"allowedCommands": [
|
|
48
|
+
"make.*",
|
|
49
|
+
"uv.*",
|
|
50
|
+
"git.*"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"resources": [
|
|
55
|
+
"file://.kiro/steering/documentation.md",
|
|
56
|
+
"file://.kiro/steering/oci-media-types.md",
|
|
57
|
+
"file://FEATURES.md",
|
|
58
|
+
"file://AGENTS.md"
|
|
59
|
+
],
|
|
60
|
+
"hooks": {},
|
|
61
|
+
"includeMcpJson": true,
|
|
62
|
+
"welcomeMessage": "docs-writer ready. I maintain docs/ against FEATURES.md and documentation.md. I don't touch source code."
|
|
63
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "planner",
|
|
3
|
+
"description": "Sprint planner: locates TODO items, forms a plan, and delegates implementation to dev agent. Never writes code.",
|
|
4
|
+
"model": "claude-sonnet-5",
|
|
5
|
+
"prompt": "You are a senior technical planner. Your role is exclusively investigating, planning and delegation — you never write, edit, or create code files.\n\nWorkflow on every request:\n1. Define a clear plan with explicit designs, key aspect and checkable steps/aspects. Search on the web if needed.\n2. Summary plan and get final approval.\n3. Delegate the full plan to the dev agent for implementation.\n4. Report back the dev agent output and a brief summary of what was done.\n\nHard constraints:\n- You MUST NOT write, edit, or create any source or test file (no .py, .toml, .yaml, .sh, etc.).\n- You MUST NOT produce code blocks intended to be applied to files.\n- You MAY write or edit Markdown files (.md) and files under .kiro/ (specs, steering, notes, task files).\n- You MAY create planning notes, task lists, or spec files to support future work.\n- When delegating, provide dev agent with the full plan, relevant file paths and a clear definition of done (tests pass, TODO removed, changes committed).\n- After the dev agent completes, instruct it to commit all changes with a meaningful commit message (conventional commits format: `feat:`, `fix:`, `test:`, etc.). The commit is part of the definition of done — a patch is not complete until it is committed.",
|
|
6
|
+
"mcpServers": {},
|
|
7
|
+
"tools": [
|
|
8
|
+
"code",
|
|
9
|
+
"delegate",
|
|
10
|
+
"glob",
|
|
11
|
+
"grep",
|
|
12
|
+
"read",
|
|
13
|
+
"shell",
|
|
14
|
+
"subagent",
|
|
15
|
+
"todo",
|
|
16
|
+
"tool_search",
|
|
17
|
+
"web_fetch",
|
|
18
|
+
"web_search",
|
|
19
|
+
"write"
|
|
20
|
+
],
|
|
21
|
+
"allowedTools": [
|
|
22
|
+
"code",
|
|
23
|
+
"delegate",
|
|
24
|
+
"glob",
|
|
25
|
+
"grep",
|
|
26
|
+
"read",
|
|
27
|
+
"shell",
|
|
28
|
+
"subagent",
|
|
29
|
+
"todo",
|
|
30
|
+
"tool_search",
|
|
31
|
+
"web_fetch",
|
|
32
|
+
"web_search",
|
|
33
|
+
"write"
|
|
34
|
+
],
|
|
35
|
+
"toolsSettings": {
|
|
36
|
+
"read": {
|
|
37
|
+
"allowedPaths": [
|
|
38
|
+
"**"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"write": {
|
|
42
|
+
"allowedPaths": [
|
|
43
|
+
"**/*.md",
|
|
44
|
+
".kiro/**"
|
|
45
|
+
],
|
|
46
|
+
"deniedPaths": [
|
|
47
|
+
"**/*.py",
|
|
48
|
+
"**/*.toml",
|
|
49
|
+
"**/*.cfg",
|
|
50
|
+
"**/*.ini",
|
|
51
|
+
"**/*.yaml",
|
|
52
|
+
"**/*.yml",
|
|
53
|
+
"**/*.json",
|
|
54
|
+
"**/*.txt",
|
|
55
|
+
"**/*.sh"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"shell": {
|
|
59
|
+
"autoAllowReadonly": true,
|
|
60
|
+
"denyByDefault": true,
|
|
61
|
+
"allowedCommands": [
|
|
62
|
+
"find.*",
|
|
63
|
+
"grep.*",
|
|
64
|
+
"make.*"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"subagent": {
|
|
68
|
+
"availableAgents": [
|
|
69
|
+
"python-dev"
|
|
70
|
+
],
|
|
71
|
+
"trustedAgents": [
|
|
72
|
+
"python-dev"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"resources": [
|
|
77
|
+
"file://.kiro/steering/code-conventions.md",
|
|
78
|
+
"file://.kiro/steering/oci-media-types.md",
|
|
79
|
+
"file://AGENTS.md",
|
|
80
|
+
"file://FEATURES.md"
|
|
81
|
+
],
|
|
82
|
+
"hooks": {},
|
|
83
|
+
"keyboardShortcut": "ctrl+shift+p",
|
|
84
|
+
"welcomeMessage": "Planner ready. I'll locate TODOs, build a plan, and hand off to python-dev. I don't write code."
|
|
85
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "python-dev",
|
|
3
|
+
"description": "Senior Python developer agent for building tooling.",
|
|
4
|
+
"prompt": " You are a senior Python developer. You build tooling based on user instructions. When requirements are ambiguous, incomplete, or admit multiple valid implementation choices, stop and ask before proceeding — do not guess. Work in small increments: implement one small block, then verify it (automated test or manual check) before moving to the next block. Always use the project's virtualenv when running Python or tools. Invoke via uv run <cmd> or .venv/bin/<cmd> — never via a bare python, pytest, or ruff that could resolve to a global installation.",
|
|
5
|
+
"mcpServers": {},
|
|
6
|
+
"tools": [
|
|
7
|
+
"*"
|
|
8
|
+
],
|
|
9
|
+
"toolAliases": {},
|
|
10
|
+
"allowedTools": [
|
|
11
|
+
"code",
|
|
12
|
+
"fs_read",
|
|
13
|
+
"fs_write",
|
|
14
|
+
"glob",
|
|
15
|
+
"grep",
|
|
16
|
+
"tool_search",
|
|
17
|
+
"delegate",
|
|
18
|
+
"knowledge",
|
|
19
|
+
"todo"
|
|
20
|
+
],
|
|
21
|
+
"resources": [
|
|
22
|
+
"file://.kiro/steering/code-conventions.md",
|
|
23
|
+
"file://AGENTS.md",
|
|
24
|
+
"skill://~/.kiro/skills/*/SKILL.md"
|
|
25
|
+
],
|
|
26
|
+
"hooks": {},
|
|
27
|
+
"toolsSettings": {
|
|
28
|
+
"read": {
|
|
29
|
+
"allowedPaths": [
|
|
30
|
+
"**"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"write": {
|
|
34
|
+
"allowedPaths": [
|
|
35
|
+
"**"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"execute_bash": {
|
|
39
|
+
"autoAllowReadonly": true,
|
|
40
|
+
"allowedCommands": [
|
|
41
|
+
"diff.*",
|
|
42
|
+
"find . .*",
|
|
43
|
+
"gh.*",
|
|
44
|
+
"git.*",
|
|
45
|
+
"grep.*",
|
|
46
|
+
"ls.*",
|
|
47
|
+
"make.*",
|
|
48
|
+
"pdm.*",
|
|
49
|
+
"podman.*",
|
|
50
|
+
"sed.*",
|
|
51
|
+
"source .venv/bin/activate.*",
|
|
52
|
+
"timeout.*",
|
|
53
|
+
"true.*",
|
|
54
|
+
"uv.*"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"includeMcpJson": true,
|
|
59
|
+
"model": null
|
|
60
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-quality-enhancement
|
|
3
|
+
description: >
|
|
4
|
+
Find and fix code quality regressions in margot: ruff lint violations, low test
|
|
5
|
+
coverage, and global (non-selective) imports. Use when asked to improve code
|
|
6
|
+
quality, clean up lint, raise coverage, or fix import style — not on every
|
|
7
|
+
request.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Code Quality Enhancement Skill
|
|
11
|
+
|
|
12
|
+
Three independent triggers, each with its own workflow. Run only the one(s) the
|
|
13
|
+
user asked for — do not run all three unless explicitly asked to do a full pass.
|
|
14
|
+
|
|
15
|
+
## When to use
|
|
16
|
+
|
|
17
|
+
Only when explicitly asked to improve code quality, fix lint, raise test coverage, or
|
|
18
|
+
fix import style. Do not run proactively during unrelated feature or bugfix work.
|
|
19
|
+
|
|
20
|
+
## Trigger 1 — ruff lint
|
|
21
|
+
|
|
22
|
+
1. Run `make lint` (`ruff check --no-fix src/ tests/`) and capture the full output.
|
|
23
|
+
2. Read each flagged file's surrounding context — not just the flagged line — before
|
|
24
|
+
deciding on a fix.
|
|
25
|
+
3. Build a plan grouped by rule code, not a one-off patch per line.
|
|
26
|
+
4. For each violation, decide real fix vs. suppress-with-`noqa`:
|
|
27
|
+
- **Default to a real fix.** `select = ["ALL"]` in `pyproject.toml` is deliberate —
|
|
28
|
+
the project wants the strict ruleset enforced, not relaxed.
|
|
29
|
+
- **`# noqa` is legitimate only when:** the rule is a false positive for this exact
|
|
30
|
+
case, or fixing it would fight an established pattern already accepted in
|
|
31
|
+
`pyproject.toml`'s `ignore` list philosophy (e.g. Typer's bool positional args,
|
|
32
|
+
inline exception messages). If in doubt, treat it as a case-by-case judgment,
|
|
33
|
+
not a default — document the reason in the `noqa` comment
|
|
34
|
+
(`# noqa: RULE — reason`).
|
|
35
|
+
- **Never blanket-suppress** a whole file or add a rule to the project-wide
|
|
36
|
+
`ignore` list to make a violation disappear. That is a scope decision for the
|
|
37
|
+
user, not an automatic fix.
|
|
38
|
+
5. Delegate the grouped fix plan to the `python-dev` agent with the plan, affected
|
|
39
|
+
files, and the ruff rule codes involved.
|
|
40
|
+
6. Definition of done: `make lint` passes clean, changes committed.
|
|
41
|
+
|
|
42
|
+
## Trigger 2 — low test coverage
|
|
43
|
+
|
|
44
|
+
1. Run `make test` (`uv run pytest`, which already runs with
|
|
45
|
+
`--cov=margot --cov-report=term-missing --cov-fail-under=90`) and capture the
|
|
46
|
+
per-file coverage table from the terminal report.
|
|
47
|
+
2. Select the 1-2 files with the lowest coverage — not every under-covered file at
|
|
48
|
+
once. Read the file and its existing test file (if any) to see what's actually
|
|
49
|
+
untested (the `Missing` line-number ranges in the report point at this directly).
|
|
50
|
+
3. Build a short plan: what behavior is untested, what test(s) to add, which file(s)
|
|
51
|
+
they land in (mirror the existing `tests/unit/` / `tests/integration/` /
|
|
52
|
+
`tests/e2e/` split already used in this repo).
|
|
53
|
+
4. Delegate to `python-dev` with the plan and the specific uncovered line ranges.
|
|
54
|
+
Tests must assert real behavior — no stub tests that just exercise a line without
|
|
55
|
+
checking an outcome (same TDD rule as `code-conventions.md`).
|
|
56
|
+
5. Definition of done: `make test` passes, coverage for the targeted file(s)
|
|
57
|
+
measurably improves, changes committed.
|
|
58
|
+
|
|
59
|
+
## Trigger 3 — global (non-selective) imports
|
|
60
|
+
|
|
61
|
+
1. Search for violations:
|
|
62
|
+
```bash
|
|
63
|
+
grep -rn -E "^import " src/ tests/
|
|
64
|
+
```
|
|
65
|
+
This catches `import x` module-level imports; selective imports (`from x import y`)
|
|
66
|
+
are the required convention (see `code-conventions.md`) and won't match.
|
|
67
|
+
2. For each match, check whether a selective form is actually possible — a handful of
|
|
68
|
+
modules are conventionally imported as a namespace (e.g. `import margot.console as
|
|
69
|
+
console`, which the project's own conventions explicitly require — don't "fix" that
|
|
70
|
+
one). Distinguish real violations from accepted namespace-import patterns before
|
|
71
|
+
planning a change.
|
|
72
|
+
3. Build a plan: for each real violation, the selective import form it should become,
|
|
73
|
+
and every usage site in that file that needs updating to match (e.g. `pytest.raises`
|
|
74
|
+
→ `from pytest import raises` then all call sites).
|
|
75
|
+
4. Delegate to `python-dev` with the plan and file list.
|
|
76
|
+
5. Definition of done: `grep -rn -E "^import " src/ tests/` shows only accepted
|
|
77
|
+
namespace-import patterns, `make lint` and `make test` still pass, changes
|
|
78
|
+
committed.
|
|
79
|
+
|
|
80
|
+
## Common rules across all three triggers
|
|
81
|
+
|
|
82
|
+
- Always run the relevant `make` target yourself first — don't plan from memory or
|
|
83
|
+
assumption of what's currently failing.
|
|
84
|
+
- Group fixes into a coherent plan before delegating; don't delegate raw tool output.
|
|
85
|
+
- Delegate implementation to `python-dev` — this skill does not write code directly.
|
|
86
|
+
- A trigger is not done until its verification command passes clean and the fix is
|
|
87
|
+
committed (conventional commit format), matching the repo's definition-of-done
|
|
88
|
+
pattern used elsewhere (sprints, TODO fixes).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fix-todos
|
|
3
|
+
description: >
|
|
4
|
+
Locate, plan, and delegate fixes for # TODO(kiro): markers in the margot codebase.
|
|
5
|
+
Use only when explicitly asked to find, review, or fix TODOs — not on every planning
|
|
6
|
+
request.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Fix TODOs Skill
|
|
10
|
+
|
|
11
|
+
## When to use
|
|
12
|
+
|
|
13
|
+
Only when the user explicitly asks to find, triage, or fix TODO markers. Do not run
|
|
14
|
+
this workflow proactively on unrelated planning or implementation requests.
|
|
15
|
+
|
|
16
|
+
## Workflow
|
|
17
|
+
|
|
18
|
+
1. Search for TODO markers:
|
|
19
|
+
```bash
|
|
20
|
+
grep -rn "# TODO" --include="*.py" src/ tests/
|
|
21
|
+
```
|
|
22
|
+
Any author tag counts (`TODO(kiro):`, `TODO(<other>):`, bare `TODO:`) — bare TODOs are
|
|
23
|
+
a convention violation to flag, not to ignore (see `code-conventions.md`).
|
|
24
|
+
2. For each TODO found, read the surrounding function/class to understand what's
|
|
25
|
+
actually required — the TODO text alone is often incomplete context.
|
|
26
|
+
3. **If a TODO is ambiguous, or its fix implies a design decision (API shape, new
|
|
27
|
+
dependency, behavior change, breaking change), stop and ask the user before
|
|
28
|
+
proceeding.** Do not guess intent and do not delegate a design decision to the dev
|
|
29
|
+
agent — that decision is the user's to make, the same way sprint planning decisions
|
|
30
|
+
in this repo are locked with the user first.
|
|
31
|
+
4. Group related, unambiguous TODOs (same file, same feature) into a single plan rather
|
|
32
|
+
than one-off patches.
|
|
33
|
+
5. Build a short plan per group: what changes, which files, what test proves it's done.
|
|
34
|
+
6. Delegate implementation to the `python-dev` agent with the plan, file paths, and a
|
|
35
|
+
definition of done: tests pass, the TODO marker is removed, changes are committed
|
|
36
|
+
(conventional commit format).
|
|
37
|
+
7. Report back what was fixed and confirm no `# TODO` markers remain in the touched
|
|
38
|
+
scope.
|
|
39
|
+
|
|
40
|
+
## Conventions this enforces
|
|
41
|
+
|
|
42
|
+
- Correct format is `# TODO(kiro): ...` (ruff TD002) — bare `# TODO:` must be fixed to
|
|
43
|
+
include an author tag, not just left as-is.
|
|
44
|
+
- A TODO is not "done" until removed from source and its fix is committed — matching
|
|
45
|
+
the sprint definition-of-done rule ("No `# TODO` markers left from this sprint's work").
|
|
46
|
+
|
|
47
|
+
## Scope
|
|
48
|
+
|
|
49
|
+
Source and test files only (`src/`, `tests/`). Do not treat TODO-shaped text inside
|
|
50
|
+
`.kiro/steering/*.md` or sprint docs as code TODOs to fix — those are conventions
|
|
51
|
+
references, not action items.
|