@kontextmind/kxm 0.7.97 → 0.7.99
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/.kxm/workflows/default.yaml +2 -0
- package/CHANGELOG.md +46 -2
- package/docs/concepts/architecture.md +1 -1
- package/docs/concepts/data-and-storage.md +1 -1
- package/docs/contracts/routing.md +1 -1
- package/docs/contributing/test-matrix.md +6 -5
- package/docs/guides/peer-messaging.md +2 -2
- package/docs/operations/backup-and-restore.md +43 -24
- package/docs/operations/deploy.md +1 -1
- package/docs/reference/cli-reference.md +65 -28
- package/docs/reference/config-reference.md +24 -13
- package/docs/reference/harness-routing.md +3 -3
- package/docs/reference/http-api.md +2 -1
- package/docs/reference/tools.md +3 -3
- package/docs/start/first-workflow.md +4 -4
- package/docs/start/quickstart-claude-code.md +2 -2
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/claude-hook.js +4 -1
- package/plugins/kxm/dist/cli.js +407 -156
- package/plugins/kxm/dist/client.js +9 -0
- package/plugins/kxm/dist/core.js +9 -3
- package/plugins/kxm/dist/extension.js +13 -1
- package/plugins/kxm/dist/mcp-server.js +14 -2
- package/plugins/kxm/dist/runtime-supervisor.js +231 -48
- package/plugins/kxm/dist/runtime.js +415 -92
- package/plugins/kxm/dist/server.js +19 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +4 -3
- package/plugins/kxm/skills/kxm-peer/SKILL.md +5 -3
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +3 -2
- package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +3 -0
- package/plugins/kxm/skills/kxm-runs/SKILL.md +8 -7
- package/plugins/kxm/src/cli/project.ts +22 -13
- package/plugins/kxm/src/cli/system.ts +22 -1
- package/plugins/kxm/src/cli.ts +14 -4
- package/plugins/kxm/src/client.ts +10 -0
- package/plugins/kxm/src/commands.ts +10 -1
- package/plugins/kxm/src/database.ts +210 -36
- package/plugins/kxm/src/engine.ts +117 -2
- package/plugins/kxm/src/extension.ts +1 -0
- package/plugins/kxm/src/harness.ts +29 -0
- package/plugins/kxm/src/hub.ts +12 -0
- package/plugins/kxm/src/init-guide-setup.ts +43 -28
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/oneshot-producer.ts +16 -8
- package/plugins/kxm/src/prices.ts +33 -2
- package/plugins/kxm/src/routing.ts +13 -7
- package/plugins/kxm/src/studio-layout.ts +5 -4
- package/plugins/kxm/src/template.ts +31 -0
- package/plugins/kxm/src/worktree-witness.ts +71 -0
- package/schemas/backup-manifest.schema.json +33 -0
|
@@ -15,7 +15,7 @@ Output shown under examples was captured from a source checkout, inside a throwa
|
|
|
15
15
|
- Hub and sessions: [`hub`](#kxm-hub-view), [`session`](#kxm-session), [`dash`](#kxm-dash), [`studio`](#kxm-studio)
|
|
16
16
|
- Harnesses, models, and roles: [`harness`](#kxm-harness), [`auth`](#kxm-auth), [`update`](#kxm-update), [`models`](#kxm-models), [`routes`](#kxm-routes), [`role`](#kxm-role)
|
|
17
17
|
- Running work: [`run`](#kxm-run), [`runs`](#kxm-runs), [`runtime`](#kxm-runtime), [`agent`](#kxm-agent), [`workflow`](#kxm-workflow), [`gate`](#kxm-gate), [`peer`](#kxm-peer), [`task`](#kxm-task), [`goal`](#kxm-goal), [`suggest`](#kxm-suggest), [`explain`](#kxm-explain)
|
|
18
|
-
- Context and learning: [`context`](#kxm-context), [`memory`](#kxm-memory), [`skills`](#kxm-skills), [`improve`](#kxm-improve), [`routing`](#kxm-routing)
|
|
18
|
+
- Context and learning: [`context`](#kxm-context), [`memory`](#kxm-memory), [`skills`](#kxm-skills), [`improve`](#kxm-improve), [`routing`](#kxm-routing), [`prices`](#kxm-prices)
|
|
19
19
|
- Operations: [`backup`](#kxm-backup), [`restore`](#kxm-restore), [`tenant`](#kxm-tenant), [`ssh`](#kxm-ssh), [`help`](#kxm-help)
|
|
20
20
|
- [Known behavior gaps](#known-behavior-gaps)
|
|
21
21
|
|
|
@@ -102,7 +102,7 @@ kxm -V
|
|
|
102
102
|
- Plan with `planned`: `backup`, `restore`, `config set`, `role add|remove|modify|set-host|resume`, `workflow add|remove|modify`, `goal create`, `task create|run|sync`, `memory note|sync`, `skills evaluate|promote|reject`, `context promote`, `context wiki-compile --out`, `auth token`, `session token`, `session brief`, and `ssh run|file|close`. Each prints its normal result plus `dryRun: true` and `planned`, a list of `{action, target}` entries whose `action` is `write`, `delete`, `move`, `request`, or `ssh`. Text mode prints `dry run: <summary>` and one indented `would <action> <target>` line per entry (`session brief` appends `dry run: would write <file>` lines to the brief instead).
|
|
103
103
|
- Plan in their own shape (described in each section): `init`, `run`, `runs drive|cancel`, `runtime start|stop|sync-retry`, `hub start|stop|bind|unbind`, `session start|stop`, `agent worker`, `dash`, `studio serve`, `models inventory-refresh`, `routes admit|disable`, `update`, `completion install`, `workflow start|signal|export|checkpoint|record|wait`, every `peer` subcommand, `gate degrade|signal`, `skills create`, and `improve report`. `gate github watch --dry-run` still polls GitHub but does not post the signal.
|
|
104
104
|
- Read-only commands run as usual, without leaving a trace: a local SQLite store is opened without creating `-wal` or `-shm` files, and `runs status|list|receipt` only attach to a running Runtime supervisor. With no supervisor running they exit 2 with `dry_run_unsupported` instead of starting one. `context wiki-compile --dry-run` still asks the hub to compile, which is a read.
|
|
105
|
-
- Refused: `kxm models` (the interactive screen)
|
|
105
|
+
- Refused: `kxm models` (the interactive screen) and `kxm prices acknowledge` exit 2 with `dry_run_unsupported`. The CLI keeps one list of the commands that answer `--dry-run` and refuses every other command the same way before it runs, so a command added without dry-run support fails closed.
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
108
|
kxm config set user.theme light --dry-run
|
|
@@ -161,7 +161,7 @@ Exit 2 covers an unknown command or option, a missing argument or required optio
|
|
|
161
161
|
| Message peers | [`kxm peer list`](#kxm-peer-list), [`kxm peer send`](#kxm-peer-send), [`kxm peer await`](#kxm-peer-await), [`kxm peer fanout`](#kxm-peer-fanout) |
|
|
162
162
|
| Operate gates and evidence | [`kxm gate validate`](#kxm-gate-validate), [`kxm gate artifacts-exist`](#kxm-gate-artifacts-exist), [`kxm gate signal`](#kxm-gate-signal), [`kxm workflow checkpoint`](#kxm-workflow-checkpoint) |
|
|
163
163
|
| Query context and memory | [`kxm context get`](#kxm-context-get), [`kxm context recall`](#kxm-context-recall), [`kxm memory brief`](#kxm-memory-brief), [`kxm memory note`](#kxm-memory-note) |
|
|
164
|
-
| Read improvement and routing reports | [`kxm improve report`](#kxm-improve-report), [`kxm routing report`](#kxm-routing-report) |
|
|
164
|
+
| Read improvement and routing reports | [`kxm improve report`](#kxm-improve-report), [`kxm routing report`](#kxm-routing-report), [`kxm prices acknowledge`](#kxm-prices-acknowledge) |
|
|
165
165
|
| Back up and restore | [`kxm backup`](#kxm-backup), [`kxm restore`](#kxm-restore) |
|
|
166
166
|
| Update KXM and harnesses | [`kxm update --check`](#kxm-update), [`kxm update --kxm`](#kxm-update) |
|
|
167
167
|
|
|
@@ -183,7 +183,7 @@ Creates, validates, repairs, resumes, or joins a KXM project at the Git root tha
|
|
|
183
183
|
- `--project-id` must match `prj_` followed by 6 to 128 letters, digits, `_`, or `-`. `--repository` is repeatable; each value must be `<id>=<absolute path>`, and a repeated ID fails with `repository_binding_argument_duplicate`.
|
|
184
184
|
- Needs a Git repository. Does not need a hub or the Runtime.
|
|
185
185
|
- Writes `.kxm/project.yaml`, `.kxm/agents/coordinator.yaml`, `.kxm/agents/implementer.yaml`, `.kxm/gates.yaml`, `.kxm/repo/repo.yaml`, `.kxm/workflows/default.yaml`, and `.kxm/template-provenance.yaml`, using a `.kxm-init-transaction` directory at the Git root while a create or repair is in flight. Repository bindings are written under the user state root, never into Git. `--dry-run` writes nothing.
|
|
186
|
-
- On an interactive terminal without `--json` or `--dry-run`, a successful create or join offers to install shell completion (suppress with `KXM_SKIP_COMPLETION_PROMPT=1`) and to write workflow-guide agents
|
|
186
|
+
- On an interactive terminal without `--json` or `--dry-run`, a successful create or join offers to install shell completion (suppress with `KXM_SKIP_COMPLETION_PROMPT=1`) and to write workflow-guide agents (suppress with `KXM_SKIP_GUIDE_SETUP_PROMPT=1`). Guided setup keeps a role only when one of its guide candidates is on a fixed map of reviewed harness/model pairs and that harness is authenticated; it writes the agent and workflow files, appends those selectors to `.kxm/routes.yaml`, and skips every other candidate. Google candidates map to the Pi `antigravity` provider, which the Runtime's Pi one-shot cannot reach yet (see [Harness routing](harness-routing.md#google-through-the-antigravity-pi-provider)).
|
|
187
187
|
- JSON keys: `action` (`planned`, `created`, `joined`, `repaired`, `resumed`, or `validated`), `mode`, `inspectedFrom`, `projectRoot`, `changesRequired`, `legacyInputs`, `issues`, `configRevision`, `files`, `plannedOnly`, and, when relevant, `localBindingFile`, `bindingsChanged`, `repairPlan`, `resumePending`, `transactionKind`.
|
|
188
188
|
- Exit 0 for every completed action and every dry-run plan. Exit 1 when the result is planning-only (legacy state, blocked repair, partial state without provenance) or for `initialization_failed` (with `issues`) and `initialization_io_failed`. A planning-only text result prints the reason and then one `<file>: <code>: <message>` line per validation issue, for example `.kxm/workflows/first.yaml: gate_outcome_impossible: ...`.
|
|
189
189
|
|
|
@@ -846,7 +846,7 @@ kxm studio serve [-p <port>] [--host <host>] [--token <token>]
|
|
|
846
846
|
Serves the Web Studio on `http://127.0.0.1:4242` until interrupted. It serves `/`, `/health`, `GET /api/layout`, and `POST /api/mutate`. The plan comes from `.kxm/workflows/default.yaml` in the current directory, or the first YAML file in `.kxm/workflows/`.
|
|
847
847
|
|
|
848
848
|
> [!WARNING]
|
|
849
|
-
> Every response carries `Access-Control-Allow-Origin: *`, so any web page open in a browser on this machine can read `/api/layout` (your workflow plan). `POST /api/mutate` requires `Authorization: Bearer <session token>` only when a session token resolves (`--token`, `KXM_SESSION_TOKEN`, or the on-disk token); with none, it accepts any caller.
|
|
849
|
+
> Every response carries `Access-Control-Allow-Origin: *`, so any web page open in a browser on this machine can read `/api/layout` (your workflow plan). `POST /api/mutate` requires `Authorization: Bearer <session token>` only when a session token resolves (`--token`, `KXM_SESSION_TOKEN`, or the on-disk token); with none, it accepts any caller. An allowlisted command name gets HTTP 501 with `ok: false`, `executed: false`, `mappedToCli: false` and `error: "mutation_handler_missing"`, because `kxm studio serve` wires no mutation handler; it executes nothing. Keep the default loopback `--host`.
|
|
850
850
|
|
|
851
851
|
| Option | Argument | Default | Description |
|
|
852
852
|
|---|---|---|---|
|
|
@@ -1388,7 +1388,7 @@ Create a KXM run (offline-first; `kxm runs drive <runId> --simulated` executes i
|
|
|
1388
1388
|
- Needs a KXM project. Starts and uses the Runtime; no hub needed. Honors `--dry-run`, which validates the project and prints the plan without starting the supervisor.
|
|
1389
1389
|
- JSON keys: `phase`, `idempotent`, `run` (`runId`, `homeRuntimeId`, `status`, `configRevision`), `supervisor` (`runtimeId`, `port`, `started`). Dry run: `projectRoot`, `workflowId`, `configRevision`. The JSON result does not carry the drive command.
|
|
1390
1390
|
- Errors: `workflow_required` (exit 2), `project_required`, `run_workflow_unknown`, `run_failed` with `issues` (any invalid file in the project fails the load, for example `gate_outcome_impossible`), `run_io_failed` (exit 1).
|
|
1391
|
-
- The `default` workflow that `kxm init` writes
|
|
1391
|
+
- The `default` workflow that `kxm init` writes does not set `limits.maxAgentTimeMs`, so it can be driven. A workflow that sets that limit is created, but `kxm runs drive` refuses it with `run_handoff_required` (`limit_unsupported`); projects from older `kxm init` templates carry it on `default`.
|
|
1392
1392
|
|
|
1393
1393
|
```bash
|
|
1394
1394
|
kxm run default "Fix the flaky login test" --dry-run
|
|
@@ -1458,7 +1458,7 @@ kxm runs status --dry-run refused: the Runtime supervisor is not running and --d
|
|
|
1458
1458
|
kxm runs drive <runId> [--simulated] [--wait] [--timeout-ms <n>]
|
|
1459
1459
|
```
|
|
1460
1460
|
|
|
1461
|
-
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`).
|
|
1461
|
+
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`; there is no fallback model). 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, when `.kxm/roster.yaml` exists, its route must be on the roster's writer lineup. Otherwise the drive hands the run off with `step_unsupported`. Around each live attempt the Runtime fingerprints the checkout with `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`).
|
|
1462
1462
|
|
|
1463
1463
|
| Option | Argument | Default | Description |
|
|
1464
1464
|
|---|---|---|---|
|
|
@@ -1480,7 +1480,7 @@ kxm runs drive run_0123456789abcdef0123456789abcdef --simulated --dry-run
|
|
|
1480
1480
|
drive plan: run run_0123456789abcdef0123456789abcdef in simulated mode (no events written)
|
|
1481
1481
|
```
|
|
1482
1482
|
|
|
1483
|
-
|
|
1483
|
+
A workflow that declares `limits.maxAgentTimeMs`, such as `default` in a project from an older `kxm init` template, is handed off (see [`kxm run`](#kxm-run)):
|
|
1484
1484
|
|
|
1485
1485
|
```bash
|
|
1486
1486
|
kxm runs drive run_a80e84c98f514299b82f0157f4537ea3 --simulated
|
|
@@ -2397,18 +2397,21 @@ kxm peer fanout --targets reviewer critic --content "Independent review of PR 42
|
|
|
2397
2397
|
kxm peer inbox
|
|
2398
2398
|
```
|
|
2399
2399
|
|
|
2400
|
-
List inbound peer requests
|
|
2400
|
+
List the inbound peer requests addressed to this agent that still need a reply, oldest first, read from the hub (`GET /v1/agents/<agentId>/inbox`). Only a stable `KXM_AGENT_NAME` has an inbox: a registered name that is offline keeps its agent ID, so a later call as the same name lists what peers queued for it with `peer send --allow-offline`. The default `cli-<pid>` is a new agent on every call, and its list is always empty. Answer each request with `peer reply` under the same name.
|
|
2401
2401
|
|
|
2402
2402
|
| Option | Argument | Default | Description |
|
|
2403
2403
|
|---|---|---|---|
|
|
2404
2404
|
| `--payload` | `<json>` | none | JSON payload |
|
|
2405
2405
|
|
|
2406
|
+
- Reads only. Listing acknowledges nothing, so a request stays `queued` for push delivery. Output key: `messages`, each a full message record (`id`, `fromName`, `content`, `status` `queued` or `delivered`, `expiresAt`).
|
|
2407
|
+
- The call registers the name while it runs, so it exits 1 (`command_failed`, `agent name already active in project`) when another session holds that name online.
|
|
2408
|
+
|
|
2406
2409
|
```bash
|
|
2407
|
-
kxm peer inbox --json
|
|
2410
|
+
KXM_AGENT_NAME=codex kxm peer inbox --json
|
|
2408
2411
|
```
|
|
2409
2412
|
|
|
2410
2413
|
```text
|
|
2411
|
-
{"schema":"kxm.cli-result.v1","messages":[]}
|
|
2414
|
+
{"schema":"kxm.cli-result.v1","messages":[{"id":"msg_1f0c…","project":"kxm","from":"agt_9d2e…","fromName":"reviewer","to":"agt_4b7a…","toName":"codex","content":"Review the retry loop in src/sync.ts","delivery":"followUp","hops":0,"maxHops":5,"seq":1,"createdAt":"2026-09-23T21:40:00.000Z","expiresAt":"2026-09-24T21:40:00.000Z","status":"queued"}]}
|
|
2412
2415
|
```
|
|
2413
2416
|
|
|
2414
2417
|
### `kxm peer reply`
|
|
@@ -3245,10 +3248,10 @@ Without `--file` it reads the same sources as [`kxm improve report`](#kxm-improv
|
|
|
3245
3248
|
- Reads only. A price catalog that cannot be loaded is skipped silently.
|
|
3246
3249
|
- `--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($)`.
|
|
3247
3250
|
- A Runtime store that exists but cannot be read exits 1 with `improve_source_unreadable`.
|
|
3248
|
-
- 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.
|
|
3251
|
+
- 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.
|
|
3249
3252
|
- 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: nothing fails over to another route.
|
|
3250
3253
|
- 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.
|
|
3251
|
-
- 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), `report` (`schema`, `generatedAt`, `totalAttempts`, `rows`).
|
|
3254
|
+
- 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`).
|
|
3252
3255
|
|
|
3253
3256
|
With no routing records yet:
|
|
3254
3257
|
|
|
@@ -3306,45 +3309,78 @@ claude fable 680 1200 450 $0.4
|
|
|
3306
3309
|
pi qwen3-coder-plus 560 1200 450 $0.12 passed
|
|
3307
3310
|
```
|
|
3308
3311
|
|
|
3312
|
+
## `kxm prices`
|
|
3313
|
+
|
|
3314
|
+
### `kxm prices acknowledge`
|
|
3315
|
+
|
|
3316
|
+
```text
|
|
3317
|
+
kxm prices acknowledge
|
|
3318
|
+
```
|
|
3319
|
+
|
|
3320
|
+
Stamps the existing `.kxm/prices.yaml` list as today's estimate. It rewrites the file with today's date and a new `sha256` over the same `models` rows, then reads it back and checks both. It does not fetch vendor rates or change any price. Cost estimates treat a catalog whose date is not today as stale and stay unknown, so run this only after you have checked the list against the vendors' current rates.
|
|
3321
|
+
|
|
3322
|
+
No command-specific options.
|
|
3323
|
+
|
|
3324
|
+
- Reads and rewrites `.kxm/prices.yaml` in the current directory. Needs no hub and no Runtime.
|
|
3325
|
+
- Refuses `--dry-run` with `dry_run_unsupported` (exit 2).
|
|
3326
|
+
- JSON keys: `date`, `sha256`, `note`.
|
|
3327
|
+
- Exit 1 with `prices_acknowledge_failed` and a `message`, for example `price catalog missing` when there is no `.kxm/prices.yaml`.
|
|
3328
|
+
|
|
3329
|
+
```bash
|
|
3330
|
+
kxm prices acknowledge
|
|
3331
|
+
```
|
|
3332
|
+
|
|
3333
|
+
```text
|
|
3334
|
+
price catalog stamped 2026-09-23 (list estimate only; vendor rates were not fetched)
|
|
3335
|
+
```
|
|
3336
|
+
|
|
3309
3337
|
## `kxm backup`
|
|
3310
3338
|
|
|
3311
3339
|
```text
|
|
3312
3340
|
kxm backup [--out <dir>]
|
|
3313
3341
|
```
|
|
3314
3342
|
|
|
3315
|
-
Creates a verified SQLite backup of the project hub store
|
|
3343
|
+
Creates a verified SQLite backup of the project hub store and the Runtime stores under the user state root, with a hashed `kxm.backup-manifest.v1` manifest. Relative to the current directory it discovers the hub store `.kxm/state/kxm.db`, and any `registry.db`, `bindings.db`, and `events/*.db` under `.kxm/runtime/`. Under the user state root (`KXM_STATE_HOME` or the platform default) it discovers `runtime/registry.db`, the `run-events.db` of every project under `runtime/projects/`, and each store's `run-events.db.run-prompts.json` prompt sidecar, which it copies as a plain file. Those Runtime stores belong to every project on the machine, not only this one. It ignores `--workspace` and `KXM_DATA_PATH`. Bindings, `update.yaml` and the other state roots are not included; see [Backup and restore](../operations/backup-and-restore.md).
|
|
3316
3344
|
|
|
3317
3345
|
| Option | Argument | Default | Description |
|
|
3318
3346
|
|---|---|---|---|
|
|
3319
3347
|
| `--out` | `<dir>` | `.kxm/backups/backup-<timestamp>` | Directory to write backup and manifest |
|
|
3320
3348
|
|
|
3321
|
-
- Writes a copy of each store and `manifest.json`. `--dry-run` lists the stores it found and the files it would write without opening any store, so no WAL is checkpointed (JSON: `outDir`, `stores` with `storeId`, `sourcePath`, `backupFile`, plus `dryRun` and `planned`).
|
|
3322
|
-
- JSON keys: `backupId`, `outDir`, `manifest` (`schema`, `backupId`, `createdAt`, `projectRoot`, `stores` with `storeId`, `sourcePath`, `backupFile`, `schemaVersion`, `sha256`, `bytes`, `integrity`; `manifestSha256`).
|
|
3323
|
-
-
|
|
3349
|
+
- Writes a copy of each store and sidecar and `manifest.json`. `--dry-run` lists the stores and files it found and the files it would write without opening any store, so no WAL is checkpointed (JSON: `outDir`, `stores` with `storeId`, `sourcePath`, `backupFile`, `files` with `id`, `sourcePath`, `backupFile`, plus `dryRun` and `planned`).
|
|
3350
|
+
- JSON keys: `ok`, `backupId`, `outDir`, `manifest` (`schema`, `backupId`, `createdAt`, `projectRoot`, `stores` with `storeId`, `sourcePath`, `backupFile`, `schemaVersion`, `sha256`, `bytes`, `integrity`; `files` with `id`, `sourcePath`, `backupFile`, `sha256`, `bytes`; `complete`; `omitted`; `manifestSha256`).
|
|
3351
|
+
- A store or sidecar that cannot be copied, or that appears while the backup runs, is listed in `omitted` and the manifest records `complete: false`. The command then prints `Backup is incomplete (<n> omitted); not ok:`, sets `ok: false`, and exits 1; `kxm restore` refuses that manifest.
|
|
3352
|
+
- Exit 1 with `backup_failed`; `issues` carry codes such as `backup_no_stores` (no store found, or none could be copied) and `database_corrupted`.
|
|
3324
3353
|
|
|
3325
3354
|
```bash
|
|
3326
3355
|
kxm backup --out ../bk
|
|
3327
3356
|
```
|
|
3328
3357
|
|
|
3329
3358
|
```text
|
|
3330
|
-
Created SQLite backup with
|
|
3359
|
+
Created SQLite backup with 3 store(s):
|
|
3331
3360
|
- hub-store: /work/proj/.kxm/state/kxm.db -> kxm.db (schema v5, 110592 bytes, sha256 sha256:56c6d...)
|
|
3361
|
+
- registry: /home/me/.local/state/kxm/runtime/registry.db -> registry.db (schema v1, 20480 bytes, sha256 sha256:a5bde...)
|
|
3362
|
+
- events:38ed26cb8eeaa297f3b0b452: /home/me/.local/state/kxm/runtime/projects/38ed26cb8eeaa297f3b0b452/run-events.db -> run-events.db (schema v7, 348160 bytes, sha256 sha256:27c13...)
|
|
3332
3363
|
Manifest: /work/bk/manifest.json
|
|
3333
3364
|
```
|
|
3334
3365
|
|
|
3335
|
-
|
|
3366
|
+
The summary lists stores; the prompt sidecar appears under `files` in the manifest.
|
|
3367
|
+
|
|
3368
|
+
In a project with a hub store and one Runtime project:
|
|
3336
3369
|
|
|
3337
3370
|
```bash
|
|
3338
3371
|
kxm backup --dry-run
|
|
3339
3372
|
```
|
|
3340
3373
|
|
|
3341
3374
|
```text
|
|
3342
|
-
dry run: back up
|
|
3375
|
+
dry run: back up 3 store(s) and 1 file(s) to /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z (sources are not opened, so their WAL is not checkpointed)
|
|
3343
3376
|
would write /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z/kxm.db
|
|
3377
|
+
would write /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z/registry.db
|
|
3378
|
+
would write /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z/run-events.db
|
|
3379
|
+
would write /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z/run-events.db.run-prompts.json
|
|
3344
3380
|
would write /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z/manifest.json
|
|
3345
3381
|
```
|
|
3346
3382
|
|
|
3347
|
-
|
|
3383
|
+
On a machine with no hub store and no Runtime stores yet:
|
|
3348
3384
|
|
|
3349
3385
|
```bash
|
|
3350
3386
|
kxm backup --json
|
|
@@ -3360,14 +3396,14 @@ kxm backup --json
|
|
|
3360
3396
|
kxm restore <manifest>
|
|
3361
3397
|
```
|
|
3362
3398
|
|
|
3363
|
-
Restores SQLite stores from a verified backup manifest. It checks the manifest schema, that every backup file is present
|
|
3399
|
+
Restores SQLite stores and prompt sidecars from a verified backup manifest. It checks the manifest schema, refuses a manifest that records `complete: false` (`restore_incomplete`), checks that every backup file is present and each file's digest, then restores each store to its recorded source path, then each sidecar. A path under the manifest's project root is rebased onto the current directory when the manifest came from another project root; Runtime stores under the user state root go back to their recorded absolute paths. A manifest without a `complete` field, from an older build, still restores.
|
|
3364
3400
|
|
|
3365
3401
|
- Arguments: `<manifest>`, path to `manifest.json`.
|
|
3366
3402
|
- No command-specific options.
|
|
3367
|
-
- Overwrites live stores
|
|
3368
|
-
- Before overwriting anything, a restore checks every store's recorded schema version against the ceiling for that store, so a store newer than this build is refused (`runtime_schema_newer`) before the first file is replaced. `--dry-run` runs the same manifest, file, digest, and schema checks and plans each target it would overwrite (and any `-wal` or `-shm` sidecar it would delete) without touching them. Dry-run JSON keys: `backupId`, `manifestPath`, `stores` (`storeId`, `targetPath`, `schemaVersion`), `dryRun`, `planned`.
|
|
3403
|
+
- Overwrites live stores, including the Runtime stores of every project the backup holds; it does not check whether the hub or the Runtime is running. Stop both before restoring.
|
|
3404
|
+
- Before overwriting anything, a restore checks every store's recorded schema version against the ceiling for that store, so a store newer than this build is refused (`runtime_schema_newer`) before the first file is replaced. `--dry-run` runs the same manifest, file, digest, and schema checks and plans each target it would overwrite (and any `-wal` or `-shm` sidecar it would delete) without touching them. Dry-run JSON keys: `backupId`, `manifestPath`, `stores` (`storeId`, `targetPath`, `schemaVersion`), `files` (`id`, `targetPath`), `dryRun`, `planned`.
|
|
3369
3405
|
- JSON keys: `backupId`, `manifestPath`, `restoredStores` (`storeId`, `sourcePath`, `backupFile`, `schemaVersion`, `integrity`).
|
|
3370
|
-
- Exit 1 with `restore_failed`; `issues` carry codes such as `runtime_path_invalid`, `restore_manifest_invalid`, `restore_file_missing`, `restore_manifest_digest_mismatch`, and `runtime_schema_newer`.
|
|
3406
|
+
- Exit 1 with `restore_failed`; `issues` carry codes such as `runtime_path_invalid`, `restore_manifest_invalid`, `restore_incomplete`, `restore_file_missing`, `restore_manifest_digest_mismatch`, and `runtime_schema_newer`.
|
|
3371
3407
|
- Two more checks run per store while restoring, after the plan checks: a backup file whose schema version differs from the version the manifest records is refused with `runtime_schema_mismatch`, and one that fails its SQLite integrity check with `database_corrupted`. In a multi-store restore, stores restored before the refused one stay restored.
|
|
3372
3408
|
|
|
3373
3409
|
```bash
|
|
@@ -3375,8 +3411,11 @@ kxm restore ../bk/manifest.json --dry-run
|
|
|
3375
3411
|
```
|
|
3376
3412
|
|
|
3377
3413
|
```text
|
|
3378
|
-
dry run: restore
|
|
3414
|
+
dry run: restore 3 store(s) and 1 file(s) from /work/bk/manifest.json; digests verified against the manifest
|
|
3379
3415
|
would write /work/proj/.kxm/state/kxm.db
|
|
3416
|
+
would write /home/me/.local/state/kxm/runtime/registry.db
|
|
3417
|
+
would write /home/me/.local/state/kxm/runtime/projects/38ed26cb8eeaa297f3b0b452/run-events.db
|
|
3418
|
+
would write /home/me/.local/state/kxm/runtime/projects/38ed26cb8eeaa297f3b0b452/run-events.db.run-prompts.json
|
|
3380
3419
|
```
|
|
3381
3420
|
|
|
3382
3421
|
A missing manifest:
|
|
@@ -3552,10 +3591,8 @@ Inspect KXM runs
|
|
|
3552
3591
|
|
|
3553
3592
|
These are behaviors of the current build that differ from what the help text or the flag names suggest. Each is also noted in the command's section.
|
|
3554
3593
|
|
|
3555
|
-
- The `default` workflow that `kxm init` writes sets `limits.maxAgentTimeMs`, so `kxm runs drive` hands every run of it off with `run_handoff_required` (`limit_unsupported`). Use a `kxm workflow add --template` workflow, or remove the limit, to drive a first run.
|
|
3556
3594
|
- `kxm routing benchmark` prints constant placeholder figures.
|
|
3557
3595
|
- `kxm task sync` does not contact GitHub or Jira.
|
|
3558
|
-
- `kxm peer inbox` always returns an empty list from the CLI.
|
|
3559
3596
|
- `kxm context` subcommands crash with a stack trace when the hub is unreachable, and they ignore the persisted hub credential.
|
|
3560
3597
|
- `kxm completion <shell>` generates a command list that includes a nonexistent `plan` command, omits `models`, `routes`, `explain`, and `ssh`, lists a nonexistent `goal get`, and omits `runs drive`, `runs receipt`, `runtime sync-retry`, and `improve report`.
|
|
3561
3598
|
- `kxm backup` JSON shows `manifestSha256` redacted.
|
|
@@ -340,11 +340,15 @@ reference. Schema: `schemas/agent.schema.json`; semantic checks in
|
|
|
340
340
|
| `session.maxIdleMs` | Integer, 0 to 31,536,000,000 | Optional | Not read by any code path yet |
|
|
341
341
|
|
|
342
342
|
Tool presets are names checked against a registered list. The live one-shot
|
|
343
|
-
producer launches
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
343
|
+
producer launches each harness with a fixed argument set and does not
|
|
344
|
+
translate `tools` into harness flags. A read-only step uses the read-only set
|
|
345
|
+
(`READ_ONLY_ONESHOT_ARGS` in `plugins/kxm/src/harness.ts`). A step with `write`
|
|
346
|
+
access uses the audited writer set (`WRITER_ONESHOT_ARGS`), which exists only
|
|
347
|
+
for `pi` (`-a` with extensions, skills, prompt templates and sessions off) and
|
|
348
|
+
`grok` (`--always-approve` with subagents and web search off). Both approve
|
|
349
|
+
every tool call, shell commands included, and neither confines the process to
|
|
350
|
+
the checkout. A live write step on any other harness is handed off; see
|
|
351
|
+
[Steps the Runtime does not execute yet](#steps-the-runtime-does-not-execute-yet).
|
|
348
352
|
|
|
349
353
|
### Model selectors
|
|
350
354
|
|
|
@@ -451,9 +455,11 @@ Error codes: `executor_unknown`, `harness_unknown`, `tool_preset_unknown`,
|
|
|
451
455
|
[Rules shared by the project bundle](#rules-shared-by-the-project-bundle), and
|
|
452
456
|
`role_roster_conflicts_with_agent` (see [Roles](#kxmrolesroleyaml-kxmrolev1)).
|
|
453
457
|
|
|
454
|
-
Commands: `kxm init` creates `coordinator`
|
|
455
|
-
`
|
|
456
|
-
|
|
458
|
+
Commands: `kxm init` creates `coordinator` (`claude`, `anthropic/fable`) and
|
|
459
|
+
`implementer` (`grok`, `xai/grok-4.6`) and admits both selectors in
|
|
460
|
+
`.kxm/routes.yaml`; an interactive `kxm init` can add workflow-guide agents for
|
|
461
|
+
reviewed harness/model pairs whose harness is authenticated, and admits their
|
|
462
|
+
selectors too; `kxm run` and the Runtime read them; `kxm trust` diffs them.
|
|
457
463
|
|
|
458
464
|
## `.kxm/models/<id>.yaml` (`kxm.model.v1`)
|
|
459
465
|
|
|
@@ -672,16 +678,21 @@ these, the run is handed off (`step_unsupported`, `gate_unsupported`, or
|
|
|
672
678
|
`limit_unsupported`) instead of executing, and `kxm runs drive` reports
|
|
673
679
|
`run_handoff_required`:
|
|
674
680
|
|
|
675
|
-
- `limits.maxAgentTimeMs` in the workflow or project. The
|
|
676
|
-
|
|
677
|
-
as generated.
|
|
681
|
+
- `limits.maxAgentTimeMs` in the workflow or project. The current `kxm init`
|
|
682
|
+
template leaves it out; older templates set it on `default`.
|
|
678
683
|
- `tools`, `secrets`, or `safeSpeculation: true` on any step.
|
|
679
684
|
- `join.strategy` other than `all` or `all-settled`, `join.minimumPassed` with
|
|
680
685
|
`all`, and `join.cancelRemaining`.
|
|
681
686
|
- `assignments.maxAttemptsPerAssignment` above 2,
|
|
682
687
|
`assignments.maxWriteRepositories` above 1, and `distinctBy` other than
|
|
683
688
|
`provider`.
|
|
684
|
-
- A live (non-simulated) step with `write` access to any repository
|
|
689
|
+
- A live (non-simulated) step with `write` access to any repository when its
|
|
690
|
+
agent's harness has no audited writer profile (only `pi` and `grok` have
|
|
691
|
+
one), when `assignments.maximum` is above 1, when the project's
|
|
692
|
+
`limits.maxConcurrentRuns` is above 1, or when `.kxm/roster.yaml` exists and
|
|
693
|
+
is not a `kxm.developer-roster.v1` whose writer lineup admits that harness
|
|
694
|
+
and model with `edit` permission. The checkout witness can attribute a
|
|
695
|
+
change only to one writer at a time.
|
|
685
696
|
- Gate steps with `assignments.allowedAgents`, any assignment count or
|
|
686
697
|
`maxAttemptsPerAssignment` other than 1, `distinctBy`,
|
|
687
698
|
`maxWriteRepositories`, a join other than plain `all`, a `model`, no
|
|
@@ -1716,7 +1727,7 @@ Everything under `.kxm/` at the project root falls into one of three groups.
|
|
|
1716
1727
|
| `logs/` | Ignored runtime logs | The hub and workers |
|
|
1717
1728
|
| `state/` | Ignored restart state: the hub database `kxm.db`, Pi sessions, worker manifests | The hub and workers |
|
|
1718
1729
|
| `run/` | Ignored sockets (`run/ssh-sockets/`) | `kxm ssh` |
|
|
1719
|
-
| `backups/` | Ignored; each `backup-<time>/` holds
|
|
1730
|
+
| `backups/` | Ignored; each `backup-<time>/` holds copies of the hub database, the Runtime stores and their prompt sidecars, and `manifest.json` | `kxm backup` (without `--out`) |
|
|
1720
1731
|
| `config/` | Legacy: its JSON files make the project unloadable | Nothing current |
|
|
1721
1732
|
| `.kxm-init-transaction/` (sibling of `.kxm/` at the Git root) | Ignored; interrupted `kxm init` state | `kxm init` |
|
|
1722
1733
|
|
|
@@ -278,7 +278,7 @@ No product producer writes `metered` today. Subscription runs are `unmetered` be
|
|
|
278
278
|
- The catalog `date` is today.
|
|
279
279
|
- The harness is `claude` and the token counts are complete. The Runtime runs every harness, Pi included, through the one-shot producer, which estimates only for `claude`. The package also ships a long-lived Pi producer that estimates for any provider, but nothing in the Runtime calls it today.
|
|
280
280
|
|
|
281
|
-
`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
|
|
281
|
+
`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`.
|
|
282
282
|
|
|
283
283
|
The `Quota` column counts attempts whose metadata looks quota-exhausted. Nothing fails over on it. The report has no provider column, so the `Harness` column is what tells you native from Pi.
|
|
284
284
|
|
|
@@ -407,7 +407,7 @@ The code today limits where that route can run:
|
|
|
407
407
|
- The KXM Pi extension registers the `antigravity` provider. The Runtime's Pi one-shot runs with `--no-extensions`, so it cannot reach `antigravity/…`.
|
|
408
408
|
- Only an interactive Pi with KXM loaded, or a long-lived Pi worker, can use it.
|
|
409
409
|
|
|
410
|
-
Admit an `antigravity/…` route only through a reviewed admission decision. Whether Google work should use `agy` or `antigravity` today is still an operator decision; see [Where the code is looser than the rules](#where-the-code-is-looser-than-the-rules).
|
|
410
|
+
Admit an `antigravity/…` route only through a reviewed admission decision. The guided setup in `kxm init` maps Google guide candidates to `antigravity/gemini-3.8-flash-high` on Pi and admits that selector, but a Runtime drive of such an agent still cannot reach the provider. Whether Google work should use `agy` or `antigravity` today is still an operator decision; see [Where the code is looser than the rules](#where-the-code-is-looser-than-the-rules).
|
|
411
411
|
|
|
412
412
|
### Claude bridge: experiment only
|
|
413
413
|
|
|
@@ -493,7 +493,7 @@ These are places where the code decides less than the [routing rules](#routing-r
|
|
|
493
493
|
- **Reseller ids without a vendor segment.** Pi also serves native vendors' models under a reseller's own provider id, for example `github-copilot/claude-…`, `amazon-bedrock/anthropic.…` or `azure-openai-responses/gpt-…`. The brake reads the provider and the vendor segment, not the model name, so it accepts these ids. Keep them out of `.kxm/routes.yaml`.
|
|
494
494
|
- **Open-weight models on a third-party plan.** A DeepSeek model billed through Alibaba's plan, such as `qwen-token-plan/deepseek-v4.1-flash`, passes the brake although DeepSeek is a braked vendor. The reverse also happens: an open-weight model filed under a native vendor's namespace, such as `groq/openai/gpt-oss-120b`, is refused. Whether a third-party plan bill counts as billing the vendor is not decided.
|
|
495
495
|
- **Selectors the brake cannot see.** A worker started without `--model` runs Pi's default model, and a bare model id lets Pi choose the provider. Neither names a vendor, so neither is checked. A model that a person selects inside an interactive Pi session is not checked either.
|
|
496
|
-
- **The Google route.** The rules name the `antigravity` Pi provider as Google's route,
|
|
496
|
+
- **The Google route.** The rules name the `antigravity` Pi provider as Google's route, and the guided setup in `kxm init` now writes Google roles on Pi with `antigravity/gemini-3.8-flash-high` and admits that selector. The Runtime's Pi one-shot runs with `--no-extensions`, so it cannot reach `antigravity/…` and a live drive of those roles fails at dispatch (section 4). A `google/gemini-…` selector still runs only through `agy`.
|
|
497
497
|
- **Two Pi provider allowlists.** `PI_ALLOWED_PROVIDERS` in `plugins/kxm/src/harness.ts` is exported but gates nothing; on the product path, the brake and admission in `.kxm/routes.yaml` decide. The developer helper keeps a different list of its own.
|
|
498
498
|
- **`limits.maxModelCost` cannot trip on a live run.** The engine counts only `metered` cost toward the cap, and no producer records `metered` today (section 2). The Runtime caps `unmetered` and `unknown` attempts at 100 per run instead; see [Cost basis and staleness](config-reference.md#cost-basis-and-staleness).
|
|
499
499
|
- **Config load checks harness/model pairs only for agents that declare `harness:` and select their model through a profile or tag.** An agent with a direct `{provider, model}` selector, or one that omits `harness:` and names `provider: xai`, passes `kxm init --dry-run` and fails only at dispatch.
|
|
@@ -49,6 +49,7 @@ Operations routes carry no message bodies. `kxm dash` and `kxm tenant status` us
|
|
|
49
49
|
| `POST` | `/v1/agents/register` | Project | Register or resume `name` in `project` with `purpose`, optional `model` and `host`. Returns the agent and a new `agentKey` (201 new, 200 resumed) |
|
|
50
50
|
| `GET` | `/v1/agents` | Agent | Agents in your project; `?includeOffline=true` adds registered offline agents |
|
|
51
51
|
| `POST` | `/v1/agents/<agentId>/heartbeat` | Agent | Renew your presence lease (clients send one every 10 seconds) |
|
|
52
|
+
| `GET` | `/v1/agents/<agentId>/inbox` | Agent | Your open inbound requests (`queued` or `delivered`), oldest first, as `{ "messages": [...] }`. Expires overdue requests first; acknowledges nothing and moves no delivery cursor |
|
|
52
53
|
| `DELETE` | `/v1/agents/<agentId>` | Agent | Mark yourself offline (204) |
|
|
53
54
|
|
|
54
55
|
Key errors: `duplicate_agent_name` (409, the name is online in the project), `invalid_agent_identity` (401). Presence (`online`, `stale`, `offline`) is computed from the hub's clock with a 30-second lease; agents never report their own presence.
|
|
@@ -191,7 +192,7 @@ A bad token is `runtime_auth_failed`; a missing parameter is `runtime_request_in
|
|
|
191
192
|
|
|
192
193
|
## Web Studio server
|
|
193
194
|
|
|
194
|
-
`kxm studio serve` runs a separate local server, on `127.0.0.1:4242` by default, with `/`, `/health`, `GET /api/layout` and `POST /api/mutate`. It answers every route with `Access-Control-Allow-Origin: *`, so any web page in a local browser can read the layout. The mutate route requires a bearer session token only when one resolves; with none it accepts any caller. It
|
|
195
|
+
`kxm studio serve` runs a separate local server, on `127.0.0.1:4242` by default, with `/`, `/health`, `GET /api/layout` and `POST /api/mutate`. It answers every route with `Access-Control-Allow-Origin: *`, so any web page in a local browser can read the layout. The mutate route requires a bearer session token only when one resolves; with none it accepts any caller. It answers an allowlisted command name with HTTP 501 and `error: "mutation_handler_missing"`, and executes nothing. See [`kxm studio serve`](cli-reference.md#kxm-studio-serve).
|
|
195
196
|
|
|
196
197
|
## Related
|
|
197
198
|
|
package/docs/reference/tools.md
CHANGED
|
@@ -24,7 +24,7 @@ flowchart LR
|
|
|
24
24
|
| `kxm_fanout` | Peers | Yes | `kxm peer fanout` |
|
|
25
25
|
| `kxm_await` | Peers | No | `kxm peer await` |
|
|
26
26
|
| `kxm_cancel` | Peers | Yes | `kxm peer cancel` |
|
|
27
|
-
| `kxm_inbox` | Peers | No | `kxm peer inbox` (
|
|
27
|
+
| `kxm_inbox` | Peers | No | `kxm peer inbox` (lists a named CLI agent's open requests; refused in Pi) |
|
|
28
28
|
| `kxm_reply` | Peers | Yes | `kxm peer reply` |
|
|
29
29
|
| `kxm_workflow_list` | Workflows | No | None; `kxm workflow list` reads the local database instead |
|
|
30
30
|
| `kxm_workflow_get` | Workflows | No | None; `kxm workflow get` reads the local database instead |
|
|
@@ -162,8 +162,8 @@ Returns the message record with `status: "cancelled"`. Cancelling an already can
|
|
|
162
162
|
Lists inbound requests that still need a reply. It takes no parameters.
|
|
163
163
|
|
|
164
164
|
- **Claude Code:** returns `{ "messages": [...] }` from the session's inbox, which fills from the hub's event stream while the session is registered. Before returning, it re-reads each request and drops those already answered, cancelled or expired. This is pull mode; see [Pushed channel mode and pull mode](../../plugins/kxm/README.md#pushed-channel-mode-and-pull-mode).
|
|
165
|
-
- **Pi:**
|
|
166
|
-
- **CLI:**
|
|
165
|
+
- **Pi:** refuses. The extension turns each inbound request into a model turn itself, and that turn's final response is the reply, so listing would offer requests its own queue is about to activate.
|
|
166
|
+
- **CLI:** `kxm peer inbox` reads the agent's open requests from the hub (`GET /v1/agents/<agentId>/inbox`), acknowledging nothing. Run it with a stable `KXM_AGENT_NAME` to see requests queued for that name while it was offline; the default `cli-<pid>` is a new agent on every call, so its list is empty.
|
|
167
167
|
|
|
168
168
|
### `kxm_reply`
|
|
169
169
|
|
|
@@ -250,11 +250,11 @@ The file is a `kxm.workflow.v1` definition. `coordinator` names the agent that o
|
|
|
250
250
|
| Cost | None | Model usage on your accounts |
|
|
251
251
|
|
|
252
252
|
> [!WARNING]
|
|
253
|
-
> Without `--simulated`, `kxm runs drive` calls live harnesses. An agent whose model is not an admitted route fails with `producer_route_not_admitted`. Read [Harness routing](../reference/harness-routing.md) before your first live drive. A live
|
|
253
|
+
> Without `--simulated`, `kxm runs drive` calls live harnesses. An agent whose model is not an admitted route fails with `producer_route_not_admitted`. Read [Harness routing](../reference/harness-routing.md) before your first live drive. A live step with `write` access runs only on a harness with an audited writer profile (`pi` or `grok`), as a single assignment, in a project whose `limits.maxConcurrentRuns` is 1, and, when `.kxm/roster.yaml` exists, only on a route in its writer lineup; any other live write step is handed off. A live write step settles `passed` only when the checkout changed, and a read-only step that changes the checkout settles `failed`. Gate steps are exempt. The read-only `spec-and-plan` template needs none of this.
|
|
254
254
|
|
|
255
|
-
### Why
|
|
255
|
+
### Why start with `first` and not `default`
|
|
256
256
|
|
|
257
|
-
`kxm init` also writes a `default` workflow
|
|
257
|
+
`kxm init` also writes a `default` workflow. Its coordinator plans on `claude` / `anthropic/fable`, its implementer writes the checkout on `grok` / `xai/grok-4.6`, and a `test` gate runs `npm test`; `kxm init` admits exactly those two models in `.kxm/routes.yaml`. You can drive it, but even a simulated drive runs `npm test` in your checkout, and a live drive spends both subscriptions and passes the implement step only when Grok changes the checkout. `first` calls no model and runs no command, so it is the safer first run. [Steps the Runtime does not execute yet](../reference/config-reference.md#steps-the-runtime-does-not-execute-yet) lists every setting that makes a drive hand the run off.
|
|
258
258
|
|
|
259
259
|
### Two kinds of runs
|
|
260
260
|
|
|
@@ -264,7 +264,7 @@ The file is a `kxm.workflow.v1` definition. `coordinator` names the agent that o
|
|
|
264
264
|
|
|
265
265
|
| Message or symptom | Cause | Fix |
|
|
266
266
|
|---|---|---|
|
|
267
|
-
| `run_handoff_required` naming `limits.maxAgentTimeMs` |
|
|
267
|
+
| `run_handoff_required` naming `limits.maxAgentTimeMs` | The workflow declares an agent-time budget, which the Runtime does not enforce; a project from an older `kxm init` template has one on `default` | Cancel the run, remove the limit or use `first` |
|
|
268
268
|
| `trust check failed: review every expansion above before merging` | The workflow is not committed | Review it, then commit it |
|
|
269
269
|
| `workflow <id> does not exist in this project` | The ID is not a local workflow | Use an ID from `kxm workflow definitions` marked `[local]` |
|
|
270
270
|
| `gate_outcome_impossible` from `kxm init` | A gate step routes failure on `failed` | Declare `implementation-failure` on the gate step |
|
|
@@ -320,7 +320,7 @@ Continue with [step 4](#4-bind-this-machine-and-check-the-hub) through [step 7](
|
|
|
320
320
|
|
|
321
321
|
### Before you update
|
|
322
322
|
|
|
323
|
-
From the directory the hub runs in, back up its database, then stop the hub and the Runtime:
|
|
323
|
+
From the directory the hub runs in, back up its database and the Runtime stores, then stop the hub and the Runtime:
|
|
324
324
|
|
|
325
325
|
```bash
|
|
326
326
|
kxm backup
|
|
@@ -331,7 +331,7 @@ kxm runtime stop
|
|
|
331
331
|
`kxm backup` writes a verified copy and a hashed manifest to `.kxm/backups/backup-<timestamp>/`.
|
|
332
332
|
|
|
333
333
|
> [!WARNING]
|
|
334
|
-
> `kxm backup` copies the hub store
|
|
334
|
+
> `kxm backup` copies the hub store and the Runtime's registry and run event stores, and those Runtime stores belong to every project on this machine. A later `kxm restore` rolls all of them back. It does not copy bindings, `update.yaml` or the other state roots; [Back up everything else](../operations/backup-and-restore.md#back-up-everything-else) covers those.
|
|
335
335
|
|
|
336
336
|
[Back up and restore KXM](../operations/backup-and-restore.md) and [Upgrade KXM](../operations/upgrade.md) cover restores and rollback.
|
|
337
337
|
|
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.99",
|
|
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",
|
|
@@ -9508,7 +9508,10 @@ var init_commands = __esm({
|
|
|
9508
9508
|
await reconcileInbox(client, context.inbox, context.notifiedInbox);
|
|
9509
9509
|
return { messages: [...context.inbox.values()] };
|
|
9510
9510
|
}
|
|
9511
|
-
return { messages:
|
|
9511
|
+
if (context?.hubInbox) return { messages: await client.listInbox() };
|
|
9512
|
+
throw new Error(
|
|
9513
|
+
"kxm_inbox is not available in this session: it activates each inbound request as a turn, and that turn's final response is the reply"
|
|
9514
|
+
);
|
|
9512
9515
|
}
|
|
9513
9516
|
},
|
|
9514
9517
|
{
|