@klhapp/skillmux 1.11.2 → 1.13.0
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 +15 -0
- package/README.md +20 -10
- package/bin/skillmux.js +89 -0
- package/docs/README.md +4 -4
- package/docs/cli.md +15 -5
- package/docs/concepts.md +4 -3
- package/docs/configuration.md +22 -5
- package/docs/deployment.md +3 -3
- package/docs/getting-started.md +32 -7
- package/docs/releasing.md +17 -2
- package/docs/sdd/cli-remote-target-parity/schema-bucket-b.yaml +297 -0
- package/docs/sdd/cli-remote-target-parity/spec-bucket-b.md +95 -0
- package/docs/sdd/cli-remote-target-parity/spec.md +111 -0
- package/docs/sdd/cli-remote-target-parity/think.md +183 -0
- package/docs/sdd/cli-surface-consistency/think.md +149 -0
- package/docs/sdd/config-authority-rerank-resilience/plan.md +338 -0
- package/docs/sdd/config-authority-rerank-resilience/review.md +124 -0
- package/docs/sdd/config-authority-rerank-resilience/spec.md +78 -0
- package/docs/sdd/feat-packaging-deployment/review.md +95 -0
- package/docs/sdd/fetch-outcome-flywheel/review.md +103 -0
- package/docs/sdd/fetch-outcome-flywheel/schema.json +347 -0
- package/docs/sdd/fetch-outcome-flywheel/spec.md +185 -0
- package/docs/sdd/npm-native-binaries/review.md +103 -0
- package/docs/sdd/npm-native-binaries/spec.md +148 -0
- package/docs/sdd/ranked-shortlist-2/pr3-calibration-removal.md +56 -0
- package/docs/sdd/refactor-builtin-target-paths/spec.md +41 -0
- package/docs/sdd/runtime-resource-hardening/review.md +86 -0
- package/docs/sdd/runtime-resource-hardening/spec.md +43 -0
- package/docs/sdd/security-hardening-phase/think.md +129 -0
- package/docs/sdd/security-observability/review.md +96 -0
- package/docs/sdd/security-observability/spec.md +55 -0
- package/docs/sdd/skill-provenance-update/review.md +152 -0
- package/docs/sdd/skill-provenance-update/schema.json +193 -0
- package/docs/sdd/skill-provenance-update/spec.md +134 -0
- package/docs/sdd/supply-chain-hardening/review.md +50 -0
- package/docs/sdd/supply-chain-hardening/spec.md +42 -0
- package/docs/sdd/target-marker-rehome/spec.md +33 -0
- package/docs/skill-management.md +1 -1
- package/docs/troubleshooting.md +18 -2
- package/package.json +15 -8
- package/src/adapters.ts +0 -438
- package/src/audit.ts +0 -21
- package/src/cli.ts +0 -928
- package/src/clients.ts +0 -368
- package/src/commands/audit.ts +0 -85
- package/src/commands/config.ts +0 -224
- package/src/commands/context.ts +0 -104
- package/src/commands/core.ts +0 -56
- package/src/commands/doctor.ts +0 -97
- package/src/commands/eval.ts +0 -88
- package/src/commands/init.ts +0 -672
- package/src/commands/install.ts +0 -155
- package/src/commands/local-vault.ts +0 -60
- package/src/commands/models.ts +0 -10
- package/src/commands/outdated.ts +0 -115
- package/src/commands/project.ts +0 -580
- package/src/commands/report.ts +0 -66
- package/src/commands/scan.ts +0 -71
- package/src/commands/shared.ts +0 -38
- package/src/commands/skill.ts +0 -33
- package/src/commands/sync.ts +0 -233
- package/src/commands/target.ts +0 -225
- package/src/commands/update.ts +0 -277
- package/src/completions.ts +0 -196
- package/src/concurrency-limiter.ts +0 -61
- package/src/config-service.ts +0 -398
- package/src/config-watcher.ts +0 -253
- package/src/config.ts +0 -583
- package/src/context.ts +0 -188
- package/src/db-audit.ts +0 -286
- package/src/db-index.ts +0 -238
- package/src/db.ts +0 -3
- package/src/deployment.ts +0 -39
- package/src/doctor.ts +0 -205
- package/src/eval.ts +0 -302
- package/src/global-flags.ts +0 -46
- package/src/init-agents.ts +0 -329
- package/src/init-instructions.ts +0 -192
- package/src/init.ts +0 -389
- package/src/install.ts +0 -232
- package/src/lifecycle.ts +0 -51
- package/src/logger.ts +0 -26
- package/src/manifest.ts +0 -352
- package/src/mcp-registration.ts +0 -89
- package/src/metrics.ts +0 -121
- package/src/models.ts +0 -20
- package/src/output.ts +0 -214
- package/src/project-setup.ts +0 -36
- package/src/prompts.ts +0 -124
- package/src/provenance.ts +0 -99
- package/src/rate-limiter.ts +0 -137
- package/src/readiness.ts +0 -30
- package/src/redact.ts +0 -52
- package/src/router-core.ts +0 -666
- package/src/rrf.ts +0 -31
- package/src/scan.ts +0 -300
- package/src/server.ts +0 -930
- package/src/setup.ts +0 -145
- package/src/snapshot.ts +0 -135
- package/src/stats.ts +0 -340
- package/src/sync.ts +0 -482
- package/src/toml-writer.ts +0 -51
- package/src/types.ts +0 -212
- package/src/vault.ts +0 -207
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# CLI surface consistency: the "target" vocabulary
|
|
2
|
+
|
|
3
|
+
Status: proposal. Nothing implemented yet.
|
|
4
|
+
|
|
5
|
+
## The problem
|
|
6
|
+
|
|
7
|
+
The word "target" carries four unrelated meanings across 587 occurrences in
|
|
8
|
+
`src/`. The clearest single demonstration:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
skillmux target list --json
|
|
12
|
+
{"target":"local","data":{"targets":[{"name":"claude-code",...}]}}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The outer `"target"` means "local versus a remote server". The inner
|
|
16
|
+
`"targets"` means "directories skills get delivered into". Same word, same
|
|
17
|
+
payload, unrelated concepts.
|
|
18
|
+
|
|
19
|
+
### The four meanings
|
|
20
|
+
|
|
21
|
+
1. **A delivery target.** A named directory recorded as `[targets.<name>]` in
|
|
22
|
+
the vault manifest. This is what `skillmux target` manages, what
|
|
23
|
+
`project --target <name>` references, what `sync` writes into, and what the
|
|
24
|
+
`.skillmux` marker records as `role: "target"`.
|
|
25
|
+
Types: `Target`, `ConfirmedTarget`, `AdoptTargetResult`,
|
|
26
|
+
`ResolvedBuiltInTarget`, `SyncTargetResult`, `SyncTargetOptions`,
|
|
27
|
+
`SyncTargetParams`, `SyncTargetSummary`, `SyncProjectTargetsParams`.
|
|
28
|
+
|
|
29
|
+
2. **The execution destination.** Local process versus remote admin server,
|
|
30
|
+
selected by `--context`/`--server`.
|
|
31
|
+
Types: `TargetAdapter`, `TargetAdapterOptions`, `createTargetAdapter`,
|
|
32
|
+
`CommandTargetSupport`, `COMMAND_TARGET_SUPPORT`, the JSON envelope's
|
|
33
|
+
`target` field, `renderTargetBanner`, `LocalAdapter`'s `targetName: "local"`.
|
|
34
|
+
|
|
35
|
+
3. **A file being scanned.** `ScanContentTarget` and `ResolvedScanTargets` in
|
|
36
|
+
`scan.ts`. Internal only, never user-facing.
|
|
37
|
+
|
|
38
|
+
4. **An output file path.** `eval promote --target <path>`. User-facing.
|
|
39
|
+
|
|
40
|
+
### Root cause
|
|
41
|
+
|
|
42
|
+
This is not four independent mistakes. Meaning 2 was already being renamed to
|
|
43
|
+
"context" in PR #163, and that rename stopped after `context.ts`. Everything
|
|
44
|
+
downstream still says target:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
src/context.ts:20 export type ResolvedContext renamed
|
|
48
|
+
src/adapters.ts:52 export interface TargetAdapter not renamed, same concept
|
|
49
|
+
src/cli.ts:281 let resolvedTarget: ResolvedContext variable and type disagree
|
|
50
|
+
src/cli.ts:97 COMMAND_TARGET_SUPPORT not renamed
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`cli.ts:281` is the clearest symptom: a variable named `resolvedTarget` holding
|
|
54
|
+
a `ResolvedContext`. The codebase has been sitting mid-rename since #163.
|
|
55
|
+
|
|
56
|
+
## Decision
|
|
57
|
+
|
|
58
|
+
**Meaning 1 keeps the word "target".** It is the correct English use: the
|
|
59
|
+
destination a sync writes into. Everything else borrowed it.
|
|
60
|
+
|
|
61
|
+
Renaming `[targets.<name>]` to `[agents.<name>]` was considered and rejected.
|
|
62
|
+
Agents and targets are many-to-one, not one-to-one, and the manifest would
|
|
63
|
+
start asserting things that are false. Evidence:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
skillmux init --agent opencode --agent github-copilot --agent windsurf --yes
|
|
67
|
+
# produces exactly one target:
|
|
68
|
+
# agent-skills:
|
|
69
|
+
# dir: ~/.agents/skills
|
|
70
|
+
# agents: opencode, github-copilot, windsurf
|
|
71
|
+
|
|
72
|
+
skillmux target add my-scratch --dir ~/scratchdir --yes
|
|
73
|
+
# my-scratch:
|
|
74
|
+
# agents: (custom)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`agent-skills` is not an agent, it is one shared directory serving three of
|
|
78
|
+
them. `my-scratch` belongs to no agent at all. Each target already carries its
|
|
79
|
+
own `agents` list as a field, so renaming the section would collide with that.
|
|
80
|
+
|
|
81
|
+
## Plan
|
|
82
|
+
|
|
83
|
+
### Step 1: finish the #163 rename (meaning 2 becomes "context")
|
|
84
|
+
|
|
85
|
+
Mostly mechanical, mostly internal.
|
|
86
|
+
|
|
87
|
+
| From | To |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `TargetAdapter` | `ContextAdapter` |
|
|
90
|
+
| `TargetAdapterOptions` | `ContextAdapterOptions` |
|
|
91
|
+
| `createTargetAdapter` | `createContextAdapter` |
|
|
92
|
+
| `CommandTargetSupport` | `CommandContextSupport` |
|
|
93
|
+
| `COMMAND_TARGET_SUPPORT` | `COMMAND_CONTEXT_SUPPORT` |
|
|
94
|
+
| `renderTargetBanner` | `renderContextBanner` |
|
|
95
|
+
| `resolvedTarget` (variable) | `resolvedContext` |
|
|
96
|
+
| `emitSuccess({ target })` param | `emitSuccess({ context })` |
|
|
97
|
+
|
|
98
|
+
Critical constraint: meaning 1 also uses the identifier `targetName`, in
|
|
99
|
+
`init.ts`, `project.ts`, and `sync.ts`, where it means a delivery target name.
|
|
100
|
+
Those must not be touched. Only `adapters.ts`'s `targetName: "local"` belongs
|
|
101
|
+
to meaning 2. A blind find-and-replace on this codebase would corrupt the
|
|
102
|
+
manifest layer, which is exactly the disease being cured.
|
|
103
|
+
|
|
104
|
+
### Step 2: the JSON envelope field, additively
|
|
105
|
+
|
|
106
|
+
The envelope's `target` field is public API and documented in `docs/cli.md`.
|
|
107
|
+
Renaming it outright is breaking, and the project is releasing 1.11.0, a minor.
|
|
108
|
+
|
|
109
|
+
Emit `context` alongside `target` with identical content, mark `target`
|
|
110
|
+
deprecated in code and docs, and remove it at the next major. This mirrors
|
|
111
|
+
what PR #177 did for the `init` envelope.
|
|
112
|
+
|
|
113
|
+
### Step 3: rename meaning 3
|
|
114
|
+
|
|
115
|
+
`ScanContentTarget` becomes `ScanContentFile`, `ResolvedScanTargets` becomes
|
|
116
|
+
`ResolvedScanFiles`. Internal only, so no compatibility concern.
|
|
117
|
+
|
|
118
|
+
### Step 4: `eval promote --target` becomes `--out`
|
|
119
|
+
|
|
120
|
+
A destination file path is defensible English on its own, but inside this CLI
|
|
121
|
+
"target" is a first-class noun you can `target list`. A `--target` that takes a
|
|
122
|
+
file path and cannot be listed, attached, or synced is the odd one out.
|
|
123
|
+
|
|
124
|
+
Add `--out <path>`, keep `--target` as a deprecated alias, remove the alias at
|
|
125
|
+
the next major.
|
|
126
|
+
|
|
127
|
+
## End state
|
|
128
|
+
|
|
129
|
+
- **target** means a delivery directory, and nothing else.
|
|
130
|
+
- **context** means local versus remote.
|
|
131
|
+
- `scan` uses its own internal vocabulary.
|
|
132
|
+
- `eval promote` writes to `--out`.
|
|
133
|
+
|
|
134
|
+
## Compatibility summary
|
|
135
|
+
|
|
136
|
+
| Change | Breaking? | Path |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| Steps 1 and 3 | No | Internal identifiers only |
|
|
139
|
+
| Step 2 | No | Additive, `target` deprecated |
|
|
140
|
+
| Step 4 | No | `--out` added, `--target` aliased |
|
|
141
|
+
|
|
142
|
+
## Out of scope
|
|
143
|
+
|
|
144
|
+
Carried over from the earlier surface review, unchanged and still open:
|
|
145
|
+
|
|
146
|
+
- `scan --format json` bypasses the documented envelope.
|
|
147
|
+
- `install` is the only mutating command with no confirmation gate.
|
|
148
|
+
- `sync`, `install`, `update`, and `outdated` document none of their flags.
|
|
149
|
+
- The top-level help's `init` line omits `--show-mcp-setup`/`--register-mcp`.
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Skillmux Routing Reliability Plan
|
|
2
|
+
|
|
3
|
+
Status: approved for specification and implementation
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
Give Skillmux a predictable OSS configuration contract, a bounded ranking
|
|
8
|
+
pipeline, and visible inference failures. Measure routing behavior before adding
|
|
9
|
+
policy machinery. Ship one foundation release, then adopt it in Bifrost through
|
|
10
|
+
one infra change.
|
|
11
|
+
|
|
12
|
+
## Problem
|
|
13
|
+
|
|
14
|
+
Skillmux accepts generic environment variables such as `EMBED_MODEL`. A parent
|
|
15
|
+
process can set the same name for another purpose. The inherited value then
|
|
16
|
+
overrides Skillmux's TOML file.
|
|
17
|
+
|
|
18
|
+
Skillmux also reranks the full lexical and vector union. With
|
|
19
|
+
`k_lexical = 15` and `k_vector = 15`, one request can send 30 documents to the
|
|
20
|
+
reranker. The current code catches inference errors and timeouts, then returns a
|
|
21
|
+
degraded retrieval result without the failure reason.
|
|
22
|
+
|
|
23
|
+
The production incident on 2026-08-17 demonstrated both failures. Bifrost's
|
|
24
|
+
`EMBED_MODEL` replaced the model in Skillmux's TOML file, so Infinity returned
|
|
25
|
+
HTTP 400. After environment isolation restored embeddings, a 10-second timeout
|
|
26
|
+
expired before the reranker finished. Infra PRs #45 and #46 restored production
|
|
27
|
+
with child-environment sanitization, smaller recall lanes, and a 30-second
|
|
28
|
+
timeout. Those changes remain safeguards until Bifrost adopts the release from
|
|
29
|
+
this plan.
|
|
30
|
+
|
|
31
|
+
A live reranked request also exposed a separate problem. For a bounded DNS
|
|
32
|
+
command, the semantic reranker placed the broad `cloudflare` mission skill above
|
|
33
|
+
the direct `infra-cli` executor. The result was relevant by topic but wrong by
|
|
34
|
+
operational ownership. This plan measures that failure class before deciding
|
|
35
|
+
whether Skillmux needs routing contracts.
|
|
36
|
+
|
|
37
|
+
## Target Ranking Pipeline
|
|
38
|
+
|
|
39
|
+
The intended pipeline is:
|
|
40
|
+
|
|
41
|
+
1. Resolve an exact skill ID or exact title match.
|
|
42
|
+
2. Retrieve lexical and vector candidates.
|
|
43
|
+
3. Fuse both ranked lists with reciprocal rank fusion (RRF).
|
|
44
|
+
4. Send only the top `k_rerank` fused candidates to the semantic reranker.
|
|
45
|
+
5. Apply routing-contract eligibility if the evidence gate justifies it.
|
|
46
|
+
6. Apply calibrated decision thresholds and return `matched`, `ambiguous`, or
|
|
47
|
+
`no_match`.
|
|
48
|
+
|
|
49
|
+
RRF is the cheap candidate-generation stage. The reranker performs the more
|
|
50
|
+
expensive semantic comparison. `k_rerank` controls reranker input, while the
|
|
51
|
+
ambiguous candidate limit controls response output. They are separate budgets.
|
|
52
|
+
|
|
53
|
+
The foundation release stops after step 4 and improves the visibility of step
|
|
54
|
+
6. Step 5 belongs to a later release unless the evaluation report proves that
|
|
55
|
+
ranking quality alone cannot enforce skill ownership.
|
|
56
|
+
|
|
57
|
+
## Configuration Contract
|
|
58
|
+
|
|
59
|
+
Skillmux uses this precedence when environment overrides are enabled:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
CLI flags
|
|
63
|
+
SKILLMUX_* environment variables
|
|
64
|
+
TOML configuration
|
|
65
|
+
defaults
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Skillmux must stop using generic `EMBED_*` and `RERANK_*` variables. The 1.x
|
|
69
|
+
line emits migration warnings. Skillmux 2.0 removes support.
|
|
70
|
+
|
|
71
|
+
Add this TOML policy:
|
|
72
|
+
|
|
73
|
+
```toml
|
|
74
|
+
[config]
|
|
75
|
+
environment_overrides = true
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`true` remains the OSS default. `false` makes TOML authoritative for behavioral
|
|
79
|
+
settings. Skillmux must still read:
|
|
80
|
+
|
|
81
|
+
- `SKILLMUX_CONFIG`, which locates the TOML file
|
|
82
|
+
- secret variables named by `api_key_env`
|
|
83
|
+
- process variables required by the runtime, such as `HOME` and `PATH`
|
|
84
|
+
- explicit CLI flags for the current invocation
|
|
85
|
+
|
|
86
|
+
`SKILLMUX_CONFIG_READONLY` keeps its current meaning. It prevents admin API
|
|
87
|
+
writes to configuration managed outside Skillmux. It does not control
|
|
88
|
+
precedence.
|
|
89
|
+
|
|
90
|
+
## Rerank Budget
|
|
91
|
+
|
|
92
|
+
Add `recall.k_rerank`:
|
|
93
|
+
|
|
94
|
+
```toml
|
|
95
|
+
[recall]
|
|
96
|
+
k_lexical = 15
|
|
97
|
+
k_vector = 15
|
|
98
|
+
k_rerank = 5
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Skillmux retrieves each lane, fuses the results, truncates the fused list to
|
|
102
|
+
`k_rerank`, and sends that list to the reranker. Decision thresholds run on the
|
|
103
|
+
reranked list.
|
|
104
|
+
|
|
105
|
+
Validation rules:
|
|
106
|
+
|
|
107
|
+
- `k_lexical`, `k_vector`, and `k_rerank` are positive integers.
|
|
108
|
+
- `k_rerank` does not exceed `k_lexical + k_vector` after configuration loads.
|
|
109
|
+
- The default supports existing installations without an invalid config.
|
|
110
|
+
- The generated example and JSON schema state the default and limits.
|
|
111
|
+
|
|
112
|
+
Benchmark `k_rerank` values of 5, 10, 15, and 20. Choose the smallest OSS
|
|
113
|
+
default that meets the candidate-recall and latency gates. Bifrost must set the
|
|
114
|
+
measured value in TOML instead of copying an arbitrary value from the incident
|
|
115
|
+
mitigation.
|
|
116
|
+
|
|
117
|
+
The current `[thresholds].candidate_limit` name is vague because it controls
|
|
118
|
+
only the candidates returned for an ambiguous result. Introduce
|
|
119
|
+
`[output].ambiguous_candidate_limit` and keep the old key as a deprecated 1.x
|
|
120
|
+
alias. Remove the alias in 2.0 with the other configuration migrations.
|
|
121
|
+
|
|
122
|
+
## Degraded Retrieval Contract
|
|
123
|
+
|
|
124
|
+
Keep safe fallback behavior. Add structured degradation metadata when a later
|
|
125
|
+
retrieval stage fails:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"outcome": "ambiguous",
|
|
130
|
+
"retrieval": "hybrid",
|
|
131
|
+
"degraded_from": "reranked",
|
|
132
|
+
"degradation_reason": "reranker_timeout",
|
|
133
|
+
"candidates": []
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use stable reason codes:
|
|
138
|
+
|
|
139
|
+
- `embedding_timeout`
|
|
140
|
+
- `embedding_unavailable`
|
|
141
|
+
- `embedding_protocol_error`
|
|
142
|
+
- `reranker_timeout`
|
|
143
|
+
- `reranker_unavailable`
|
|
144
|
+
- `reranker_protocol_error`
|
|
145
|
+
|
|
146
|
+
Return safe codes through MCP. Write detailed errors to service logs. Add one
|
|
147
|
+
metric counter labelled by stage and reason. Audit rows must retain the safe
|
|
148
|
+
reason without storing credentials, response bodies, or endpoint URLs that may
|
|
149
|
+
contain credentials.
|
|
150
|
+
|
|
151
|
+
## Implementation Work
|
|
152
|
+
|
|
153
|
+
### Change 1: Configuration authority
|
|
154
|
+
|
|
155
|
+
Update the config types, defaults, TOML loader, environment override layer,
|
|
156
|
+
configuration provenance, JSON schema, CLI documentation, deployment examples,
|
|
157
|
+
and migration notes.
|
|
158
|
+
|
|
159
|
+
The loader must distinguish three inputs:
|
|
160
|
+
|
|
161
|
+
1. Namespaced behavioral overrides such as `SKILLMUX_EMBED_MODEL`.
|
|
162
|
+
2. Deprecated generic aliases such as `EMBED_MODEL`.
|
|
163
|
+
3. Secret variables named by an `api_key_env` field.
|
|
164
|
+
|
|
165
|
+
When `environment_overrides = false`, the loader ignores category 1, warns for
|
|
166
|
+
category 2 during the 1.x migration window, and resolves category 3 at request
|
|
167
|
+
time. `config show --sources` and `doctor` must report the policy and the source
|
|
168
|
+
of each effective behavioral value.
|
|
169
|
+
|
|
170
|
+
### Change 2: Bounded reranking
|
|
171
|
+
|
|
172
|
+
Add `k_rerank` to the recall type and schema. In `retrieveAndRerank`, fuse the
|
|
173
|
+
lexical and vector results, then slice the fused list before building reranker
|
|
174
|
+
documents. Preserve each candidate's skill ID, title, description, and score.
|
|
175
|
+
|
|
176
|
+
Calibration and evaluation must use the same cap as runtime. Dataset generation
|
|
177
|
+
must record the effective recall and rerank settings so a calibration run cannot
|
|
178
|
+
move between configurations without an error.
|
|
179
|
+
|
|
180
|
+
### Change 3: Failure visibility
|
|
181
|
+
|
|
182
|
+
Replace broad inference catches with classification that maps
|
|
183
|
+
`RemoteInferenceError.kind`, timeouts, and transport failures to stable reason
|
|
184
|
+
codes. Preserve fallback. Return the degradation fields, write one structured
|
|
185
|
+
log entry, increment metrics, and store the safe code in the audit row.
|
|
186
|
+
|
|
187
|
+
Do not expose raw exception text through MCP.
|
|
188
|
+
|
|
189
|
+
### Change 4: Routing evidence gate
|
|
190
|
+
|
|
191
|
+
Build a sequential labelled corpus that includes direct execution,
|
|
192
|
+
investigation, cross-system correlation, and non-match prompts. For every case,
|
|
193
|
+
record the fused rank, reranked rank, final outcome, latency, effective ranking
|
|
194
|
+
settings, and degradation state.
|
|
195
|
+
|
|
196
|
+
The foundation is acceptable when:
|
|
197
|
+
|
|
198
|
+
- the expected skill enters the reranker pool for direct and investigative
|
|
199
|
+
prompts
|
|
200
|
+
- at least 99 percent of evaluation cases complete without degraded retrieval
|
|
201
|
+
- p95 latency stays within the published service budget
|
|
202
|
+
- non-match prompts do not become confident false matches
|
|
203
|
+
|
|
204
|
+
If the expected skill reaches the reranker but loses on ownership despite
|
|
205
|
+
matching the topic, classify the case as an ownership failure. That result opens
|
|
206
|
+
the routing-contract phase. Retrieval misses, fusion-order errors, and reranker
|
|
207
|
+
errors remain ranking work.
|
|
208
|
+
|
|
209
|
+
### Change 5: Routing contracts, gated follow-up
|
|
210
|
+
|
|
211
|
+
Do not implement this change in the foundation release. If the evidence gate
|
|
212
|
+
opens the phase, write a separate specification for generic skill metadata such
|
|
213
|
+
as:
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
routing:
|
|
217
|
+
accepts: [bounded_execution]
|
|
218
|
+
rejects: [investigation, cross_system_correlation]
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Apply eligibility after semantic reranking and before decision thresholds. If
|
|
222
|
+
the request intent is uncertain, return `ambiguous` instead of forcing a match.
|
|
223
|
+
The specification must define intent extraction, schema validation, conflicting
|
|
224
|
+
contracts, metadata provenance, audit output, and compatibility for skills with
|
|
225
|
+
no routing metadata. It must not encode provider names or special cases in the
|
|
226
|
+
Skillmux engine.
|
|
227
|
+
|
|
228
|
+
## Acceptance Criteria
|
|
229
|
+
|
|
230
|
+
1. A generic `EMBED_MODEL` cannot change the effective model without a 1.x
|
|
231
|
+
deprecation warning. Skillmux 2.0 rejects or ignores it according to the
|
|
232
|
+
published migration contract.
|
|
233
|
+
2. `SKILLMUX_EMBED_MODEL` overrides TOML when
|
|
234
|
+
`config.environment_overrides = true`.
|
|
235
|
+
3. TOML wins when `config.environment_overrides = false`.
|
|
236
|
+
4. `api_key_env` resolves its named secret under both policies.
|
|
237
|
+
5. `config show --sources` and `doctor` identify the override policy and each
|
|
238
|
+
behavioral value's source.
|
|
239
|
+
6. Runtime sends no more than `k_rerank` documents to the reranker.
|
|
240
|
+
7. Lexical and vector retrieval still use their configured lane sizes before
|
|
241
|
+
fusion and truncation.
|
|
242
|
+
8. Calibration and runtime use the same `k_rerank` value.
|
|
243
|
+
9. An embedding failure returns lexical retrieval with the correct safe reason.
|
|
244
|
+
10. A reranker timeout returns hybrid retrieval with
|
|
245
|
+
`degraded_from = "reranked"` and `reranker_timeout`.
|
|
246
|
+
11. Successful inference returns `retrieval = "reranked"` without degradation
|
|
247
|
+
fields.
|
|
248
|
+
12. Logs, metrics, and audit rows record the failure class without secret data.
|
|
249
|
+
13. Existing installations with no new settings load a documented default.
|
|
250
|
+
14. The full unit, CLI, MCP, doctor, calibration, and Docker smoke suites pass.
|
|
251
|
+
15. Evaluation output records each candidate's fused rank, reranked rank, final
|
|
252
|
+
outcome, latency, ranking settings, and degradation state.
|
|
253
|
+
16. Routing contracts cannot enter the foundation release. A separate
|
|
254
|
+
specification starts only when the evidence gate identifies ownership
|
|
255
|
+
failures.
|
|
256
|
+
17. `ambiguous_candidate_limit` controls ambiguous response output and the old
|
|
257
|
+
`candidate_limit` alias emits the documented 1.x migration warning.
|
|
258
|
+
|
|
259
|
+
## Test Plan
|
|
260
|
+
|
|
261
|
+
Add focused tests before each behavior change:
|
|
262
|
+
|
|
263
|
+
- config precedence matrix for TOML, namespaced environment, generic aliases,
|
|
264
|
+
strict policy, and CLI flags
|
|
265
|
+
- secret resolution under both environment policies
|
|
266
|
+
- provenance and doctor output
|
|
267
|
+
- `k_rerank` validation and request-document count
|
|
268
|
+
- ambiguous output-limit migration and behavior
|
|
269
|
+
- calibration metadata compatibility
|
|
270
|
+
- timeout, availability, and protocol fallback codes
|
|
271
|
+
- MCP response, audit row, structured log, and metric output
|
|
272
|
+
- Docker smoke coverage with a polluted parent environment
|
|
273
|
+
- ownership-versus-relevance fixtures where executor and mission skills share a
|
|
274
|
+
provider topic
|
|
275
|
+
|
|
276
|
+
Use fake inference clients for deterministic unit tests. Add one HTTP adapter
|
|
277
|
+
integration test that verifies cancellation and timeout classification.
|
|
278
|
+
|
|
279
|
+
## Compatibility and Release
|
|
280
|
+
|
|
281
|
+
Ship the foundation work in reviewable PRs, then publish one release:
|
|
282
|
+
|
|
283
|
+
1. Configuration authority and migration warnings.
|
|
284
|
+
2. Rerank budget and calibration metadata.
|
|
285
|
+
3. Degradation responses, logs, metrics, and audit data.
|
|
286
|
+
4. Documentation, examples, and release notes.
|
|
287
|
+
5. Sequential evaluation report and selected defaults.
|
|
288
|
+
|
|
289
|
+
Do not publish an intermediate GHCR image for Bifrost. Merge the full set,
|
|
290
|
+
release one Skillmux version through GitHub Actions, and verify the image digest
|
|
291
|
+
and smoke tests before changing infra.
|
|
292
|
+
|
|
293
|
+
Routing contracts use a second release. Start that work only after the
|
|
294
|
+
foundation is running in Bifrost and the evidence report passes the gate.
|
|
295
|
+
|
|
296
|
+
## Bifrost Adoption
|
|
297
|
+
|
|
298
|
+
Create one follow-up PR in `klhq/infra` after the GHCR release:
|
|
299
|
+
|
|
300
|
+
- update the pinned Skillmux GHCR version
|
|
301
|
+
- set `config.environment_overrides = false`
|
|
302
|
+
- restore `k_lexical = 15` and `k_vector = 15`
|
|
303
|
+
- set `k_rerank` to the measured value from the foundation evaluation
|
|
304
|
+
- retain `timeout_ms = 30000` for the first deployment
|
|
305
|
+
- set `SKILLMUX_CONFIG_READONLY=true`
|
|
306
|
+
- remove unused `SKILLMUX_EMBED_KEY`
|
|
307
|
+
- keep wrapper sanitization for one release as defense in depth
|
|
308
|
+
|
|
309
|
+
Deploy through the Bifrost Forgejo workflow and Komodo. Verify the child
|
|
310
|
+
environment, `doctor`, one live reranked request, and the sequential training
|
|
311
|
+
corpus. Keep wrapper sanitization until strict config mode has production
|
|
312
|
+
evidence, then remove it in a later infra change.
|
|
313
|
+
|
|
314
|
+
Classify the sequential report before opening more implementation work:
|
|
315
|
+
|
|
316
|
+
- retrieval, fusion, or reranker failures return to the ranking pipeline
|
|
317
|
+
- ownership failures open the routing-contract specification
|
|
318
|
+
- a clean report freezes a fresh v2 held-out corpus for later regression tests
|
|
319
|
+
|
|
320
|
+
## Out of Scope
|
|
321
|
+
|
|
322
|
+
- New embedding or reranker models
|
|
323
|
+
- Threshold calibration for the infra routing corpus
|
|
324
|
+
- Mission-skill renames
|
|
325
|
+
- Removal of generic aliases before the documented major release
|
|
326
|
+
- Provider-specific ownership rules hard-coded in Skillmux
|
|
327
|
+
- Routing-contract implementation inside the foundation release
|
|
328
|
+
|
|
329
|
+
## Handoff
|
|
330
|
+
|
|
331
|
+
Implement the foundation work in `klhq/skillmux`. Keep configuration authority,
|
|
332
|
+
bounded reranking, failure visibility, and evaluation support in separate
|
|
333
|
+
commits or PRs. Publish one foundation release. Do not edit `klhq/infra` until
|
|
334
|
+
Skillmux publishes that release and its GHCR smoke tests pass.
|
|
335
|
+
|
|
336
|
+
After Bifrost produces the sequential report, apply the evidence gate. If it
|
|
337
|
+
shows ownership failures, create a separate routing-contract specification and
|
|
338
|
+
release plan. Do not fold that design into the foundation implementation.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Review: Configuration Authority and Rerank Resilience
|
|
2
|
+
|
|
3
|
+
Verdict: Code findings resolved. Release evidence remains pending.
|
|
4
|
+
|
|
5
|
+
## Remediation
|
|
6
|
+
|
|
7
|
+
The 2026-08-17 fix pass resolved findings 1 through 4 and finding 6:
|
|
8
|
+
|
|
9
|
+
- evaluation now uses the production retrieval, RRF, reranker, degradation,
|
|
10
|
+
and decision functions
|
|
11
|
+
- fused and reranked ranks come from the same execution that produces the
|
|
12
|
+
recorded outcome
|
|
13
|
+
- degradation logs no longer contain the raw query
|
|
14
|
+
- calibration evidence persists effective recall settings, and doctor marks a
|
|
15
|
+
run stale when those settings drift
|
|
16
|
+
- doctor receives and reports behavioral configuration provenance
|
|
17
|
+
- strict mode tests cover `SKILLMUX_CONFIG` and `SKILLMUX_CONFIG_READONLY`
|
|
18
|
+
|
|
19
|
+
Finding 5 is release evidence, not a code defect. Run the sequential corpus at
|
|
20
|
+
`k_rerank` values 5, 10, 15, and 20 against the deployed inference service.
|
|
21
|
+
Select the default only after candidate recall, p95 latency, degradation rate,
|
|
22
|
+
and non-match safety meet the gates in the approved plan.
|
|
23
|
+
|
|
24
|
+
Reviewed `main...feat/config-authority-rerank-resilience` against `spec.md` and
|
|
25
|
+
the approved routing reliability plan. Runtime tests pass, but the evaluation
|
|
26
|
+
contract and several observability requirements are incomplete.
|
|
27
|
+
|
|
28
|
+
## Findings
|
|
29
|
+
|
|
30
|
+
### 1. High: Evaluation output does not execute the runtime ranking pipeline
|
|
31
|
+
|
|
32
|
+
`src/eval.ts:99` builds lexical and vector results itself. It never calls the
|
|
33
|
+
configured reranker or the decision function. At `src/eval.ts:126`, every case
|
|
34
|
+
is recorded as `outcome: "ambiguous"` and `retrieval: "hybrid"` regardless of
|
|
35
|
+
the real result. `reranked_rank` is declared but never populated, and
|
|
36
|
+
degradation fields cannot be produced by this path.
|
|
37
|
+
|
|
38
|
+
This does not satisfy AC 4.1 and cannot distinguish a retrieval miss, reranker
|
|
39
|
+
failure, threshold error, or ownership failure. Reuse the production retrieval
|
|
40
|
+
and decision path, or extract one shared instrumented pipeline that returns
|
|
41
|
+
fused rank, reranked rank, outcome, latency, and degradation data.
|
|
42
|
+
|
|
43
|
+
### 2. High: Degradation logs copy the raw user query
|
|
44
|
+
|
|
45
|
+
`src/router-core.ts:558` and `src/router-core.ts:585` write `input.query` into
|
|
46
|
+
service logs when inference fails. A query may contain a credential, signed
|
|
47
|
+
URL, customer data, or other sensitive input. This conflicts with AC 3.3's safe
|
|
48
|
+
sanitization requirement and creates a new disclosure path outside the audit
|
|
49
|
+
store.
|
|
50
|
+
|
|
51
|
+
Remove the raw query from these warning records. Log a request or audit ID,
|
|
52
|
+
stage, safe reason code, and timing instead. If query logging is a supported
|
|
53
|
+
operator feature, it needs an explicit redaction and retention policy.
|
|
54
|
+
|
|
55
|
+
### 3. Medium: Calibration evidence omits the effective ranking settings
|
|
56
|
+
|
|
57
|
+
The branch adds `recall_settings` only to `src/eval.ts`. The calibration and
|
|
58
|
+
dataset evidence paths contain no `k_lexical`, `k_vector`, or `k_rerank`
|
|
59
|
+
metadata. This leaves AC 2.3 incomplete and permits a calibration artifact to be
|
|
60
|
+
applied under a different candidate budget without detecting the mismatch.
|
|
61
|
+
|
|
62
|
+
Persist the effective recall settings with calibration and dataset evidence.
|
|
63
|
+
Reject or mark stale any run whose settings differ from runtime.
|
|
64
|
+
|
|
65
|
+
### 4. Medium: Doctor reports policy but not value provenance
|
|
66
|
+
|
|
67
|
+
`src/doctor.ts:111` adds one `config_authority` check. It does not report the
|
|
68
|
+
source of each behavioral value as required by AC 1.5. `config show --sources`
|
|
69
|
+
has a source map, but doctor does not expose equivalent provenance.
|
|
70
|
+
|
|
71
|
+
Share the effective-source map with doctor and report at least every supported
|
|
72
|
+
behavioral override. Include `server.allowed_origins`, which is recognized by
|
|
73
|
+
`isEnvMasked` but absent from the source-map key list at
|
|
74
|
+
`src/config-service.ts:146`.
|
|
75
|
+
|
|
76
|
+
### 5. Medium: The foundation evidence gate and selected default are absent
|
|
77
|
+
|
|
78
|
+
The approved plan requires benchmarks for `k_rerank` values 5, 10, 15, and 20,
|
|
79
|
+
a sequential labelled evaluation report, and a selected default backed by the
|
|
80
|
+
candidate-recall and latency gates. The branch hard-codes a default of 10 and
|
|
81
|
+
contains no benchmark or sequential report.
|
|
82
|
+
|
|
83
|
+
Complete the evaluation implementation first. Then check in the reproducible
|
|
84
|
+
report or release evidence that selects the OSS default.
|
|
85
|
+
|
|
86
|
+
### 6. Low: Strict-mode exempt controls lack combined coverage
|
|
87
|
+
|
|
88
|
+
The suite tests `SKILLMUX_CONFIG` and `SKILLMUX_CONFIG_READONLY` in other
|
|
89
|
+
contexts, but it does not verify that both remain effective when
|
|
90
|
+
`config.environment_overrides = false`. Add one strict-mode integration test
|
|
91
|
+
covering these exemptions.
|
|
92
|
+
|
|
93
|
+
## Verification
|
|
94
|
+
|
|
95
|
+
- `bun test`: PASS, 644 passed and 0 failed
|
|
96
|
+
- `git diff --check main...HEAD`: PASS
|
|
97
|
+
- Build check: SKIPPED, no build command was supplied to the review recipe
|
|
98
|
+
- Performance pass: no finding
|
|
99
|
+
- Security, correctness, and compliance delegated passes hit a temporary model
|
|
100
|
+
rate limit and were completed manually
|
|
101
|
+
|
|
102
|
+
## AC Status
|
|
103
|
+
|
|
104
|
+
| Criterion | Status | Notes |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| AC 1.1 Precedence and policy | ✅ Done | Namespaced environment overrides follow the configured policy. |
|
|
107
|
+
| AC 1.2 Strict TOML mode | ✅ Done | Behavioral overrides are ignored in strict mode. |
|
|
108
|
+
| AC 1.3 Exempt variables | ✅ Done | Strict mode covers config location, read-only control, and secret resolution. |
|
|
109
|
+
| AC 1.4 Generic environment and deprecated keys | ✅ Done | Migration warnings and aliases are implemented. |
|
|
110
|
+
| AC 1.5 Provenance and diagnostics | ✅ Done | Config show and doctor report behavioral value sources. |
|
|
111
|
+
| AC 1.6 Output candidate limit | ✅ Done | New output key controls ambiguous results with a legacy alias. |
|
|
112
|
+
| AC 2.1 Schema and validation | ✅ Done | `k_rerank` is typed, defaulted, and bounded against both lanes. |
|
|
113
|
+
| AC 2.2 Runtime fusion and truncation | ✅ Done | The fused list is truncated before reranker input. |
|
|
114
|
+
| AC 2.3 Calibration and evaluation alignment | ✅ Done | Calibration evidence stores recall settings and doctor detects drift. |
|
|
115
|
+
| AC 3.1 Stable error codes | ✅ Done | Error classes map to the specified codes. |
|
|
116
|
+
| AC 3.2 Safe fallback and metadata | ✅ Done | Embedding and reranker failures preserve a surviving lane. |
|
|
117
|
+
| AC 3.3 MCP and safe sanitization | ✅ Done | Failure logs contain safe stage and reason fields without the raw query. |
|
|
118
|
+
| AC 4.1 Evaluation case output | ✅ Done | Evaluation uses production ranking and records actual ranks, outcome, and degradation. |
|
|
119
|
+
|
|
120
|
+
## Security Escalation
|
|
121
|
+
|
|
122
|
+
A dedicated security review is recommended before shipping because the change
|
|
123
|
+
touches remote network egress, credentials referenced through environment
|
|
124
|
+
variables, public MCP response fields, and persistent audit data.
|