@kontextmind/kxm 0.7.150 → 0.7.151
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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +14 -0
- package/docs/architecture/agent-path.md +5 -0
- package/docs/operations/troubleshooting.md +1 -0
- package/docs/reference/cli-reference.md +4 -4
- package/docs/reference/config-reference.md +17 -4
- package/docs/reference/harness-routing.md +7 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +153 -60
- package/plugins/kxm/dist/core.js +22 -3
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime-supervisor.js +676 -130
- package/plugins/kxm/dist/runtime.js +720 -164
- package/plugins/kxm/dist/server.js +1 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/system.ts +4 -1
- package/plugins/kxm/src/engine-fold.ts +1 -0
- package/plugins/kxm/src/engine.ts +264 -22
- package/plugins/kxm/src/improve-sources.ts +17 -3
- package/plugins/kxm/src/improve.ts +14 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/policy-draft.mjs +2 -2
- package/plugins/kxm/src/role.ts +1 -1
- package/plugins/kxm/src/route-fallback.ts +504 -0
- package/plugins/kxm/src/route-switch.ts +49 -0
- package/plugins/kxm/src/routing.ts +24 -1
- package/schemas/common.schema.json +2 -1
- package/schemas/role.schema.json +1 -1
- package/schemas/run-event.schema.json +20 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,20 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
6
6
|
|
|
7
7
|
### Added
|
|
8
8
|
|
|
9
|
+
- **An opted-in role continues a failed attempt on the next admitted route.**
|
|
10
|
+
`policy.fallback.onError` lists `rate_limit`, `transport`,
|
|
11
|
+
`provider_unavailable`, and `context_overflow`. An empty or absent list is
|
|
12
|
+
unchanged: the attempt fails on the first route. The walk is bounded by
|
|
13
|
+
`maxSwitches` (default 1), skips a critic-vendor collision when the role
|
|
14
|
+
requires vendor independence, and records `routing.route_switched` plus a
|
|
15
|
+
`route_switch` log line. A bounded redacted transcript is appended to the
|
|
16
|
+
next prompt. `revert: never` keeps the successful route for later steps in
|
|
17
|
+
the same run. `kxm routing report` and `kxm improve report` show the switch.
|
|
18
|
+
Cancellation, policy refusal, authentication, an unhosted model, a gate
|
|
19
|
+
failure, tool policy, and admission errors do not walk. See
|
|
20
|
+
[role fallback](docs/reference/config-reference.md#kxmrolesroleyaml-kxmrolev2)
|
|
21
|
+
and [mid-attempt fallback](docs/reference/harness-routing.md#mid-attempt-fallback).
|
|
22
|
+
|
|
9
23
|
- **A live agent step uses a configurable one-shot timeout, and a cancelling run recovers when its child has already exited.**
|
|
10
24
|
The bound is the step `timeoutMs`, or the project `limits.agentStepTimeoutMs`
|
|
11
25
|
when the step omits it (minimum 60 seconds, default one hour). A wider step
|
|
@@ -14,6 +14,11 @@ a checkout fingerprint, invokes the producer, then fingerprints again
|
|
|
14
14
|
does not change the tree cannot stay `passed`. A read-only step that changes
|
|
15
15
|
the tree cannot stay `passed`.
|
|
16
16
|
|
|
17
|
+
When the step's role lists the failure on `policy.fallback.onError`, a
|
|
18
|
+
walkable producer error is redispatched on the next admitted route before the
|
|
19
|
+
attempt settles. The engine records `routing.route_switched` and logs
|
|
20
|
+
`route_switch`. An empty or absent list does not take this path.
|
|
21
|
+
|
|
17
22
|
```mermaid
|
|
18
23
|
sequenceDiagram
|
|
19
24
|
participant CLI as kxm CLI
|
|
@@ -207,6 +207,7 @@ A gate step declares an outcome its `expect` value never produces. The message n
|
|
|
207
207
|
| `runtime_supervisor_unreachable` | A live supervisor process does not answer its token probe | Check the PID from `kxm runtime status`, stop a hung process with your OS tools, then `kxm runtime start` |
|
|
208
208
|
| `project_required` | The command ran outside a KXM project | Run it from the checkout, or run `kxm init` |
|
|
209
209
|
| `producer_route_not_admitted` | A live drive uses a model route that is not admitted | `kxm routes admit --model <provider/model>`, or drive with `--simulated` |
|
|
210
|
+
| A 429, timeout, or provider error fails the attempt on the first route | The role's `policy.fallback.onError` is empty, omits that class, or `maxSwitches` is already spent. Cancellation, policy refusal, and authentication do not walk | List the class on the role, admit the next route, and read `routing.route_switched` in the run events. `kxm routing report` prints Route switches |
|
|
210
211
|
| `pi_not_authenticated: pi harness not detected (pi_native_impersonation_blocked)` | A Pi agent's model belongs to a vendor with its own harness | Set the agent's native `harness:`, or choose an admitted Pi route whose vendor has none |
|
|
211
212
|
| `run_busy` (HTTP 409) | The run is already admitted or queued for a drive | Wait, and check `kxm runs status <run-id>` |
|
|
212
213
|
| A run store is refused with `runtime_schema_outdated` | The store predates this release | See [Upgrade KXM](upgrade.md#understand-schema-changes) |
|
|
@@ -1688,7 +1688,7 @@ kxm runs status --dry-run refused: the Runtime supervisor is not running and --d
|
|
|
1688
1688
|
kxm runs drive <runId> [--simulated] [--wait] [--timeout-ms <n>] [--lane <unit>]
|
|
1689
1689
|
```
|
|
1690
1690
|
|
|
1691
|
-
Opens a drive of the run. With `--simulated`, a model-free producer reports every agent step as passed. Without `--simulated` the drive runs in live mode: each agent step invokes its harness through a one-shot producer, and the agent's model must be an admitted route (otherwise `producer_route_not_admitted
|
|
1691
|
+
Opens a drive of the run. With `--simulated`, a model-free producer reports every agent step as passed. Without `--simulated` the drive runs in live mode: each agent step invokes its harness through a one-shot producer, and the agent's model must be an admitted route (otherwise `producer_route_not_admitted`). When the role's `policy.fallback.onError` lists the failure class, the same attempt continues on the next admitted route and records `routing.route_switched`; an empty or absent list fails the attempt on the first route. A read-only step runs with the harness's read-only flags. A step with `write` access runs with an audited writer profile, which only `pi` and `grok` have; it must be a single assignment in a project whose `limits.maxConcurrentRuns` is 1, and its route must be on the writer roster in `.kxm/roles/writer.yaml`. Otherwise the drive hands the run off with `step_unsupported`. Around each live attempt the Runtime fingerprints the checkout with `git rev-parse HEAD`, `git status`, and `git diff`: a write step settles `passed` only when the checkout changed (routing metadata `authored: true`), and a read-only step that changed it settles `failed` (`authoringWitness: readonly_mutated`).
|
|
1692
1692
|
|
|
1693
1693
|
| Option | Argument | Default | Description |
|
|
1694
1694
|
|---|---|---|---|
|
|
@@ -3415,7 +3415,7 @@ Generate the improvement report and candidates from routing records. Inside a KX
|
|
|
3415
3415
|
- Reads `improvement.*` from the project and user configuration (see [`kxm.config.v1`](config-reference.md#personalization-settings-kxmconfigv1)) and reports each candidate's promotion readiness under `improvement.promotionPolicy`. Readiness never authorizes anything. Under `critic_quorum` every candidate reports not ready, because this command cites no critic receipts. A configuration that cannot be loaded exits 1 with `config_invalid`.
|
|
3416
3416
|
- A Runtime store that exists but cannot be read exits 1 with `improve_source_unreadable`; `detail` names the path.
|
|
3417
3417
|
- Writes candidate files under `--out-dir` (relative to the current directory) and the report at `.kxm/assets/improvements/<timestamp>.json`. Honors `--dry-run` (writes neither). No hub needed.
|
|
3418
|
-
- JSON keys: `path`, `events`, `recordsCount`, `groupsCount`, `candidatesCount`, `candidates`, `report` (`schema`, `createdAt`, `reviewDecision`, `recordsCount`, `groups`, `candidates`, `promotionPolicy`, `promotion`), `sources`, `projectRoot` (`null` outside a project).
|
|
3418
|
+
- JSON keys: `path`, `events`, `recordsCount`, `groupsCount`, `candidatesCount`, `candidates`, `report` (`schema`, `createdAt`, `reviewDecision`, `recordsCount`, `groups`, `candidates`, `promotionPolicy`, `promotion`, and `routeSwitches` when the store recorded any), `sources`, `projectRoot` (`null` outside a project). `routeSwitches` lists opted-in mid-attempt walks (`from`, `to`, `reason`, optional `effort`, `attemptId`, `stepId`). It is omitted when there are none.
|
|
3419
3419
|
- Each `sources` entry has `kind` (`engine`, `telemetry`, or `file`), `path`, `exists`, `records`, and `duplicatesDropped`; the `engine` entry also has `skippedInvalid`, `excludedSimulated`, and `undecided`.
|
|
3420
3420
|
- Each `report.groups` row has `workflowHash`, `workflowId` (Runtime records), `stepId`, `agentRole`, `promptHash`, `recurrence`, `distinctRuns`, `askRecurrence`, `undecidedRecords`, `meanCost`, `meanLatency`, `verifyPassRate` (accepted share of decided records), `rework`, `weightedRecurrence`, `undatedRecords`, `costSamples`, `writesRepository`, `evidenceRefs`, `isCandidate`, and, when they apply, `excludedReason`, `candidateKind`, and `candidateId`.
|
|
3421
3421
|
- Each `report.promotion` entry has `candidateId`, `policy`, `readyForReview`, and `reason`.
|
|
@@ -3481,9 +3481,9 @@ Without `--file` it reads the same sources as [`kxm improve report`](#kxm-improv
|
|
|
3481
3481
|
- `--equivalent-list-cost` loads the catalog without the freshness check the producers apply, so it prices with a catalog of any date, including one the producers treat as stale. Check the catalog `date` before you rely on `ListEquiv($)`.
|
|
3482
3482
|
- A Runtime store that exists but cannot be read exits 1 with `improve_source_unreadable`.
|
|
3483
3483
|
- Ranking: quality first (Pass%, then Rwk%), then cost per accepted attempt. Among routes of equal quality, any route with an unknown-cost attempt ranks after every route without one. Such a route's cost is unknown, not a partial sum: `$/Acc` prints `-` (JSON `costPerAcceptedUsd: null`) and the `*` in `Unk` marks it.
|
|
3484
|
-
- The `Quota` column counts attempts whose metadata looks quota-exhausted (a quota failure class, a `quota` flag, or text such as `rate limit` or `HTTP 429`). It is a count only
|
|
3484
|
+
- The `Quota` column counts attempts whose metadata looks quota-exhausted (a quota failure class, a `quota` flag, or text such as `rate limit` or `HTTP 429`). It is a count only. Quota is not an `onError` class, and the column does not choose a route. Walks a role opted into are listed under Route switches when the store has `routing.route_switched` events (`from`, `to`, `reason`, optional `effort`, `stepId`).
|
|
3485
3485
|
- The text output does not list the sources, and prints `no routing records in telemetry` when no source holds a record. The Rwk% column counts records with `transitions` greater than 0, which Runtime records never set.
|
|
3486
|
-
- JSON keys: `file` (the telemetry path, also when the Runtime store was read), `sources` (without `--file`; the same shape as in `kxm improve`), `configurations` (per behavioral hash for v1 records; `totalCostUsd` is `null` when any record lacks a cost, and `missingCostRuns` counts those records), `report` (`schema`, `generatedAt`, `totalAttempts`, `rows`).
|
|
3486
|
+
- JSON keys: `file` (the telemetry path, also when the Runtime store was read), `sources` (without `--file`; the same shape as in `kxm improve`), `configurations` (per behavioral hash for v1 records; `totalCostUsd` is `null` when any record lacks a cost, and `missingCostRuns` counts those records), `report` (`schema`, `generatedAt`, `totalAttempts`, `rows`, and `routeSwitches` when the store recorded any).
|
|
3487
3487
|
|
|
3488
3488
|
With no routing records yet:
|
|
3489
3489
|
|
|
@@ -422,7 +422,7 @@ bytes.
|
|
|
422
422
|
| `thinking` | String, 1 to 64 characters | Optional | Recorded on the route |
|
|
423
423
|
| `tags`, `capabilities` | Unique identifiers, at most 32 | Optional | Selector tags |
|
|
424
424
|
| `priority` | Integer, -10,000 to 10,000 | Optional | Recorded on the route |
|
|
425
|
-
| `fallbacks` | Up to 8 `profile`, `tag
|
|
425
|
+
| `fallbacks` | Up to 8 `profile`, `tag` (optional `capabilities`), or `provider`+`model` objects | Optional | The opt-in walk expands each roster entry one level |
|
|
426
426
|
| `limits.contextTokens`, `limits.outputTokens` | Integer, at least 1 | Optional | Recorded on the route |
|
|
427
427
|
| `limits.timeoutMs` | Integer, 0 to 31,536,000,000 | Optional | Recorded on the route |
|
|
428
428
|
|
|
@@ -917,9 +917,9 @@ global one with the same id.
|
|
|
917
917
|
| `extends` | Identifier of another role in the same project | Optional | Refused when the chain cycles |
|
|
918
918
|
| `roster[].effort` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max` | Optional | Must be inside the harness ceiling when set |
|
|
919
919
|
| `roster[].mode` | `headless`, `interactive`, or `either` | Optional | Recorded on the entry |
|
|
920
|
-
| `policy.fallback.onError` | Unique `rate_limit`, `transport`, `provider_unavailable` | Optional |
|
|
921
|
-
| `policy.fallback.maxSwitches` | Integer, at least 0 | Optional |
|
|
922
|
-
| `policy.fallback.revert` | `next_run` or `never` | Optional |
|
|
920
|
+
| `policy.fallback.onError` | Unique `rate_limit`, `transport`, `provider_unavailable`, `context_overflow` | Optional; empty or absent means no walk | The attempt runner, only for a listed class |
|
|
921
|
+
| `policy.fallback.maxSwitches` | Integer, at least 0 | Optional; 1 when `onError` is non-empty and this field is omitted | The attempt runner. `0` allows no switch |
|
|
922
|
+
| `policy.fallback.revert` | `next_run` or `never` | Optional; `next_run` | `next_run` starts the next run on the first entry. `never` keeps the route that succeeded for later steps in the same run |
|
|
923
923
|
| `skills`, `tools`, `produces`, `consumes` | See `schemas/role.schema.json` | Optional | `kxm role` |
|
|
924
924
|
| `policy.vendorIndependenceRequired`, `policy.maxTransitions`, `policy.requiresGateVerification` | Boolean, or a positive integer for `maxTransitions` | Optional | Recorded on the role |
|
|
925
925
|
|
|
@@ -929,6 +929,19 @@ from the agent's `role` roster and that route's `.kxm/models/<route-id>.yaml`,
|
|
|
929
929
|
never from the agent file. The developer assignment runner reads
|
|
930
930
|
`.kxm/roles/*.yaml` and `.kxm/models/*.yaml` at `refs/remotes/origin/main`.
|
|
931
931
|
|
|
932
|
+
When `policy.fallback.onError` lists a failure class, a failed attempt of that
|
|
933
|
+
class continues on the next admitted route before it settles. The chain is the
|
|
934
|
+
role roster (own entries, then `extends`), then one level of each route's
|
|
935
|
+
`fallbacks` selectors. Retired, disabled, and unhosted routes are skipped. A
|
|
936
|
+
live write step also requires `edit`, an audited writer profile, and a writer
|
|
937
|
+
roster binding. When `policy.vendorIndependenceRequired` is true, a later
|
|
938
|
+
route whose vendor matches `reviewer-arch` or `reviewer-cli` is skipped. The
|
|
939
|
+
engine appends `routing.route_switched` and logs `route_switch`. A bounded
|
|
940
|
+
redacted transcript from the failed attempt is appended to the next prompt and
|
|
941
|
+
is not stored on the event. Cancellation, policy refusal, authentication, an
|
|
942
|
+
unhosted model, a gate failure, tool policy, and admission errors never walk.
|
|
943
|
+
A role with an empty or absent `onError` list fails on the first route.
|
|
944
|
+
|
|
932
945
|
```yaml
|
|
933
946
|
schema: kxm.role.v2
|
|
934
947
|
id: writer
|
|
@@ -296,7 +296,13 @@ No product producer writes `metered` today. Subscription runs are `unmetered` be
|
|
|
296
296
|
|
|
297
297
|
`kxm routing report` groups records by harness, model, effort and role. It ranks routes by quality first (Pass%, then Rwk%), then by cost per accepted attempt. Among routes of equal quality, a route with any unknown-cost attempt ranks after every route without one, because its cost is unknown. Its `$/Acc` prints `-` instead of a partial sum, and the `*` in the `Unk` column marks it. Read `Unm` and `Unk` before you trust `$/Acc`.
|
|
298
298
|
|
|
299
|
-
The `Quota` column counts attempts whose metadata looks quota-exhausted.
|
|
299
|
+
The `Quota` column counts attempts whose metadata looks quota-exhausted. The column does not choose a route, and quota is not an `onError` class. The report has no provider column, so the `Harness` column is what tells you native from Pi.
|
|
300
|
+
|
|
301
|
+
### Mid-attempt fallback
|
|
302
|
+
|
|
303
|
+
A role opts in by listing classes on `policy.fallback.onError`: `rate_limit`, `transport`, `provider_unavailable`, and `context_overflow`. An empty or absent list fails the attempt on the first route. On a listed class the engine appends `routing.route_switched` (`from`, `to`, `reason`, and `effort` when the next entry or the failing attempt has one), logs `route_switch`, and invokes the producer again on the next admitted chain entry, at most `maxSwitches` times (default 1; explicit `0` walks nothing). The chain is roster order, then `extends`, then one level of each route's `fallbacks` selectors. A bounded redacted transcript is appended to the next prompt and is not written to the event log.
|
|
304
|
+
|
|
305
|
+
Cancellation, policy refusal, authentication, an unhosted model, a gate failure, tool policy, and admission errors never walk. `revert: next_run` (the default) starts the next run on the first entry. `revert: never` keeps the route that succeeded for later steps in the same run. `kxm routing report` and `kxm improve report` print a Route switches section when the event store has any. See [`.kxm/roles`](config-reference.md#kxmrolesroleyaml-kxmrolev2).
|
|
300
306
|
|
|
301
307
|
```bash
|
|
302
308
|
kxm routing report
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "kxm",
|
|
4
4
|
"displayName": "KXM",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.151",
|
|
6
6
|
"description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "KontextMind",
|