@klhapp/skillmux 1.6.0 → 1.7.1
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.
- package/CHANGELOG.md +21 -0
- package/README.md +7 -7
- package/config.example.toml +5 -0
- package/config.remote.example.toml +4 -7
- package/docs/README.md +4 -4
- package/docs/assets/architecture.svg +1 -1
- package/docs/cli.md +4 -57
- package/docs/concepts.md +12 -14
- package/docs/configuration.md +10 -11
- package/docs/deployment.md +11 -8
- package/docs/getting-started.md +1 -1
- package/docs/mcp-routing.md +28 -23
- package/docs/ranked-shortlist-migration.md +160 -0
- package/docs/schema.json +37 -139
- package/docs/skill-management.md +7 -2
- package/docs/troubleshooting.md +12 -14
- package/package.json +1 -1
- package/src/adapters.ts +1 -536
- package/src/audit.ts +1 -3
- package/src/cli.ts +19 -254
- package/src/completions.ts +0 -4
- package/src/config-service.ts +19 -32
- package/src/config-watcher.ts +2 -6
- package/src/config.ts +61 -60
- package/src/db.ts +32 -18
- package/src/doctor.ts +1 -84
- package/src/eval.ts +143 -60
- package/src/init.ts +4 -5
- package/src/metrics.ts +1 -13
- package/src/router-core.ts +42 -149
- package/src/server.ts +13 -27
- package/src/stats.ts +126 -57
- package/src/types.ts +8 -39
- package/docs/calibration.md +0 -198
- package/src/calibrate.ts +0 -1775
- package/src/config-mutation.ts +0 -65
- package/src/dataset-generator.ts +0 -119
- package/src/decision.ts +0 -45
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.7.1](https://github.com/klhq/skillmux/compare/v1.7.0...v1.7.1) (2026-08-21)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
* **config:** neutralize migration error wording ([#128](https://github.com/klhq/skillmux/issues/128)) ([1fb130e](https://github.com/klhq/skillmux/commit/1fb130e3a6c3c3c084ca183c67ab7c8f984595a7))
|
|
14
|
+
|
|
15
|
+
## [1.7.0](https://github.com/klhq/skillmux/compare/v1.6.0...v1.7.0) (2026-08-21)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
* **calibration:** remove obsolete threshold calibration ([#125](https://github.com/klhq/skillmux/issues/125)) ([1432948](https://github.com/klhq/skillmux/commit/143294848c333c35186d70742ef59c230dc850bb))
|
|
21
|
+
* **eval:** rank Skillmux 2.0 evaluation ([#124](https://github.com/klhq/skillmux/issues/124)) ([2fab68d](https://github.com/klhq/skillmux/commit/2fab68d73702913fea5a6e4d8f892c2802a65a88))
|
|
22
|
+
* **ranking:** ranked-only Skillmux 2.0 runtime contract ([#122](https://github.com/klhq/skillmux/issues/122)) ([00810df](https://github.com/klhq/skillmux/commit/00810df92b7de60289dad41fe1fcb5a982686493))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
* **audit:** remove legacy classifier outcomes ([#126](https://github.com/klhq/skillmux/issues/126)) ([953edc4](https://github.com/klhq/skillmux/commit/953edc40147fb2f87eec5a57d53d6fa022566b77))
|
|
28
|
+
|
|
8
29
|
## [1.6.0](https://github.com/klhq/skillmux/compare/v1.5.2...v1.6.0) (2026-08-18)
|
|
9
30
|
|
|
10
31
|
|
package/README.md
CHANGED
|
@@ -231,18 +231,18 @@ Skillmux exposes two tools:
|
|
|
231
231
|
|
|
232
232
|
| Tool | Input | Result |
|
|
233
233
|
| --- | --- | --- |
|
|
234
|
-
| `resolve_skill` | Natural-language task description | A
|
|
234
|
+
| `resolve_skill` | Natural-language task description | A ranked shortlist of candidates |
|
|
235
235
|
| `fetch_skill` | Exact `skill_id` | The current `SKILL.md` body, SHA-256 digest, and supporting-file paths |
|
|
236
236
|
|
|
237
237
|
Skillmux uses the best available capability:
|
|
238
238
|
|
|
239
239
|
1. SQLite FTS5 provides lexical retrieval and offline fallback.
|
|
240
240
|
2. Local or remote embeddings add semantic recall.
|
|
241
|
-
3. An optional reranker
|
|
241
|
+
3. An optional reranker scores and reorders candidates.
|
|
242
242
|
|
|
243
|
-
|
|
243
|
+
Skillmux returns a ranked shortlist and lets the calling model choose. Endpoint failures degrade to a healthy lower retrieval mode instead of taking the MCP server down.
|
|
244
244
|
|
|
245
|
-
Read [MCP routing](docs/mcp-routing.md) for transports,
|
|
245
|
+
Read [MCP routing](docs/mcp-routing.md) for transports, client instructions, retrieval modes, and the wire contract.
|
|
246
246
|
|
|
247
247
|
## Supported clients
|
|
248
248
|
|
|
@@ -264,7 +264,7 @@ Skillmux preserves existing instruction files and unmanaged target content. Run
|
|
|
264
264
|
- **Managed ownership:** sync removes only entries recorded in the target's `.skillmux` marker.
|
|
265
265
|
- **Current bytes:** MCP delivery hashes the file on disk and never serves a stale indexed body.
|
|
266
266
|
- **Graceful retrieval:** embedding and reranker failures fall back without hiding the active capability.
|
|
267
|
-
- **Auditable decisions:** each `resolve_skill` call records its
|
|
267
|
+
- **Auditable decisions:** each `resolve_skill` call records its query, retrieval capability, candidates, scores, and latency in the state database.
|
|
268
268
|
|
|
269
269
|
## Documentation
|
|
270
270
|
|
|
@@ -275,11 +275,11 @@ Start with the [documentation hub](docs/README.md).
|
|
|
275
275
|
| [Getting started](docs/getting-started.md) | Native management, local MCP, and shared-service recipes |
|
|
276
276
|
| [Concepts](docs/concepts.md) | Delivery tiers, deployment topologies, retrieval modes, and ownership |
|
|
277
277
|
| [Managing skills](docs/skill-management.md) | Install, scan, pin, sync, report, overlays, and recovery |
|
|
278
|
-
| [MCP routing](docs/mcp-routing.md) | Tools,
|
|
278
|
+
| [MCP routing](docs/mcp-routing.md) | Tools, ranked candidate retrieval, transports, fallback, and integrity |
|
|
279
279
|
| [Deployment](docs/deployment.md) | Docker, container command boundaries, HTTP surfaces and auth, CORS, rate limits, and comparable CLI, health, and metrics status |
|
|
280
280
|
| [Configuration](docs/configuration.md) | Machine config, inference, HTTP surfaces, manifests, overlays, and container read-only configuration |
|
|
281
281
|
| [CLI reference](docs/cli.md) | Host and container command surfaces, administrative contexts, automation, JSON output, and exit codes |
|
|
282
|
-
| [
|
|
282
|
+
| [Ranked-shortlist migration](docs/ranked-shortlist-migration.md) | Upgrade guide for the ranked-only contract |
|
|
283
283
|
| [Troubleshooting](docs/troubleshooting.md) | `doctor`, deployment identity, common failures, and migration notes |
|
|
284
284
|
| [MCP schema](docs/schema.json) | JSON Schema 2020-12 tool contract |
|
|
285
285
|
|
package/config.example.toml
CHANGED
|
@@ -15,3 +15,8 @@ vault_path = "~/skills"
|
|
|
15
15
|
# vault_path for a given skill_id. Never holds skillmux.toml or the sync git
|
|
16
16
|
# hook — those always stay in vault_path. See docs/configuration.md#local-vault-overlays.
|
|
17
17
|
# local_vault_paths = ["~/skills-local"]
|
|
18
|
+
|
|
19
|
+
# Optional: output configuration for resolve_skill ranked candidates.
|
|
20
|
+
# [output]
|
|
21
|
+
# top_k = 10
|
|
22
|
+
# max_top_k = 50
|
|
@@ -28,10 +28,7 @@ endpoint = "https://reranker.example.com/v1/rerank"
|
|
|
28
28
|
model = "your-reranker-model"
|
|
29
29
|
api_key_env = "RERANKER_API_KEY"
|
|
30
30
|
|
|
31
|
-
# Optional
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
match_score = 0.90
|
|
36
|
-
match_margin = 0.30
|
|
37
|
-
candidate_floor = 0.50
|
|
31
|
+
# Optional: output configuration for resolve_skill ranked candidates.
|
|
32
|
+
# [output]
|
|
33
|
+
# top_k = 10
|
|
34
|
+
# max_top_k = 50
|
package/docs/README.md
CHANGED
|
@@ -49,8 +49,8 @@ deployed server only, never remote client skill directories. See
|
|
|
49
49
|
retrieval capability.
|
|
50
50
|
- [Managing skills](skill-management.md): install, scan, pin, sync, inspect,
|
|
51
51
|
and recover skills.
|
|
52
|
-
- [MCP routing](mcp-routing.md): register stdio or HTTP MCP and
|
|
53
|
-
|
|
52
|
+
- [MCP routing](mcp-routing.md): register stdio or HTTP MCP and route queries
|
|
53
|
+
to ranked candidate shortlists.
|
|
54
54
|
|
|
55
55
|
## Operate Skillmux
|
|
56
56
|
|
|
@@ -62,8 +62,8 @@ deployed server only, never remote client skill directories. See
|
|
|
62
62
|
server settings, local overlays, and container read-only configuration.
|
|
63
63
|
- [CLI reference](cli.md): use host and container command surfaces,
|
|
64
64
|
administrative contexts, JSON output, and exit codes.
|
|
65
|
-
- [
|
|
66
|
-
|
|
65
|
+
- [Ranked-shortlist migration](ranked-shortlist-migration.md): upgrade to the ranked-only
|
|
66
|
+
shortlist contract.
|
|
67
67
|
- [Troubleshooting](troubleshooting.md): diagnose vault, sync, model, and server
|
|
68
68
|
problems.
|
|
69
69
|
|
|
@@ -149,6 +149,6 @@
|
|
|
149
149
|
|
|
150
150
|
<rect x="420" y="608" width="740" height="82" rx="14" fill="#0f172a"/>
|
|
151
151
|
<text x="444" y="633" class="chip" fill="#cbd5e1">MCP TOOL CONTRACT · STDIO + HTTP</text>
|
|
152
|
-
<text x="444" y="655" class="mono mono-light" style="font-size: 12px">resolve_skill →
|
|
152
|
+
<text x="444" y="655" class="mono mono-light" style="font-size: 12px">resolve_skill → lexical + vector → RRF → optional rerank → top_k → ranked candidates</text>
|
|
153
153
|
<text x="444" y="677" class="mono mono-light" style="font-size: 12px">fetch_skill → exact current SKILL.md + SHA-256</text>
|
|
154
154
|
</svg>
|
package/docs/cli.md
CHANGED
|
@@ -24,7 +24,7 @@ CLI. Its `skillmux --help` surface is intentionally limited to `serve`,
|
|
|
24
24
|
`index`, `doctor`, `report`, `scan`, `skill which`, and read-only `config`
|
|
25
25
|
inspection (`show`, `get`, `validate`, `diff`, and `status`). Run `init`,
|
|
26
26
|
`install`, pinning, `sync`, project or target management, model downloads,
|
|
27
|
-
contexts,
|
|
27
|
+
contexts, evaluation, and configuration changes on the host.
|
|
28
28
|
|
|
29
29
|
When the image rejects one of those commands, it exits with code 2. JSON mode
|
|
30
30
|
uses `CONTAINER_COMMAND_UNSUPPORTED` and includes `rejected_command`,
|
|
@@ -267,8 +267,8 @@ whole call fails and the manifest file is left untouched. To pin into a
|
|
|
267
267
|
|
|
268
268
|
Config changes are categorized into live-reloadable and restart-required settings:
|
|
269
269
|
|
|
270
|
-
- **Reloadable**: `vault_path`, `recall
|
|
271
|
-
- **Restart Required**: `server.hostname`, `server.auth_enabled`, `server.auth_token_env`, `server.admin.enabled`, `server.admin.token_env`, `inference.mode`, `state_dir`
|
|
270
|
+
- **Reloadable**: `config.environment_overrides`, `vault_path`, `recall.k_lexical`, `recall.k_vector`, `recall.k_rerank`, `output.top_k`, `output.max_top_k`, `inference.embedding.endpoint`, `inference.embedding.api_key_env`, `inference.reranker.adapter`, `inference.reranker.endpoint`, `inference.reranker.model`, `inference.reranker.api_key_env`, `inference.timeout_ms`, `server.rate_limit.enabled`, `server.rate_limit.requests_per_minute`, `server.rate_limit.trust_proxy`
|
|
271
|
+
- **Restart Required**: `server.hostname`, `server.auth_enabled`, `server.auth_token_env`, `server.admin.enabled`, `server.admin.token_env`, `inference.mode`, `inference.bundle`, `inference.models_dir`, `state_dir`, `inference.embedding.model`, `inference.embedding.dimension`, `inference.embedding.device`, `inference.embedding.dtype`
|
|
272
272
|
|
|
273
273
|
The config file is optional. `skillmux serve` starts with defaults if its
|
|
274
274
|
config path or parent directory is absent. In that case reload is inactive
|
|
@@ -287,56 +287,6 @@ skillmux skill which csv-formatter
|
|
|
287
287
|
|
|
288
288
|
---
|
|
289
289
|
|
|
290
|
-
## Policy calibration (`skillmux calibrate`)
|
|
291
|
-
|
|
292
|
-
Calibrate decision thresholds (`match_score`, `match_margin`, `candidate_floor`) against synthetic or labeled query datasets.
|
|
293
|
-
Calibration is local-only in this release. Remote targets advertise the
|
|
294
|
-
capability as unavailable and return `not_implemented`; a local dataset path is
|
|
295
|
-
never uploaded or represented as remotely executed. See
|
|
296
|
-
[`docs/calibration.md`](calibration.md) for dataset responsibilities,
|
|
297
|
-
certification gates, run evidence, reference values, and the complete operator
|
|
298
|
-
lifecycle.
|
|
299
|
-
|
|
300
|
-
```sh
|
|
301
|
-
# Run calibration on a dataset with default certification gates (min precision 0.75, min count 15)
|
|
302
|
-
skillmux calibrate run --dataset ./eval/queries.json
|
|
303
|
-
|
|
304
|
-
# Specify explicit certification gates and tune selection buffers
|
|
305
|
-
# Note: --min-auto-match-precision is interpreted as a 95% Wilson lower confidence bound.
|
|
306
|
-
# Calibration preflight validates that the requested gate is mathematically attainable on the tune split.
|
|
307
|
-
skillmux calibrate run --dataset ./eval/queries.json \
|
|
308
|
-
--min-auto-match-precision 0.75 \
|
|
309
|
-
--min-auto-match-count 15 \
|
|
310
|
-
--min-retrieval-recall-at-k 0.95 \
|
|
311
|
-
--min-delivered-shortlist-recall-at-k 0.95 \
|
|
312
|
-
--tune-auto-match-precision-buffer 0.03 \
|
|
313
|
-
--tune-auto-match-count-buffer 3 \
|
|
314
|
-
--tune-delivered-shortlist-recall-buffer 0.02
|
|
315
|
-
|
|
316
|
-
# Set the bounded worker count
|
|
317
|
-
skillmux calibrate run --dataset ./eval/queries.json --concurrency 6
|
|
318
|
-
|
|
319
|
-
# Print aggregate performance timing to stderr
|
|
320
|
-
skillmux calibrate run --dataset ./eval/queries.json --timing
|
|
321
|
-
|
|
322
|
-
# Resume a running or interrupted attempt with the same inputs and gates
|
|
323
|
-
skillmux calibrate run --dataset ./eval/queries.json --resume <run_id>
|
|
324
|
-
|
|
325
|
-
# List stored calibration runs in the evidence store
|
|
326
|
-
skillmux calibrate list
|
|
327
|
-
|
|
328
|
-
# Inspect detailed metrics and confusion matrix for a run
|
|
329
|
-
skillmux calibrate show <run_id>
|
|
330
|
-
|
|
331
|
-
# Apply calibrated thresholds to configuration (with fingerprint validation)
|
|
332
|
-
skillmux calibrate apply <run_id>
|
|
333
|
-
|
|
334
|
-
# Generate a synthetic decision dataset from vault skills
|
|
335
|
-
skillmux calibrate generate-dataset --out ./eval/queries.json
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
---
|
|
339
|
-
|
|
340
290
|
## Administrative HTTP API (`/admin/v1/*`)
|
|
341
291
|
|
|
342
292
|
The HTTP server has two separate surfaces:
|
|
@@ -363,12 +313,9 @@ Requests require `Authorization: Bearer <token>` where `<token>` matches the env
|
|
|
363
313
|
|
|
364
314
|
| Endpoint | Method | Description |
|
|
365
315
|
|----------|--------|-------------|
|
|
366
|
-
| `/admin/v1/capabilities` | `GET` | Advertises server features (`config_read`, `config_write`, `
|
|
316
|
+
| `/admin/v1/capabilities` | `GET` | Advertises server features (`config_read`, `config_write`, `persistence`) |
|
|
367
317
|
| `/admin/v1/config` | `GET` | Returns desired/effective config, sources, and `ETag` revision hash |
|
|
368
318
|
| `/admin/v1/config` | `PATCH` | Applies dotted-key updates; requires matching `If-Match` header |
|
|
369
|
-
| `/admin/v1/calibrations` | `GET`, `POST` | Returns `501 not_implemented` (calibration is local-only) |
|
|
370
|
-
| `/admin/v1/calibrations/{run_id}` | `GET` | Returns `501 not_implemented`; raw evaluation queries are not exposed |
|
|
371
|
-
| `/admin/v1/calibrations/{run_id}/apply` | `POST` | Returns `501 not_implemented` |
|
|
372
319
|
|
|
373
320
|
---
|
|
374
321
|
|
package/docs/concepts.md
CHANGED
|
@@ -168,21 +168,19 @@ Skillmux reports the active retrieval capability:
|
|
|
168
168
|
| `reranked` | A configured reranker reorders the fused candidates |
|
|
169
169
|
| `exact` | An exact skill ID resolves directly |
|
|
170
170
|
|
|
171
|
-
A reranker
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
A reranker scores and reorders the fused candidates. Reranking does not classify
|
|
172
|
+
outcomes or filter by score thresholds; Skillmux delivers the top-ranked candidates
|
|
173
|
+
directly to the calling model.
|
|
174
174
|
|
|
175
|
-
##
|
|
175
|
+
## Ranked shortlist retrieval
|
|
176
176
|
|
|
177
|
-
`resolve_skill` returns
|
|
177
|
+
`resolve_skill` always returns a ranked candidate list:
|
|
178
178
|
|
|
179
|
-
-
|
|
180
|
-
|
|
181
|
-
- `
|
|
182
|
-
|
|
183
|
-
- `no_match`: no candidate passed the policy and the agent continues without a
|
|
184
|
-
skill.
|
|
179
|
+
- each candidate contains a `rank`, `skill_id`, `description`, and a nullable `score`;
|
|
180
|
+
- `top_k` controls the maximum candidate count returned, bounded by `output.max_top_k`;
|
|
181
|
+
- if no candidates match the query, `resolve_skill` returns an empty list (`candidates: []`);
|
|
182
|
+
- the calling model reviews the candidate shortlist and calls `fetch_skill` with the chosen `skill_id` to retrieve complete instructions.
|
|
185
183
|
|
|
186
|
-
Embedding or reranker failures reduce the active capability
|
|
187
|
-
|
|
188
|
-
valid retrieval.
|
|
184
|
+
Embedding or reranker failures reduce the active capability and return
|
|
185
|
+
structured degradation metadata. Vault and index failures make the server
|
|
186
|
+
unready because Skillmux can no longer guarantee valid retrieval.
|
package/docs/configuration.md
CHANGED
|
@@ -27,9 +27,8 @@ commands, target resolution, and automation envelopes, see
|
|
|
27
27
|
[CLI reference](cli.md). For Linux CLI installation, see the
|
|
28
28
|
[pinned checksum-verified download](getting-started.md#install-the-cli) or the
|
|
29
29
|
[attested GitHub CLI path](getting-started.md#install-with-github-cli-attestation).
|
|
30
|
-
For
|
|
31
|
-
|
|
32
|
-
[Policy calibration](calibration.md).
|
|
30
|
+
For ranking evaluation and upgrading from earlier releases, see
|
|
31
|
+
[Ranked-shortlist migration](ranked-shortlist-migration.md).
|
|
33
32
|
|
|
34
33
|
## Machine config bootstrap
|
|
35
34
|
|
|
@@ -70,7 +69,7 @@ loads it and cache it in `~/.cache/skillmux/models`. The full image
|
|
|
70
69
|
already contains the model.
|
|
71
70
|
|
|
72
71
|
Skillmux combines FTS5 and cosine result lists with reciprocal-rank fusion.
|
|
73
|
-
|
|
72
|
+
Skillmux returns the fused candidates as a ranked shortlist.
|
|
74
73
|
|
|
75
74
|
Advanced local overrides:
|
|
76
75
|
|
|
@@ -120,9 +119,8 @@ Remote embedding `dimension` is required. `endpoint`, `api_key_env`, and the
|
|
|
120
119
|
shared timeout reload live; model, dimension, device, and dtype require a
|
|
121
120
|
restart. Changing only endpoint does not invalidate stored vectors.
|
|
122
121
|
|
|
123
|
-
Reranker
|
|
124
|
-
|
|
125
|
-
adapter or model does.
|
|
122
|
+
Reranker configuration pairs an adapter (such as `jina-v1` or `bifrost-v1`) with a
|
|
123
|
+
model name and a complete endpoint URL.
|
|
126
124
|
|
|
127
125
|
## Configuration authority
|
|
128
126
|
|
|
@@ -142,7 +140,7 @@ Inspect provenance and active policy with `skillmux config show --sources` or `s
|
|
|
142
140
|
|
|
143
141
|
## Advanced retrieval
|
|
144
142
|
|
|
145
|
-
Candidate-generation depth, reranking candidate budgets, and
|
|
143
|
+
Candidate-generation depth, reranking candidate budgets, and output candidate shortlist size are separate controls:
|
|
146
144
|
|
|
147
145
|
```toml
|
|
148
146
|
[recall]
|
|
@@ -151,12 +149,14 @@ k_vector = 20
|
|
|
151
149
|
k_rerank = 10
|
|
152
150
|
|
|
153
151
|
[output]
|
|
154
|
-
|
|
152
|
+
top_k = 10
|
|
153
|
+
max_top_k = 50
|
|
155
154
|
```
|
|
156
155
|
|
|
157
156
|
- `recall.k_lexical` and `recall.k_vector` control initial candidate generation depth.
|
|
158
157
|
- `recall.k_rerank` bounds the candidate shortlist sent to the reranker adapter (defaults to `10`, cannot exceed `k_lexical + k_vector`).
|
|
159
|
-
- `output.
|
|
158
|
+
- `output.top_k` sets the default maximum number of candidates returned by `resolve_skill` (defaults to `10`).
|
|
159
|
+
- `output.max_top_k` sets the upper bound for per-request `top_k` overrides (defaults to `50`).
|
|
160
160
|
|
|
161
161
|
### Failure visibility and degraded retrieval
|
|
162
162
|
|
|
@@ -164,7 +164,6 @@ When remote embedding or reranking fails or times out, Skillmux gracefully falls
|
|
|
164
164
|
|
|
165
165
|
```json
|
|
166
166
|
{
|
|
167
|
-
"outcome": "ambiguous",
|
|
168
167
|
"retrieval": "hybrid",
|
|
169
168
|
"degraded_from": "reranked",
|
|
170
169
|
"degradation_reason": "reranker_timeout",
|
package/docs/deployment.md
CHANGED
|
@@ -113,7 +113,7 @@ The supported container commands are `serve`, `index`, `doctor`, `report`,
|
|
|
113
113
|
|
|
114
114
|
The image rejects host-management commands, including `init`, `sync`,
|
|
115
115
|
`install`, `project`, `target`, `core`, `local-vault`, `models download`,
|
|
116
|
-
context management,
|
|
116
|
+
context management, evaluation, and configuration initialization
|
|
117
117
|
or mutation. Install the Skillmux CLI on the host when a command needs to
|
|
118
118
|
manage a local vault or agent directory.
|
|
119
119
|
|
|
@@ -141,8 +141,8 @@ docker run -d \
|
|
|
141
141
|
ghcr.io/klhq/skillmux:latest-slim
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
Set `SKILLMUX_CONFIG` and mount a TOML file when you need reranking,
|
|
145
|
-
|
|
144
|
+
Set `SKILLMUX_CONFIG` and mount a TOML file when you need reranking, custom
|
|
145
|
+
recall/output settings, server policy, or API-key environment names:
|
|
146
146
|
|
|
147
147
|
```sh
|
|
148
148
|
docker run -d \
|
|
@@ -242,15 +242,18 @@ The HTTP server provides:
|
|
|
242
242
|
| `GET /health/ready` | Vault, index, inference, active capability, version, runtime, and image variant |
|
|
243
243
|
| `GET /health` | Compatibility alias for liveness |
|
|
244
244
|
| `GET /metrics` | Prometheus text exposition |
|
|
245
|
-
| `GET /stats` | Aggregated routing
|
|
245
|
+
| `GET /stats` | Aggregated routing statistics for `skillmux report` |
|
|
246
246
|
| `POST /mcp` | Streamable HTTP MCP transport |
|
|
247
247
|
| `/admin/v1/*` | Administrative configuration API (when enabled) |
|
|
248
248
|
|
|
249
249
|
The Docker health check calls `/health/ready`.
|
|
250
250
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
`GET /stats` returns JSON aggregated from audit rows over a query window (using `?since=`, defaulting to 24 hours). The response contains `since`, `until`, `total_requests`, `empty_shortlist_count`, `empty_shortlist_rate`, `retrieval_totals` (counts for `exact`, `reranked`, `hybrid`, and `lexical`), `degraded_count`, `average_latency_ms`, per-skill candidate counts in `skills` (`skill_id`, `candidate_count`), and `top_empty_shortlist_queries` (`query`, `count`). See [Managing skills](skill-management.md#use-routing-data-to-tune-tiers) for using these statistics to tune delivery tiers.
|
|
252
|
+
|
|
253
|
+
Prometheus metrics cover request totals, resolve latency histograms, errors,
|
|
254
|
+
rate-limit rejections, degraded retrieval totals by stage and reason, readiness
|
|
255
|
+
and active retrieval capability gauges, and a `skill_router_deployment_info` gauge
|
|
256
|
+
labelled with `version`, `runtime`, and `image_variant`. The values match `skillmux doctor`,
|
|
254
257
|
`skillmux config status`, and `/health/ready`; use `image_variant="none"` for
|
|
255
258
|
a host runtime. These operational outputs never include credentials, API keys,
|
|
256
259
|
or token values. Health and metrics do not require bearer authentication, but
|
|
@@ -286,7 +289,7 @@ their mounted vault checkout and do not manage host agent directories.
|
|
|
286
289
|
|
|
287
290
|
## Persistent data and backups
|
|
288
291
|
|
|
289
|
-
Persist `state_dir` to retain the index
|
|
292
|
+
Persist `state_dir` to retain the index and audit log.
|
|
290
293
|
Skill content remains in the server's vault checkout and should use its own
|
|
291
294
|
backup or Git workflow.
|
|
292
295
|
|
package/docs/getting-started.md
CHANGED
|
@@ -212,7 +212,7 @@ Register it with your MCP client:
|
|
|
212
212
|
```
|
|
213
213
|
|
|
214
214
|
The client launches the process and closes it with the MCP session. Continue
|
|
215
|
-
with [MCP routing](mcp-routing.md) for client behavior and retrieval
|
|
215
|
+
with [MCP routing](mcp-routing.md) for client behavior and ranked candidate retrieval.
|
|
216
216
|
|
|
217
217
|
## Run a shared MCP service
|
|
218
218
|
|
package/docs/mcp-routing.md
CHANGED
|
@@ -70,16 +70,30 @@ Input:
|
|
|
70
70
|
|
|
71
71
|
```json
|
|
72
72
|
{
|
|
73
|
-
"query": "convert this spreadsheet to a Markdown table"
|
|
73
|
+
"query": "convert this spreadsheet to a Markdown table",
|
|
74
|
+
"top_k": 5
|
|
74
75
|
}
|
|
75
76
|
```
|
|
76
77
|
|
|
77
|
-
Skillmux returns
|
|
78
|
+
Skillmux returns a ranked candidates response:
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"retrieval": "reranked",
|
|
83
|
+
"candidates": [
|
|
84
|
+
{
|
|
85
|
+
"rank": 1,
|
|
86
|
+
"skill_id": "csv-formatter",
|
|
87
|
+
"description": "Convert CSV and spreadsheets into formatted Markdown tables.",
|
|
88
|
+
"score": 0.92
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- `retrieval`: the effective retrieval capability (`reranked`, `hybrid`, or `lexical`).
|
|
95
|
+
- `candidates`: zero through effective `top_k` candidates ordered by descending score with contiguous 1-based ranks.
|
|
96
|
+
- If reranking or embedding fails, degradation metadata (`degraded_from`, `degradation_reason`) is included.
|
|
83
97
|
|
|
84
98
|
### `fetch_skill`
|
|
85
99
|
|
|
@@ -102,13 +116,9 @@ The complete wire contract lives in [schema.json](schema.json).
|
|
|
102
116
|
Give the calling client these rules:
|
|
103
117
|
|
|
104
118
|
1. Call `resolve_skill` when a task may benefit from a specialized workflow.
|
|
105
|
-
2.
|
|
106
|
-
3.
|
|
107
|
-
4.
|
|
108
|
-
|
|
109
|
-
Do not treat the first ambiguous candidate as an automatic match. Skillmux
|
|
110
|
-
uses ambiguity to keep the final choice with the calling model when it lacks
|
|
111
|
-
enough confidence.
|
|
119
|
+
2. Review the returned ranked candidates shortlist.
|
|
120
|
+
3. If a relevant candidate exists, call `fetch_skill` with its `skill_id` to retrieve complete instructions.
|
|
121
|
+
4. If no candidate is relevant (or `candidates` is empty), continue under your normal workflow.
|
|
112
122
|
|
|
113
123
|
## Retrieval pipeline
|
|
114
124
|
|
|
@@ -118,7 +128,7 @@ Skillmux builds candidates in stages:
|
|
|
118
128
|
2. Local or remote embeddings rank semantic similarity.
|
|
119
129
|
3. Reciprocal-rank fusion combines both lists.
|
|
120
130
|
4. An optional reranker scores the fused candidates.
|
|
121
|
-
5.
|
|
131
|
+
5. Returns up to effective `top_k` ranked candidates.
|
|
122
132
|
|
|
123
133
|
The default local inference configuration uses FTS5 and quantized
|
|
124
134
|
`Xenova/gte-small` embeddings. Skillmux CLI installations cache the
|
|
@@ -128,13 +138,8 @@ OpenAI-compatible embedding endpoint.
|
|
|
128
138
|
|
|
129
139
|
Remote inference also supports `jina-v1` or `bifrost-v1` reranker adapters.
|
|
130
140
|
|
|
131
|
-
Without a reranker, Skillmux returns a shortlist and does not auto-match.
|
|
132
|
-
Without calibrated thresholds, a configured reranker orders the shortlist but
|
|
133
|
-
still does not auto-match.
|
|
134
|
-
|
|
135
141
|
Read [Configuration](configuration.md#local-inference) for local and remote
|
|
136
|
-
inference settings.
|
|
137
|
-
automatic matches.
|
|
142
|
+
inference settings.
|
|
138
143
|
|
|
139
144
|
## Fallback and readiness
|
|
140
145
|
|
|
@@ -169,10 +174,10 @@ access.
|
|
|
169
174
|
Each resolve request records:
|
|
170
175
|
|
|
171
176
|
- timestamp and query;
|
|
172
|
-
- retrieval capability
|
|
177
|
+
- retrieval capability;
|
|
178
|
+
- degradation metadata (`degraded_from`, `degradation_reason`) when degraded;
|
|
173
179
|
- candidates with scores;
|
|
174
|
-
-
|
|
175
|
-
- latency.
|
|
180
|
+
- latency in milliseconds.
|
|
176
181
|
|
|
177
182
|
Skillmux stores audit rows in the SQLite database under `state_dir`. Use
|
|
178
183
|
`skillmux report` to summarize activity. Treat raw queries as private user
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Ranked-shortlist migration
|
|
2
|
+
|
|
3
|
+
The ranked-shortlist release replaces threshold-based classification with ranked candidate retrieval. Instead of classifying a query as `matched`, `ambiguous`, or `no_match` and returning inline skill text on match, `resolve_skill` always returns a ranked shortlist of candidate summaries. The calling client reviews the shortlist and invokes `fetch_skill` to load the full instructions for the chosen skill.
|
|
4
|
+
|
|
5
|
+
## Upgrading configuration
|
|
6
|
+
|
|
7
|
+
Legacy threshold configuration tables and candidate limits are obsolete. Threshold values do not map semantically to candidate list lengths; replace threshold tables with retrieval depth and output bounds.
|
|
8
|
+
|
|
9
|
+
In `~/.config/skillmux/config.toml`, configure `[recall]` to control candidate generation and `[output]` to set candidate shortlist limits:
|
|
10
|
+
|
|
11
|
+
```toml
|
|
12
|
+
vault_path = "~/skills"
|
|
13
|
+
state_dir = "~/.local/state/skillmux"
|
|
14
|
+
|
|
15
|
+
[recall]
|
|
16
|
+
k_lexical = 20
|
|
17
|
+
k_vector = 20
|
|
18
|
+
k_rerank = 10
|
|
19
|
+
|
|
20
|
+
[output]
|
|
21
|
+
top_k = 10
|
|
22
|
+
max_top_k = 50
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`recall.k_lexical` and `recall.k_vector` set the number of candidates retrieved from FTS5 lexical search and vector similarity before reciprocal rank fusion. `recall.k_rerank` limits the candidate shortlist sent to an optional remote reranker adapter and cannot exceed `k_lexical + k_vector`.
|
|
26
|
+
|
|
27
|
+
`output.top_k` sets the default maximum number of candidates returned by `resolve_skill`. `output.max_top_k` sets the upper bound for per-request `top_k` overrides. When a remote reranker is configured, `output.max_top_k` cannot exceed `recall.k_rerank`.
|
|
28
|
+
|
|
29
|
+
Existing `calibrate.sqlite3` databases in `state_dir` remain untouched on disk. Skillmux does not delete or modify historical calibration data.
|
|
30
|
+
|
|
31
|
+
## Obsolete configuration keys
|
|
32
|
+
|
|
33
|
+
Startup fails with an explicit error when obsolete configuration keys are present:
|
|
34
|
+
|
|
35
|
+
| Obsolete configuration key | Replacement | Migration guidance |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| `[thresholds]` | `[output].top_k` | The `[thresholds]` table is obsolete. Threshold calibration was removed; use `[output]` with `top_k`. |
|
|
38
|
+
| `output.ambiguous_candidate_limit` | `output.top_k` | `output.ambiguous_candidate_limit` is obsolete. Use `output.top_k` instead. |
|
|
39
|
+
| `inference.thresholds` | Removed | `inference.thresholds` is obsolete. Threshold calibration was removed. |
|
|
40
|
+
| `inference.calibration` | `skillmux eval` | `inference.calibration` is obsolete and should be deleted. Threshold calibration was removed; use `skillmux eval` for ranking evaluation. |
|
|
41
|
+
| `skillmux calibrate` | `skillmux eval` | `skillmux calibrate` was removed. Threshold calibration was removed; use `skillmux eval` for ranking evaluation. |
|
|
42
|
+
|
|
43
|
+
## Wire contract changes
|
|
44
|
+
|
|
45
|
+
In the legacy classifier contract, `resolve_skill` returned an `outcome` classification and delivered the complete `SKILL.md` body directly when a single match met threshold criteria:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"outcome": "matched",
|
|
50
|
+
"retrieval": "reranked",
|
|
51
|
+
"skill_id": "csv-formatter",
|
|
52
|
+
"title": "CSV Formatter",
|
|
53
|
+
"content_sha256": "8a3f...",
|
|
54
|
+
"body": "# CSV Formatter\n...",
|
|
55
|
+
"files": [],
|
|
56
|
+
"candidates": [
|
|
57
|
+
{
|
|
58
|
+
"rank": 1,
|
|
59
|
+
"skill_id": "csv-formatter",
|
|
60
|
+
"score": 0.95
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
In the current contract, `resolve_skill` returns ranked candidate summaries with descriptions and scores. The client reviews candidate descriptions and calls `fetch_skill` with the desired `skill_id` to retrieve instructions and supporting files:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"retrieval": "reranked",
|
|
71
|
+
"candidates": [
|
|
72
|
+
{
|
|
73
|
+
"rank": 1,
|
|
74
|
+
"skill_id": "csv-formatter",
|
|
75
|
+
"description": "Convert CSV and spreadsheet data into clean Markdown tables.",
|
|
76
|
+
"score": 0.92
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"rank": 2,
|
|
80
|
+
"skill_id": "table-helper",
|
|
81
|
+
"description": "Format ASCII and Markdown tables.",
|
|
82
|
+
"score": 0.74
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
When retrieval finds no candidates, `resolve_skill` returns an empty candidate list:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"retrieval": "hybrid",
|
|
93
|
+
"candidates": []
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
When upstream embedding or reranking endpoints fail or time out, Skillmux falls back to the next available retrieval lane and reports structured degradation metadata:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"retrieval": "hybrid",
|
|
102
|
+
"degraded_from": "reranked",
|
|
103
|
+
"degradation_reason": "reranker_timeout",
|
|
104
|
+
"candidates": [
|
|
105
|
+
{
|
|
106
|
+
"rank": 1,
|
|
107
|
+
"skill_id": "csv-formatter",
|
|
108
|
+
"description": "Convert CSV and spreadsheet data into clean Markdown tables.",
|
|
109
|
+
"score": 0.033
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Audit database migration
|
|
116
|
+
|
|
117
|
+
On startup, Skillmux inspects the `audit` table in `state_dir/index.sqlite3`. If legacy classifier columns (`outcome`, `selected_skill_id`, `degraded`) are present, it migrates the table inside an atomic SQLite transaction:
|
|
118
|
+
|
|
119
|
+
```sql
|
|
120
|
+
CREATE TABLE audit (
|
|
121
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
122
|
+
ts TEXT NOT NULL,
|
|
123
|
+
query TEXT NOT NULL,
|
|
124
|
+
retrieval TEXT NOT NULL DEFAULT 'lexical',
|
|
125
|
+
degraded_from TEXT,
|
|
126
|
+
degradation_reason TEXT,
|
|
127
|
+
candidates TEXT NOT NULL,
|
|
128
|
+
latency_ms INTEGER NOT NULL
|
|
129
|
+
);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Historical rows retain their `id`, `ts`, `query`, `retrieval`, `candidates`, and `latency_ms` values. Classifier-only columns are removed.
|
|
133
|
+
|
|
134
|
+
## Ranking evaluation
|
|
135
|
+
|
|
136
|
+
Use `skillmux eval` to evaluate retrieval and ranking quality across lexical and hybrid pipelines:
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
skillmux eval
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The `skillmux eval` command reads the default `eval/queries.json` dataset from the repository because the CLI currently has no `--dataset` flag.
|
|
143
|
+
|
|
144
|
+
Evaluation cases specify `relevant_skill_ids` as an array of skill identifiers rather than legacy outcome fields:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"query": "format a csv file",
|
|
149
|
+
"relevant_skill_ids": ["csv-formatter"],
|
|
150
|
+
"split": "test"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Legacy fields `expected` and `expected_outcome` are rejected with validation errors. Cases with empty `relevant_skill_ids: []` represent unjudged queries and are excluded from aggregate ranking metrics without penalizing the evaluation score.
|
|
155
|
+
|
|
156
|
+
The evaluation report computes four ranking metrics for lexical and hybrid retrieval:
|
|
157
|
+
- Recall@5 measures the fraction of relevant skills found in the top 5 candidates.
|
|
158
|
+
- Recall@10 measures the fraction of relevant skills found in the top 10 candidates.
|
|
159
|
+
- Mean Reciprocal Rank (MRR) measures the reciprocal rank of the first relevant candidate.
|
|
160
|
+
- Binary nDCG@10 discounts relevance logarithmically across the top 10 positions.
|