@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.
Files changed (53) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.kxm/workflows/default.yaml +2 -0
  3. package/CHANGELOG.md +46 -2
  4. package/docs/concepts/architecture.md +1 -1
  5. package/docs/concepts/data-and-storage.md +1 -1
  6. package/docs/contracts/routing.md +1 -1
  7. package/docs/contributing/test-matrix.md +6 -5
  8. package/docs/guides/peer-messaging.md +2 -2
  9. package/docs/operations/backup-and-restore.md +43 -24
  10. package/docs/operations/deploy.md +1 -1
  11. package/docs/reference/cli-reference.md +65 -28
  12. package/docs/reference/config-reference.md +24 -13
  13. package/docs/reference/harness-routing.md +3 -3
  14. package/docs/reference/http-api.md +2 -1
  15. package/docs/reference/tools.md +3 -3
  16. package/docs/start/first-workflow.md +4 -4
  17. package/docs/start/quickstart-claude-code.md +2 -2
  18. package/package.json +1 -1
  19. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  20. package/plugins/kxm/dist/claude-hook.js +4 -1
  21. package/plugins/kxm/dist/cli.js +407 -156
  22. package/plugins/kxm/dist/client.js +9 -0
  23. package/plugins/kxm/dist/core.js +9 -3
  24. package/plugins/kxm/dist/extension.js +13 -1
  25. package/plugins/kxm/dist/mcp-server.js +14 -2
  26. package/plugins/kxm/dist/runtime-supervisor.js +231 -48
  27. package/plugins/kxm/dist/runtime.js +415 -92
  28. package/plugins/kxm/dist/server.js +19 -1
  29. package/plugins/kxm/package.json +1 -1
  30. package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +4 -3
  31. package/plugins/kxm/skills/kxm-peer/SKILL.md +5 -3
  32. package/plugins/kxm/skills/kxm-project-setup/SKILL.md +3 -2
  33. package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +3 -0
  34. package/plugins/kxm/skills/kxm-runs/SKILL.md +8 -7
  35. package/plugins/kxm/src/cli/project.ts +22 -13
  36. package/plugins/kxm/src/cli/system.ts +22 -1
  37. package/plugins/kxm/src/cli.ts +14 -4
  38. package/plugins/kxm/src/client.ts +10 -0
  39. package/plugins/kxm/src/commands.ts +10 -1
  40. package/plugins/kxm/src/database.ts +210 -36
  41. package/plugins/kxm/src/engine.ts +117 -2
  42. package/plugins/kxm/src/extension.ts +1 -0
  43. package/plugins/kxm/src/harness.ts +29 -0
  44. package/plugins/kxm/src/hub.ts +12 -0
  45. package/plugins/kxm/src/init-guide-setup.ts +43 -28
  46. package/plugins/kxm/src/mcp-server.ts +1 -1
  47. package/plugins/kxm/src/oneshot-producer.ts +16 -8
  48. package/plugins/kxm/src/prices.ts +33 -2
  49. package/plugins/kxm/src/routing.ts +13 -7
  50. package/plugins/kxm/src/studio-layout.ts +5 -4
  51. package/plugins/kxm/src/template.ts +31 -0
  52. package/plugins/kxm/src/worktree-witness.ts +71 -0
  53. 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) exits 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.
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 for authenticated harnesses (suppress with `KXM_SKIP_GUIDE_SETUP_PROMPT=1`).
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. It accepts an allowlisted command name and answers `ok: true`, but executes nothing. Keep the default loopback `--host`.
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 sets `limits.maxAgentTimeMs`, which the Runtime does not enforce yet, so a run of it is created but `kxm runs drive` refuses it with `run_handoff_required`. A workflow written by `kxm workflow add <id> --template implement-and-verify` omits that limit.
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
- The `default` workflow from `kxm init` is handed off (see [`kxm run`](#kxm-run)):
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. From the CLI this always returns `{"messages":[]}`: the inbox lives in a long-running harness session, which a one-shot CLI call does not have. Use `kxm dash --screen inbox` to see pending 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. `$/Acc` still shows only the priced part, so a route mixing unmetered and unknown-cost attempts can read `$0.0000`; the `*` in `Unk` marks it.
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, with a hashed `kxm.backup-manifest.v1` manifest (Runtime stores under the user state root are not included). It discovers stores relative to the current directory: the hub store `.kxm/state/kxm.db`, and any `registry.db`, `bindings.db`, and `events/*.db` it finds under `.kxm/runtime/`. The Runtime writes its stores under the user state root instead, so a backup normally holds only the hub store and `manifest.json`. It ignores `--workspace` and `KXM_DATA_PATH`. To back up the Runtime, see [Backup and restore](../operations/backup-and-restore.md).
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
- - Exit 1 with `backup_failed`; `issues` carry codes such as `backup_no_stores` and `database_corrupted`.
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 1 store(s):
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
- In a project with a hub store:
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 1 store(s) to /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z (sources are not opened, so their WAL is not checkpointed)
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
- In a project without a hub store yet:
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, and each file's digest, then restores each store to its recorded source path (rebased onto the current directory when the manifest came from another project root).
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. Stop the hub and the Runtime before restoring.
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 1 store(s) from /work/bk/manifest.json; digests verified against the manifest
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 every harness with a fixed read-only argument set
344
- (`READ_ONLY_ONESHOT_ARGS` in `plugins/kxm/src/harness.ts`); it does not
345
- translate `tools` into harness flags. The Runtime refuses live steps that
346
- request `write` access until the writer sandbox is in place, so a step that
347
- writes a repository runs today only under the simulated producer.
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` and `implementer`; an interactive
455
- `kxm init` can add workflow-guide agents for authenticated harnesses; `kxm run`
456
- and the Runtime read them; `kxm trust` diffs them.
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 built-in template
676
- sets it, so the `default` workflow that `kxm init` writes cannot be driven
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 a copy of the hub database and `manifest.json` | `kxm backup` (without `--out`) |
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 only a lower bound. Its `$/Acc` still shows only what was priced, so a route that mixes unmetered and unknown-cost attempts can read `$0.0000`; the `*` in the `Unk` column marks it. Read `Unm` and `Unk` before you trust `$/Acc`.
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, but the code sends Google through `agy`: the guided setup in `kxm init` maps Google candidates to `agy`, and the Runtime's Pi one-shot cannot reach `antigravity/…` (section 4).
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 accepts an allowlisted command name but executes nothing. See [`kxm studio serve`](cli-reference.md#kxm-studio-serve).
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
 
@@ -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` (always empty from the CLI) |
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:** always returns an empty list. The extension turns each inbound request into a model turn instead.
166
- - **CLI:** always returns an empty list, because a one-shot command holds no inbox.
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 drive hands off any agent, panel, approval or wait step with `write` access; gate steps are exempt, and the read-only `spec-and-plan` template avoids the refusal.
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 not the `default` workflow
255
+ ### Why start with `first` and not `default`
256
256
 
257
- `kxm init` also writes a `default` workflow that plans, implements and runs the test gate. It declares `limits.maxAgentTimeMs`, an agent-time budget the Runtime cannot enforce yet. A drive of it is refused with HTTP 409 `run_handoff_required` (reason `limit_unsupported`), and the run stays `preparing` until you cancel it with `kxm runs cancel <run-id>`. [Steps the Runtime does not execute yet](../reference/config-reference.md#steps-the-runtime-does-not-execute-yet) lists every setting that causes a handoff.
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` | You drove the `default` workflow | Cancel the run and use `first` |
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 only. It does not find the Runtime's registry and run event stores under the user state root. Copy those while the Runtime is stopped, as [Back up everything else](../operations/backup-and-restore.md#back-up-everything-else) describes.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.97",
3
+ "version": "0.7.99",
4
4
  "description": "KXM local-first multi-agent orchestration and operator dashboard",
5
5
  "type": "module",
6
6
  "author": "KontextMind",
@@ -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.97",
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
  {