skillroute 0.2.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.
- skillroute-0.2.0/.github/dependabot.yml +21 -0
- skillroute-0.2.0/.github/workflows/ci.yml +172 -0
- skillroute-0.2.0/.github/workflows/release.yml +144 -0
- skillroute-0.2.0/.gitignore +25 -0
- skillroute-0.2.0/CHANGELOG.md +146 -0
- skillroute-0.2.0/CONTRIBUTING.md +55 -0
- skillroute-0.2.0/LICENSE +21 -0
- skillroute-0.2.0/ONBOARDING.md +127 -0
- skillroute-0.2.0/PKG-INFO +220 -0
- skillroute-0.2.0/README.md +190 -0
- skillroute-0.2.0/SECURITY.md +18 -0
- skillroute-0.2.0/docs/agent-setup.md +227 -0
- skillroute-0.2.0/docs/assets/screenshot-route.svg +21 -0
- skillroute-0.2.0/docs/assets/screenshot-skill-atlas.png +0 -0
- skillroute-0.2.0/docs/assets/screenshot-traces.svg +27 -0
- skillroute-0.2.0/docs/astra-backend.md +65 -0
- skillroute-0.2.0/docs/evals.md +83 -0
- skillroute-0.2.0/docs/getting-started.md +106 -0
- skillroute-0.2.0/docs/harnesses.md +218 -0
- skillroute-0.2.0/docs/mcp-server.md +89 -0
- skillroute-0.2.0/docs/metadata-overlays.md +51 -0
- skillroute-0.2.0/docs/roadmap.md +99 -0
- skillroute-0.2.0/docs/route-observability.md +51 -0
- skillroute-0.2.0/docs/skill-atlas.md +79 -0
- skillroute-0.2.0/examples/evals/dogfood_routes.json +21 -0
- skillroute-0.2.0/examples/evals/golden_routes.json +21 -0
- skillroute-0.2.0/examples/skills/astra-vector-backend/SKILL.md +18 -0
- skillroute-0.2.0/examples/skills/mcp-server-patterns/SKILL.md +20 -0
- skillroute-0.2.0/examples/skills/mcp-server-patterns/templates/tool-template.md +5 -0
- skillroute-0.2.0/examples/skills/python-patterns/SKILL.md +18 -0
- skillroute-0.2.0/examples/skills/python-testing/SKILL.md +18 -0
- skillroute-0.2.0/harnesses/amp.toml +17 -0
- skillroute-0.2.0/harnesses/claude-code.toml +51 -0
- skillroute-0.2.0/harnesses/claude-desktop.toml +22 -0
- skillroute-0.2.0/harnesses/codex.toml +43 -0
- skillroute-0.2.0/harnesses/cursor.toml +19 -0
- skillroute-0.2.0/harnesses/gemini-cli.toml +22 -0
- skillroute-0.2.0/harnesses/goose.toml +29 -0
- skillroute-0.2.0/harnesses/hermes.toml +50 -0
- skillroute-0.2.0/harnesses/ibm-bob.toml +22 -0
- skillroute-0.2.0/harnesses/opencode.toml +33 -0
- skillroute-0.2.0/harnesses/pi.toml +41 -0
- skillroute-0.2.0/harnesses/vscode.toml +19 -0
- skillroute-0.2.0/harnesses/windsurf.toml +18 -0
- skillroute-0.2.0/harnesses/zed.toml +29 -0
- skillroute-0.2.0/hatch_build.py +52 -0
- skillroute-0.2.0/mcp/LICENSE +21 -0
- skillroute-0.2.0/mcp/README.md +23 -0
- skillroute-0.2.0/mcp/package-lock.json +1573 -0
- skillroute-0.2.0/mcp/package.json +51 -0
- skillroute-0.2.0/mcp/src/bridge.ts +154 -0
- skillroute-0.2.0/mcp/src/index.ts +96 -0
- skillroute-0.2.0/mcp/tests/bridge-command.test.mjs +75 -0
- skillroute-0.2.0/mcp/tests/mcp-smoke.mjs +83 -0
- skillroute-0.2.0/mcp/tsconfig.json +16 -0
- skillroute-0.2.0/pyproject.toml +77 -0
- skillroute-0.2.0/scripts/bootstrap.sh +56 -0
- skillroute-0.2.0/scripts/install.sh +339 -0
- skillroute-0.2.0/src/skillroute/__init__.py +15 -0
- skillroute-0.2.0/src/skillroute/__main__.py +5 -0
- skillroute-0.2.0/src/skillroute/atlas.py +263 -0
- skillroute-0.2.0/src/skillroute/attribution.py +82 -0
- skillroute-0.2.0/src/skillroute/backends.py +566 -0
- skillroute-0.2.0/src/skillroute/catalog.py +750 -0
- skillroute-0.2.0/src/skillroute/cli.py +988 -0
- skillroute-0.2.0/src/skillroute/client_setup.py +70 -0
- skillroute-0.2.0/src/skillroute/context.py +92 -0
- skillroute-0.2.0/src/skillroute/dogfood.py +78 -0
- skillroute-0.2.0/src/skillroute/evals.py +70 -0
- skillroute-0.2.0/src/skillroute/harness_doctor.py +438 -0
- skillroute-0.2.0/src/skillroute/harness_render.py +494 -0
- skillroute-0.2.0/src/skillroute/harness_setup.py +339 -0
- skillroute-0.2.0/src/skillroute/harnesses.py +354 -0
- skillroute-0.2.0/src/skillroute/mcp_setup.py +91 -0
- skillroute-0.2.0/src/skillroute/metadata.py +152 -0
- skillroute-0.2.0/src/skillroute/migrations.py +327 -0
- skillroute-0.2.0/src/skillroute/models.py +104 -0
- skillroute-0.2.0/src/skillroute/overlays.py +44 -0
- skillroute-0.2.0/src/skillroute/parser.py +370 -0
- skillroute-0.2.0/src/skillroute/py.typed +0 -0
- skillroute-0.2.0/src/skillroute/rerankers.py +68 -0
- skillroute-0.2.0/src/skillroute/routing.py +368 -0
- skillroute-0.2.0/src/skillroute/text.py +79 -0
- skillroute-0.2.0/src/skillroute/tuning.py +200 -0
- skillroute-0.2.0/src/skillroute/ui_server.py +199 -0
- skillroute-0.2.0/tests/conftest.py +20 -0
- skillroute-0.2.0/tests/fixtures/golden_routes.json +26 -0
- skillroute-0.2.0/tests/fixtures/schema_v1.sql +66 -0
- skillroute-0.2.0/tests/fixtures/skills/astra-vector-backend/SKILL.md +11 -0
- skillroute-0.2.0/tests/fixtures/skills/mcp-server-patterns/SKILL.md +20 -0
- skillroute-0.2.0/tests/fixtures/skills/mcp-server-patterns/templates/tool.md +4 -0
- skillroute-0.2.0/tests/fixtures/skills/python-testing/SKILL.md +12 -0
- skillroute-0.2.0/tests/test_atlas.py +126 -0
- skillroute-0.2.0/tests/test_attribution.py +136 -0
- skillroute-0.2.0/tests/test_backends.py +476 -0
- skillroute-0.2.0/tests/test_catalog.py +227 -0
- skillroute-0.2.0/tests/test_cli.py +927 -0
- skillroute-0.2.0/tests/test_client_setup.py +318 -0
- skillroute-0.2.0/tests/test_context.py +88 -0
- skillroute-0.2.0/tests/test_dogfood.py +106 -0
- skillroute-0.2.0/tests/test_evals.py +17 -0
- skillroute-0.2.0/tests/test_harness_doctor.py +290 -0
- skillroute-0.2.0/tests/test_harnesses.py +533 -0
- skillroute-0.2.0/tests/test_metadata.py +127 -0
- skillroute-0.2.0/tests/test_migrations.py +279 -0
- skillroute-0.2.0/tests/test_parser.py +74 -0
- skillroute-0.2.0/tests/test_rerankers.py +90 -0
- skillroute-0.2.0/tests/test_routing.py +113 -0
- skillroute-0.2.0/tests/test_scripts.py +26 -0
- skillroute-0.2.0/tests/test_tuning.py +229 -0
- skillroute-0.2.0/tests/test_ui_server.py +162 -0
- skillroute-0.2.0/uv.lock +814 -0
- skillroute-0.2.0/web/dist/assets/index-I0Sgrz_R.css +1 -0
- skillroute-0.2.0/web/dist/assets/index-ylXOtl-c.js +15 -0
- skillroute-0.2.0/web/dist/index.html +13 -0
- skillroute-0.2.0/web/eslint.config.js +40 -0
- skillroute-0.2.0/web/index.html +12 -0
- skillroute-0.2.0/web/package-lock.json +3689 -0
- skillroute-0.2.0/web/package.json +32 -0
- skillroute-0.2.0/web/src/App.tsx +248 -0
- skillroute-0.2.0/web/src/api.ts +28 -0
- skillroute-0.2.0/web/src/components/graph-nodes.tsx +42 -0
- skillroute-0.2.0/web/src/components/inspector.tsx +277 -0
- skillroute-0.2.0/web/src/components/panels.tsx +238 -0
- skillroute-0.2.0/web/src/components/primitives.tsx +80 -0
- skillroute-0.2.0/web/src/components/route-preview.tsx +77 -0
- skillroute-0.2.0/web/src/graph.test.ts +123 -0
- skillroute-0.2.0/web/src/graph.ts +188 -0
- skillroute-0.2.0/web/src/main.tsx +11 -0
- skillroute-0.2.0/web/src/styles.css +1186 -0
- skillroute-0.2.0/web/src/types.ts +132 -0
- skillroute-0.2.0/web/src/ui.ts +2 -0
- skillroute-0.2.0/web/src/util.ts +22 -0
- skillroute-0.2.0/web/src/vite-env.d.ts +1 -0
- skillroute-0.2.0/web/tsconfig.json +21 -0
- skillroute-0.2.0/web/vite.config.ts +13 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: github-actions
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
|
|
8
|
+
- package-ecosystem: npm
|
|
9
|
+
directory: "/mcp"
|
|
10
|
+
schedule:
|
|
11
|
+
interval: weekly
|
|
12
|
+
|
|
13
|
+
- package-ecosystem: npm
|
|
14
|
+
directory: "/web"
|
|
15
|
+
schedule:
|
|
16
|
+
interval: weekly
|
|
17
|
+
|
|
18
|
+
- package-ecosystem: uv
|
|
19
|
+
directory: "/"
|
|
20
|
+
schedule:
|
|
21
|
+
interval: weekly
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
python:
|
|
13
|
+
name: Python ${{ matrix.python-version }}
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.11", "3.13"]
|
|
19
|
+
steps:
|
|
20
|
+
- name: Check out repository
|
|
21
|
+
uses: actions/checkout@v7
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
25
|
+
with:
|
|
26
|
+
cache-suffix: python-${{ matrix.python-version }}
|
|
27
|
+
|
|
28
|
+
- name: Set up Python
|
|
29
|
+
uses: actions/setup-python@v7
|
|
30
|
+
with:
|
|
31
|
+
python-version: ${{ matrix.python-version }}
|
|
32
|
+
|
|
33
|
+
- name: Verify lockfile is up to date
|
|
34
|
+
run: uv lock --check
|
|
35
|
+
|
|
36
|
+
- name: Run tests with coverage
|
|
37
|
+
run: uv run --frozen --extra dev pytest --cov=skillroute --cov-report=term-missing --cov-fail-under=80
|
|
38
|
+
|
|
39
|
+
- name: Run lint
|
|
40
|
+
run: uv run --frozen --extra dev ruff check .
|
|
41
|
+
|
|
42
|
+
- name: Run type check
|
|
43
|
+
run: uv run --frozen --extra dev mypy
|
|
44
|
+
|
|
45
|
+
- name: Run example golden routes
|
|
46
|
+
run: uv run --frozen --extra dev skillroute eval run --fresh --index-root examples/skills --cases examples/evals/golden_routes.json
|
|
47
|
+
|
|
48
|
+
- name: Audit Python dependencies
|
|
49
|
+
run: |
|
|
50
|
+
uv export --frozen --no-emit-project --no-hashes --format requirements-txt -o requirements-audit.txt
|
|
51
|
+
uvx pip-audit --no-deps -r requirements-audit.txt
|
|
52
|
+
|
|
53
|
+
web:
|
|
54
|
+
name: Web
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
steps:
|
|
57
|
+
- name: Check out repository
|
|
58
|
+
uses: actions/checkout@v7
|
|
59
|
+
|
|
60
|
+
- name: Set up Node
|
|
61
|
+
uses: actions/setup-node@v7
|
|
62
|
+
with:
|
|
63
|
+
node-version: "22"
|
|
64
|
+
cache: npm
|
|
65
|
+
cache-dependency-path: web/package-lock.json
|
|
66
|
+
|
|
67
|
+
- name: Install web dependencies
|
|
68
|
+
working-directory: web
|
|
69
|
+
run: npm ci
|
|
70
|
+
|
|
71
|
+
- name: Typecheck web
|
|
72
|
+
working-directory: web
|
|
73
|
+
run: npm run typecheck
|
|
74
|
+
|
|
75
|
+
- name: Lint web
|
|
76
|
+
working-directory: web
|
|
77
|
+
run: npm run lint
|
|
78
|
+
|
|
79
|
+
- name: Test web
|
|
80
|
+
working-directory: web
|
|
81
|
+
run: npm run test
|
|
82
|
+
|
|
83
|
+
- name: Build web
|
|
84
|
+
working-directory: web
|
|
85
|
+
run: npm run build
|
|
86
|
+
|
|
87
|
+
- name: Audit web dependencies
|
|
88
|
+
working-directory: web
|
|
89
|
+
run: npm audit --audit-level=high
|
|
90
|
+
|
|
91
|
+
mcp:
|
|
92
|
+
name: MCP
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
steps:
|
|
95
|
+
- name: Check out repository
|
|
96
|
+
uses: actions/checkout@v7
|
|
97
|
+
|
|
98
|
+
- name: Install uv
|
|
99
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
100
|
+
with:
|
|
101
|
+
cache-suffix: mcp
|
|
102
|
+
|
|
103
|
+
- name: Set up Python
|
|
104
|
+
uses: actions/setup-python@v7
|
|
105
|
+
with:
|
|
106
|
+
python-version: "3.13"
|
|
107
|
+
|
|
108
|
+
- name: Set up Node
|
|
109
|
+
uses: actions/setup-node@v7
|
|
110
|
+
with:
|
|
111
|
+
node-version: "22"
|
|
112
|
+
cache: npm
|
|
113
|
+
cache-dependency-path: mcp/package-lock.json
|
|
114
|
+
|
|
115
|
+
- name: Install MCP dependencies
|
|
116
|
+
working-directory: mcp
|
|
117
|
+
run: npm ci
|
|
118
|
+
|
|
119
|
+
- name: Build MCP server
|
|
120
|
+
working-directory: mcp
|
|
121
|
+
run: npm run build
|
|
122
|
+
|
|
123
|
+
- name: Typecheck MCP server
|
|
124
|
+
working-directory: mcp
|
|
125
|
+
run: npm run typecheck
|
|
126
|
+
|
|
127
|
+
- name: Test MCP server
|
|
128
|
+
working-directory: mcp
|
|
129
|
+
run: npm test
|
|
130
|
+
|
|
131
|
+
- name: Verify MCP package contents
|
|
132
|
+
working-directory: mcp
|
|
133
|
+
run: npm pack --dry-run
|
|
134
|
+
|
|
135
|
+
- name: Audit MCP dependencies
|
|
136
|
+
working-directory: mcp
|
|
137
|
+
run: npm audit --audit-level=high
|
|
138
|
+
|
|
139
|
+
- name: Smoke test MCP tools
|
|
140
|
+
working-directory: mcp
|
|
141
|
+
run: npm run smoke
|
|
142
|
+
|
|
143
|
+
package:
|
|
144
|
+
name: Package
|
|
145
|
+
runs-on: ubuntu-latest
|
|
146
|
+
steps:
|
|
147
|
+
- name: Check out repository
|
|
148
|
+
uses: actions/checkout@v7
|
|
149
|
+
|
|
150
|
+
- name: Install uv
|
|
151
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
152
|
+
with:
|
|
153
|
+
cache-suffix: package
|
|
154
|
+
|
|
155
|
+
- name: Set up Python
|
|
156
|
+
uses: actions/setup-python@v7
|
|
157
|
+
with:
|
|
158
|
+
python-version: "3.13"
|
|
159
|
+
|
|
160
|
+
- name: Set up Node
|
|
161
|
+
uses: actions/setup-node@v7
|
|
162
|
+
with:
|
|
163
|
+
node-version: "22"
|
|
164
|
+
|
|
165
|
+
- name: Build sdist and wheel
|
|
166
|
+
run: uv build
|
|
167
|
+
|
|
168
|
+
- name: Check distribution metadata
|
|
169
|
+
run: uvx twine check dist/*
|
|
170
|
+
|
|
171
|
+
- name: Verify wheel bundles the web UI
|
|
172
|
+
run: unzip -l dist/*.whl | grep -q "skillroute/_web/index.html"
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
name: Build artifacts
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Check out repository
|
|
16
|
+
uses: actions/checkout@v7
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v9.0.0
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v7
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.13"
|
|
25
|
+
|
|
26
|
+
- name: Set up Node
|
|
27
|
+
uses: actions/setup-node@v7
|
|
28
|
+
with:
|
|
29
|
+
node-version: "22"
|
|
30
|
+
|
|
31
|
+
# The tag is the only thing a human types here, and the version published
|
|
32
|
+
# comes from package metadata, not from the tag. Without this check,
|
|
33
|
+
# tagging v0.2.0 while pyproject.toml still says 0.1.0 publishes 0.1.0 to
|
|
34
|
+
# PyPI under a release titled v0.2.0 -- and a PyPI version can never be
|
|
35
|
+
# reused, so there is no clean recovery.
|
|
36
|
+
- name: Verify the tag matches both package versions
|
|
37
|
+
run: |
|
|
38
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
39
|
+
py=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
|
|
40
|
+
npm_version=$(node -p "require('./mcp/package.json').version")
|
|
41
|
+
echo "tag=$tag pyproject=$py package.json=$npm_version"
|
|
42
|
+
if [ "$tag" != "$py" ] || [ "$tag" != "$npm_version" ]; then
|
|
43
|
+
echo "::error::Tag $GITHUB_REF_NAME disagrees with pyproject.toml ($py) and/or mcp/package.json ($npm_version)."
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
- name: Build sdist and wheel (bundles the web UI)
|
|
48
|
+
run: uv build
|
|
49
|
+
|
|
50
|
+
- name: Check distribution metadata
|
|
51
|
+
run: uvx twine check dist/*
|
|
52
|
+
|
|
53
|
+
- name: Verify wheel bundles the web UI
|
|
54
|
+
run: unzip -l dist/*.whl | grep -q "skillroute/_web/index.html"
|
|
55
|
+
|
|
56
|
+
- name: Pack MCP server tarball
|
|
57
|
+
working-directory: mcp
|
|
58
|
+
run: |
|
|
59
|
+
npm ci
|
|
60
|
+
npm pack --pack-destination ../dist
|
|
61
|
+
|
|
62
|
+
- name: Upload artifacts
|
|
63
|
+
uses: actions/upload-artifact@v6
|
|
64
|
+
with:
|
|
65
|
+
name: release-artifacts
|
|
66
|
+
path: dist/*
|
|
67
|
+
|
|
68
|
+
github-release:
|
|
69
|
+
name: Create GitHub release
|
|
70
|
+
needs: build
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
permissions:
|
|
73
|
+
contents: write
|
|
74
|
+
steps:
|
|
75
|
+
- name: Check out repository
|
|
76
|
+
uses: actions/checkout@v7
|
|
77
|
+
|
|
78
|
+
- name: Download artifacts
|
|
79
|
+
uses: actions/download-artifact@v7
|
|
80
|
+
with:
|
|
81
|
+
name: release-artifacts
|
|
82
|
+
path: dist
|
|
83
|
+
|
|
84
|
+
- name: Create release with artifacts
|
|
85
|
+
env:
|
|
86
|
+
GH_TOKEN: ${{ github.token }}
|
|
87
|
+
run: |
|
|
88
|
+
gh release create "$GITHUB_REF_NAME" dist/* \
|
|
89
|
+
--title "$GITHUB_REF_NAME" \
|
|
90
|
+
--generate-notes
|
|
91
|
+
|
|
92
|
+
pypi:
|
|
93
|
+
name: Publish to PyPI
|
|
94
|
+
if: vars.PYPI_PUBLISH == 'true'
|
|
95
|
+
needs: build
|
|
96
|
+
runs-on: ubuntu-latest
|
|
97
|
+
environment: pypi
|
|
98
|
+
permissions:
|
|
99
|
+
id-token: write
|
|
100
|
+
steps:
|
|
101
|
+
- name: Download artifacts
|
|
102
|
+
uses: actions/download-artifact@v7
|
|
103
|
+
with:
|
|
104
|
+
name: release-artifacts
|
|
105
|
+
path: dist
|
|
106
|
+
|
|
107
|
+
- name: Remove non-PyPI artifacts
|
|
108
|
+
run: rm -f dist/*.tgz
|
|
109
|
+
|
|
110
|
+
- name: Publish via trusted publishing
|
|
111
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
112
|
+
|
|
113
|
+
npm:
|
|
114
|
+
name: Publish MCP server to npm
|
|
115
|
+
if: vars.NPM_PUBLISH == 'true'
|
|
116
|
+
needs: build
|
|
117
|
+
runs-on: ubuntu-latest
|
|
118
|
+
permissions:
|
|
119
|
+
# npm trusted publishing is OIDC: this replaces NPM_TOKEN entirely, so
|
|
120
|
+
# there is no long-lived credential in repo secrets to leak or rotate.
|
|
121
|
+
id-token: write
|
|
122
|
+
steps:
|
|
123
|
+
- name: Check out repository
|
|
124
|
+
uses: actions/checkout@v7
|
|
125
|
+
|
|
126
|
+
# Trusted publishing needs npm >= 11.5.1. Node 22 bundles npm 10.x even at
|
|
127
|
+
# its latest patch, so it cannot be used here; Node 24 bundles 11.17+,
|
|
128
|
+
# which clears the floor without installing anything.
|
|
129
|
+
#
|
|
130
|
+
# Do not "fix" this by adding `npm install -g npm@latest` on Node 22: that
|
|
131
|
+
# is what v0.2.0's first release attempt did, and it failed with
|
|
132
|
+
# EBADENGINE because npm 12 requires Node ^22.22.2 || ^24.15.0 while
|
|
133
|
+
# setup-node had pinned 22.14.0.
|
|
134
|
+
- name: Set up Node
|
|
135
|
+
uses: actions/setup-node@v7
|
|
136
|
+
with:
|
|
137
|
+
node-version: "24"
|
|
138
|
+
registry-url: "https://registry.npmjs.org"
|
|
139
|
+
|
|
140
|
+
- name: Publish
|
|
141
|
+
working-directory: mcp
|
|
142
|
+
run: |
|
|
143
|
+
npm ci
|
|
144
|
+
npm publish
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.coverage
|
|
2
|
+
.pytest_cache/
|
|
3
|
+
.ruff_cache/
|
|
4
|
+
.skillroute/
|
|
5
|
+
.venv/
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
*.pyc
|
|
9
|
+
|
|
10
|
+
.env
|
|
11
|
+
.env.*
|
|
12
|
+
!.env.example
|
|
13
|
+
|
|
14
|
+
requirements-audit.txt
|
|
15
|
+
|
|
16
|
+
mcp/build/
|
|
17
|
+
mcp/node_modules/
|
|
18
|
+
web/dist/
|
|
19
|
+
web/node_modules/
|
|
20
|
+
node_modules/
|
|
21
|
+
|
|
22
|
+
dist/
|
|
23
|
+
.mypy_cache/
|
|
24
|
+
htmlcov/
|
|
25
|
+
coverage.xml
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2026-08-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Harness packs.** Every agent tool SkillRoute supports is now one declarative
|
|
15
|
+
manifest in `harnesses/*.toml` describing detection, per-platform config paths,
|
|
16
|
+
and which install modes it offers. v0.1 encoded this as a hardcoded if/elif
|
|
17
|
+
chain plus a per-client detection function, so adding a tool meant editing
|
|
18
|
+
around seven places across two modules and three docs; adding one that fits an
|
|
19
|
+
existing config shape is now a data change with no Python. Six of the fourteen
|
|
20
|
+
shipped harnesses reuse the same shape unchanged. `tests/test_harnesses.py` is
|
|
21
|
+
parametrized over whatever is in `harnesses/`, so a new manifest is covered
|
|
22
|
+
automatically.
|
|
23
|
+
- Seven new harnesses: `pi`, `hermes`, `opencode`, `goose`, `gemini-cli`, `zed`,
|
|
24
|
+
and `amp` — joining the seven from v0.1, all migrated to manifests with
|
|
25
|
+
byte-identical generated output.
|
|
26
|
+
- Install modes beyond MCP: `acp`, `skills` (native skills-directory discovery
|
|
27
|
+
and projection), `hook`, `extension`, and `router_skill`. Where a harness lets
|
|
28
|
+
you register an extra skills directory (Hermes `external_dirs`, Pi's settings),
|
|
29
|
+
SkillRoute registers rather than copying — no duplication, no sync drift.
|
|
30
|
+
- Cross-platform config paths. Manifests declare `macos`/`linux`/`windows`
|
|
31
|
+
variants and the most specific match wins; `skillroute harness show --platform`
|
|
32
|
+
renders for a platform you are not on. v0.1 detection was macOS-only.
|
|
33
|
+
- `skillroute harness list | detect | show | install | doctor`, plus
|
|
34
|
+
[docs/harnesses.md](docs/harnesses.md) covering how to add a harness.
|
|
35
|
+
- `skillroute harness doctor` verifies a pack still matches reality: the manifest
|
|
36
|
+
declares a path for the current platform, every mode still renders, and the
|
|
37
|
+
config on disk names our server. It then runs the exact server command the
|
|
38
|
+
config points at and confirms it answers an MCP `initialize` handshake — the
|
|
39
|
+
one check that inspection cannot fake. Config paths for fourteen tools rot
|
|
40
|
+
silently, because `harness install` keeps reporting success while writing to a
|
|
41
|
+
file the tool no longer reads. An absent or unconfigured harness warns rather
|
|
42
|
+
than fails, so a non-zero exit means real breakage and the command works as a
|
|
43
|
+
CI gate (`--json`, `--no-probe`).
|
|
44
|
+
- `--server-source {local,npx}` on `harness show` and `harness install` chooses
|
|
45
|
+
whether a generated config starts the MCP server from a built checkout or from
|
|
46
|
+
the published `@skillroute/mcp-server` via `npx -y`. v0.1 hardcoded the
|
|
47
|
+
checkout path, which is why nothing outside a git clone could run SkillRoute.
|
|
48
|
+
The default stays `local` until the package is actually on npm, so this adds
|
|
49
|
+
the capability without emitting configs that resolve to nothing.
|
|
50
|
+
- Catalog schema v2 with real migration machinery. `skillroute.migrations`
|
|
51
|
+
defines ordered, named migrations; `Catalog.initialize()` detects the on-disk
|
|
52
|
+
version, takes a write lock (`BEGIN IMMEDIATE`) so a concurrent index and UI
|
|
53
|
+
server cannot both migrate, backs the file up before altering it, and refuses
|
|
54
|
+
a catalog written by a newer SkillRoute instead of corrupting it. Existing v1
|
|
55
|
+
catalogs upgrade in place; their traces are unpacked into the new columns
|
|
56
|
+
rather than discarded.
|
|
57
|
+
- Route traces now record who asked and what happened: `harness_id`,
|
|
58
|
+
`harness_version`, `surface`, `request_text`, `top_confidence`,
|
|
59
|
+
`second_confidence`, `catalog_fingerprint`, and the routing weights in effect.
|
|
60
|
+
A new `route_trace_candidates` table denormalizes every ranked candidate and
|
|
61
|
+
its score breakdown so analytics can use SQL instead of parsing response
|
|
62
|
+
blobs. `skillroute route --harness <id>` and `SKILLROUTE_HARNESS` set the
|
|
63
|
+
attribution; an unknown caller stays unknown rather than erroring.
|
|
64
|
+
- `Catalog.record_outcome()` and a `route_outcomes` table, so an agent can
|
|
65
|
+
report which skill it actually used. The rank it was offered at is resolved
|
|
66
|
+
from the recorded candidates rather than trusted from the caller.
|
|
67
|
+
- `route_trace_daily` aggregates every route on the day it happens. Raw traces
|
|
68
|
+
are still capped, but the rollup is not, so route counts, clarification rates,
|
|
69
|
+
and confidence distributions survive pruning and remain answerable over time.
|
|
70
|
+
- SQLite FTS5 retrieval backend (`--backend fts5`, alias `sqlite-fts5`):
|
|
71
|
+
local BM25 ranking with term-frequency and document-length normalization on
|
|
72
|
+
top of the existing token-overlap lexical score. Query input is escaped so
|
|
73
|
+
FTS5 syntax in requests is treated as literal terms. Available in the CLI,
|
|
74
|
+
bridge, and MCP server backend choices.
|
|
75
|
+
- Routing weights are now explicit and tunable: `RouteWeights` replaces the
|
|
76
|
+
hardcoded blend constants, `SKILLROUTE_WEIGHTS` overrides them per process,
|
|
77
|
+
and `skillroute eval tune` grid-searches weights against golden route cases
|
|
78
|
+
so changes are backed by eval evidence. Defaults are unchanged.
|
|
79
|
+
|
|
80
|
+
### Changed
|
|
81
|
+
|
|
82
|
+
- The npm release job publishes via npm trusted publishing (OIDC) instead of a
|
|
83
|
+
long-lived `NPM_TOKEN` secret, so there is no static credential in repo
|
|
84
|
+
secrets to leak or rotate, and provenance attestations are generated
|
|
85
|
+
automatically. Requires `id-token: write` and npm ≥ 11.5.1, which Node 22 does
|
|
86
|
+
not bundle — the job upgrades npm explicitly.
|
|
87
|
+
- The release workflow now fails if the pushed tag disagrees with the version in
|
|
88
|
+
`pyproject.toml` or `mcp/package.json`. The published version comes from
|
|
89
|
+
package metadata rather than the tag, so tagging `v0.2.0` against a `0.1.0`
|
|
90
|
+
pyproject would have published `0.1.0` under a release titled `v0.2.0` — and
|
|
91
|
+
a PyPI version can never be reused, so there is no clean recovery.
|
|
92
|
+
- Skill discovery is derived from the harness manifests instead of a hardcoded
|
|
93
|
+
three-entry tuple, growing from 3 roots to 10 — including `~/.claude/skills`,
|
|
94
|
+
which v0.1 never scanned.
|
|
95
|
+
- Raw route-trace retention raised from 1,000 to 20,000, configurable via
|
|
96
|
+
`SKILLROUTE_MAX_TRACES` (`0` disables pruning). 1,000 rows was a few days of
|
|
97
|
+
one active harness — too short a horizon for any question about change over
|
|
98
|
+
time. Pruning is now amortized across inserts rather than run on every one, so
|
|
99
|
+
the table may sit slightly above the cap between prunes.
|
|
100
|
+
|
|
101
|
+
### Deprecated
|
|
102
|
+
|
|
103
|
+
- `skillroute mcp config --client <id>` in favour of `skillroute harness show`
|
|
104
|
+
and `skillroute harness install`. Output is unchanged and the deprecation
|
|
105
|
+
notice goes to stderr, so `--json` stdout stays machine-parseable. The
|
|
106
|
+
`skillroute.client_setup` and `skillroute.mcp_setup` modules are now shims
|
|
107
|
+
re-exporting `skillroute.harness_setup` and `skillroute.harness_render`. All
|
|
108
|
+
are removed in 0.3.
|
|
109
|
+
|
|
110
|
+
### Security
|
|
111
|
+
|
|
112
|
+
- The Skill Atlas `POST /api/route-preview` endpoint no longer accepts an
|
|
113
|
+
arbitrary `repo` filesystem path. Any caller who could reach the local UI
|
|
114
|
+
server could use it to probe the disk: the response reports whether a
|
|
115
|
+
directory exists, its resolved absolute path, which marker files it holds,
|
|
116
|
+
and how many files it contains. A `repo` is now honored only when
|
|
117
|
+
`SKILLROUTE_REPO_ROOT` names a base directory, and only for paths that
|
|
118
|
+
resolve inside it (CodeQL `py/path-injection`). The bundled UI never sent
|
|
119
|
+
`repo`, and the CLI's `--repo` is unaffected.
|
|
120
|
+
|
|
121
|
+
[Unreleased]: https://github.com/erichare/skill-route/compare/v0.2.0...HEAD
|
|
122
|
+
[0.2.0]: https://github.com/erichare/skill-route/compare/v0.1.0...v0.2.0
|
|
123
|
+
|
|
124
|
+
## [0.1.0] - 2026-08-10
|
|
125
|
+
|
|
126
|
+
First release.
|
|
127
|
+
|
|
128
|
+
### Added
|
|
129
|
+
|
|
130
|
+
- SKILL.md bundle indexing into a local SQLite catalog (`skillroute index`)
|
|
131
|
+
- Semantic routing with ranked skills, confidence, evidence snippets, suggested
|
|
132
|
+
order, and clarification questions (`skillroute route`)
|
|
133
|
+
- Hybrid search over indexed skills (`skillroute search`) and per-skill
|
|
134
|
+
inspection (`skillroute inspect`)
|
|
135
|
+
- Pluggable retrieval backends: local token backend and Astra Data API backend,
|
|
136
|
+
plus a LangChain retriever adapter
|
|
137
|
+
- Metadata overlays for curating tags, domains, and languages without editing
|
|
138
|
+
skill sources
|
|
139
|
+
- Route observability: persisted route traces (`skillroute traces list`)
|
|
140
|
+
- Golden route evals (`skillroute eval run`)
|
|
141
|
+
- Skill Atlas web UI (`skillroute ui`), bundled into the Python wheel
|
|
142
|
+
- MCP stdio server (`@skillroute/mcp-server`) exposing `skillroute.route`,
|
|
143
|
+
`skillroute.search`, and `skillroute.inspect_skill`, with client setup via
|
|
144
|
+
`skillroute mcp config --client <client>`
|
|
145
|
+
|
|
146
|
+
[0.1.0]: https://github.com/erichare/skill-route/releases/tag/v0.1.0
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in SkillRoute! This page covers local development and
|
|
4
|
+
the release process.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
Requirements: [uv](https://docs.astral.sh/uv/), Node 20+.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# Python package (src/skillroute) + tests
|
|
12
|
+
uv sync --extra dev
|
|
13
|
+
uv run --extra dev pytest --cov=skillroute --cov-fail-under=80
|
|
14
|
+
uv run --extra dev ruff check .
|
|
15
|
+
uv run --extra dev mypy
|
|
16
|
+
|
|
17
|
+
# Skill Atlas web UI
|
|
18
|
+
npm --prefix web ci
|
|
19
|
+
npm --prefix web run typecheck && npm --prefix web run lint && npm --prefix web run test
|
|
20
|
+
|
|
21
|
+
# MCP server
|
|
22
|
+
npm --prefix mcp ci
|
|
23
|
+
npm --prefix mcp run build && npm --prefix mcp test && npm --prefix mcp run smoke
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
CI mirrors these commands plus dependency audits and a packaging check; see
|
|
27
|
+
[.github/workflows/ci.yml](.github/workflows/ci.yml).
|
|
28
|
+
|
|
29
|
+
## Guidelines
|
|
30
|
+
|
|
31
|
+
- Conventional commit messages (`feat:`, `fix:`, `chore:`, ...)
|
|
32
|
+
- Add or update tests with behavior changes; overall coverage must stay >= 80%
|
|
33
|
+
- `ruff` and `mypy` must pass
|
|
34
|
+
|
|
35
|
+
## Releasing
|
|
36
|
+
|
|
37
|
+
1. Bump the version in `pyproject.toml`, `mcp/package.json` (and
|
|
38
|
+
`web/package.json` for consistency). Python code and the MCP server read
|
|
39
|
+
their versions from package metadata — do not hardcode versions elsewhere.
|
|
40
|
+
2. Add a section to `CHANGELOG.md` and update its compare/tag links.
|
|
41
|
+
3. Land those changes on `main`, then tag and push:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git tag vX.Y.Z && git push origin vX.Y.Z
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
4. The [release workflow](.github/workflows/release.yml) builds the sdist,
|
|
48
|
+
wheel, and npm tarball, then creates a GitHub release with the artifacts
|
|
49
|
+
attached.
|
|
50
|
+
- PyPI publishing runs only when the `PYPI_PUBLISH` repository variable is
|
|
51
|
+
`true` and a [PyPI trusted publisher](https://docs.pypi.org/trusted-publishers/)
|
|
52
|
+
is configured for this repository.
|
|
53
|
+
- npm publishing runs only when the `NPM_PUBLISH` repository variable is
|
|
54
|
+
`true` and an `NPM_TOKEN` secret with publish rights to the
|
|
55
|
+
`@skillroute` scope is configured.
|
skillroute-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eric Hare
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|