@kontextmind/kxm 0.7.98 → 0.7.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +19 -0
- package/docs/contributing/test-matrix.md +2 -0
- package/docs/guides/peer-messaging.md +2 -2
- package/docs/reference/cli-reference.md +10 -7
- package/docs/reference/config-reference.md +4 -2
- package/docs/reference/http-api.md +1 -0
- package/docs/reference/tools.md +3 -3
- 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 +115 -57
- package/plugins/kxm/dist/client.js +9 -0
- package/plugins/kxm/dist/core.js +4 -1
- package/plugins/kxm/dist/extension.js +13 -1
- package/plugins/kxm/dist/mcp-server.js +14 -2
- package/plugins/kxm/dist/runtime-supervisor.js +19 -4
- package/plugins/kxm/dist/runtime.js +19 -4
- package/plugins/kxm/dist/server.js +12 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm-peer/SKILL.md +5 -3
- package/plugins/kxm/src/cli/workflows.ts +34 -9
- package/plugins/kxm/src/cli.ts +3 -1
- package/plugins/kxm/src/client.ts +10 -0
- package/plugins/kxm/src/commands.ts +10 -1
- package/plugins/kxm/src/extension.ts +1 -0
- package/plugins/kxm/src/hub.ts +12 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/project-config.ts +45 -3
package/CHANGELOG.md
CHANGED
|
@@ -319,6 +319,18 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
319
319
|
|
|
320
320
|
### Fixed
|
|
321
321
|
|
|
322
|
+
- **A local `kxm workflow add` writes only what the project loader accepts, where it reads
|
|
323
|
+
it.** Local scope needs a KXM project (`project_not_found` outside one, creating nothing)
|
|
324
|
+
and writes to the project root's `.kxm/workflows/` from any subdirectory. Before writing,
|
|
325
|
+
also under `--dry-run`, the project loader checks the project with the new document; if
|
|
326
|
+
it would not load, the command exits 2 with `workflow_invalid`, lists the issues and
|
|
327
|
+
writes nothing. A `--file` in the shape written through 0.7.92 is refused, and
|
|
328
|
+
`--overwrite` repairs a file left in that shape. See
|
|
329
|
+
`docs/reference/cli-reference.md#kxm-workflow-add`.
|
|
330
|
+
- **`kxm workflow add --pick <global-id>` copies the global definition.** In local scope,
|
|
331
|
+
picking a global definition wrote the one-step scaffold under its id and reported
|
|
332
|
+
success. It now writes the global definition's content, with `--description` replacing
|
|
333
|
+
its description, and the loader check refuses one the project cannot load.
|
|
322
334
|
- **Live `kxm runs drive` can author on an audited writer profile.** A write-repository
|
|
323
335
|
step on pi (`-a`, with extensions, skills, and the session off) or grok
|
|
324
336
|
(`--always-approve`, with subagents and web search off) runs against the checkout.
|
|
@@ -365,6 +377,13 @@ All notable user-facing changes are documented here. The project follows [Semant
|
|
|
365
377
|
- **Workflow prompts no longer point agents at `.kxm/config`**, a path KXM refuses.
|
|
366
378
|
- **`kxm gate signal` and `kxm workflow wait` inside a KXM project reach the hub for hub
|
|
367
379
|
runs.** They go to the local Runtime only for a run its store holds.
|
|
380
|
+
- **`kxm peer inbox` lists the requests waiting for a named CLI agent.** It returned
|
|
381
|
+
`{"messages":[]}` every time. The hub now serves `GET /v1/agents/:id/inbox`
|
|
382
|
+
(agent-authenticated, project-scoped): the caller's queued and delivered requests,
|
|
383
|
+
oldest first, acknowledging nothing. Run with a stable `KXM_AGENT_NAME` (for example
|
|
384
|
+
`codex`) to list requests peers queued for it while it was offline, then answer them
|
|
385
|
+
with `kxm peer reply`. The Pi extension's `kxm_inbox` tool now refuses instead of
|
|
386
|
+
returning an empty list, because Pi activates each inbound request as a turn itself.
|
|
368
387
|
|
|
369
388
|
- **The Claude plugin's SessionStart hook is one bundled, read-only, project-scoped
|
|
370
389
|
script.** The two shell hooks it replaces (`kxm session brief --status` and
|
|
@@ -61,6 +61,8 @@ to run one file is in [Develop KXM](development.md#run-one-file-or-one-test).
|
|
|
61
61
|
| Dispatch context: only committed, pinned memory and hash-verified promoted skills reach an agent; the rest is a `dispatch_context_*` gap | `engine.test.ts` ("dispatch context: agents receive only committed, pinned memory and verified skills; anything else is withheld with a gap and the step still completes") |
|
|
62
62
|
| `kxm run` prints the simulated drive command for the new run | `cli.test.ts` ("kxm run prints the simulated drive command for the created run") |
|
|
63
63
|
| `kxm workflow add --template` writes workflows that validate and plan; an impossible gate outcome is refused | `cli-experience.test.ts` ("workflow add templates validate and plan a run, and a gate outcome the step can never produce is refused") |
|
|
64
|
+
| `kxm workflow add` writes a local workflow only where the loader reads it and only if the project still loads; outside a project it refuses | `role-and-workflow-manager.test.ts` ("workflow add writes only what the project loader accepts, at the project root, and loadKxmProject still loads") |
|
|
65
|
+
| `kxm workflow add --pick <global-id>` copies the global definition into the project, not the scaffold, and the loader check refuses one that does not fit | `role-and-workflow-manager.test.ts` ("workflow add --pick <global-id> copies that global definition into the project, and refuses one the project loader rejects") |
|
|
64
66
|
| `default.yaml` and the 13-step `fix.yaml` compile deterministically; back edges need budgets | `engine-compile.test.ts` |
|
|
65
67
|
| Artifact gate: non-empty regular files pass; missing, empty, non-file and escaping paths fail | `artifacts-exist.test.ts` |
|
|
66
68
|
| Vision gate: strict verdicts, admitted routes only, unreadable images fail closed | `vision-gate.test.ts` |
|
|
@@ -210,7 +210,7 @@ CLI (run with the recipient's `KXM_AGENT_NAME`):
|
|
|
210
210
|
kxm peer reply msg_779f5e0f22e04ac1af6078589a874971 "The plan is sound. Add a test for a zero discount."
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
-
Only the recipient can reply, and only once. From the CLI, `kxm peer inbox`
|
|
213
|
+
Only the recipient can reply, and only once. From the CLI, `kxm peer inbox` lists the requests still waiting for the agent named by `KXM_AGENT_NAME`, including ones queued while it was offline, without acknowledging them. The default `cli-<pid>` name is a new agent on every call, so its list is empty.
|
|
214
214
|
|
|
215
215
|
## Choose a delivery mode
|
|
216
216
|
|
|
@@ -291,7 +291,7 @@ Errors about `workflowContext` are covered in [Peer provenance and quorum gates]
|
|
|
291
291
|
| A request stays `delivered` | The recipient's turn, tool, or provider call is still running, or a Claude Code session restarted after acknowledging it. | Wait, or cancel and send it again with a new idempotency key. |
|
|
292
292
|
| `kxm_fanout` returns `pending` | The local wait ended before a reply. | Use the returned message IDs with `kxm_get`, or repeat the exact call. |
|
|
293
293
|
| Claude Code never sees requests | Channel mode is off or blocked by policy. | Use `kxm_inbox` and `kxm_reply`. |
|
|
294
|
-
| `kxm peer inbox` is always empty |
|
|
294
|
+
| `kxm peer inbox` is always empty | `KXM_AGENT_NAME` is unset, so each call registers a new `cli-<pid>` agent that nobody has addressed. | Set `KXM_AGENT_NAME` to the name peers send to. |
|
|
295
295
|
|
|
296
296
|
For hub-level problems, see [Troubleshoot KXM](../operations/troubleshooting.md).
|
|
297
297
|
|
|
@@ -91,7 +91,7 @@ kxm -V
|
|
|
91
91
|
- The `command` field is not always the words you typed: `hub stop` and `session stop` report `stop`, `session token` reports `auth token`, `routes admit` and `routes disable` report `routes admitted` and `routes disabled`, `models inventory-refresh` reports `models inventory refresh`, `workflow export` reports `retrospective export`, `gate degrade` reports `workflow degrade`, `gate signal` and `workflow signal` report `signal`, `gate github watch` reports `github watch`, `agent worker` reports `worker`, and `improve report` reports `improve`.
|
|
92
92
|
- A result with `ok: false` is written to stderr in both text and JSON mode; everything else goes to stdout. `runtime status` is the exception: when the supervisor is down it prints `ok: true, running: false` on stdout and exits 1.
|
|
93
93
|
- `peer` subcommands and `workflow checkpoint|record|wait` print the hub's result object as returned, tagged with `schema` but without `ok` or `command`. Their failures print `{"ok":false,"error":"command_failed","detail":"..."}`. Text mode prints the same JSON.
|
|
94
|
-
- Several error paths ignore `--json` and print one plain line on stderr: argument checks in `agent worker`, `session start`, `workflow start`, `gate degrade`, `gate signal`, and `gate github watch`; every error from `config`, `role`, `workflow definitions|add|remove|modify` (except the
|
|
94
|
+
- Several error paths ignore `--json` and print one plain line on stderr: argument checks in `agent worker`, `session start`, `workflow start`, `gate degrade`, `gate signal`, and `gate github watch`; every error from `config`, `role`, `workflow definitions|add|remove|modify` (except the `workflow add` refusals listed under it, which honor `--json`), `goal`, `task`, `memory`, `skills` (other than `skills create --dry-run`), `suggest`, `studio`, and `completion`. Check the exit code before parsing stdout.
|
|
95
95
|
- Every `context` subcommand exits 1 with a Node.js stack trace and no JSON when the hub cannot be reached.
|
|
96
96
|
- Output is redacted. Values of environment variables whose names contain `TOKEN`, `SECRET`, `KEY`, or `PASSWORD` are replaced with `[redacted]`, and 64-character hex strings are replaced unless they appear in a known digest field such as `configRevision` or `sha256`. `session brief` and `auth token` print the session token itself; treat their output as a credential.
|
|
97
97
|
|
|
@@ -1961,7 +1961,7 @@ WORKFLOW DEFINITIONS:
|
|
|
1961
1961
|
kxm workflow add [workflowId] [--template <name> | --file <path> | --pick [selection]] [--description <text>] [--scope global|local] [--overwrite]
|
|
1962
1962
|
```
|
|
1963
1963
|
|
|
1964
|
-
Add a workflow definition to global or local configuration. With `--template <name>`, the named built-in template is written under the workflow ID. Without a workflow ID, or with `--pick`, you choose from the built-in templates and, for local scope, existing global definitions. With `--file`, the YAML file is copied as-is. Otherwise a one-step scaffold is written: one `implementer` agent step with write access to `control` that ends the run `completed` on `passed` and `failed` on `failed`.
|
|
1964
|
+
Add a workflow definition to global or local configuration. With `--template <name>`, the named built-in template is written under the workflow ID. Without a workflow ID, or with `--pick`, you choose from the built-in templates and, for local scope, existing global definitions; a global definition with a template's ID is not offered. The choice is written under its own ID with its content: the template, or a copy of the global definition's file, with `--description` replacing its description. With `--file`, the YAML file is copied as-is once it passes the local check below. Otherwise a one-step scaffold is written: one `implementer` agent step with write access to `control` that ends the run `completed` on `passed` and `failed` on `failed`.
|
|
1965
1965
|
|
|
1966
1966
|
| Option | Argument | Default | Description |
|
|
1967
1967
|
|---|---|---|---|
|
|
@@ -1975,7 +1975,8 @@ Add a workflow definition to global or local configuration. With `--template <na
|
|
|
1975
1975
|
- Templates: `implement-and-verify` runs the `implementer` agent, then the project's `test` gate, and a failing gate (`implementation-failure`) sends the work back to `implement` at most twice. `dual-critic-review` adds two review steps between them, both run as the `coordinator` agent with read access; point `review-arch` and `review-cli` at your own agents for independent critics. `spec-and-plan` plans and then reviews the plan, both as `coordinator`, reading the repository only.
|
|
1976
1976
|
- The templates and the scaffold are valid `kxm.workflow.v1` definitions that use only what `kxm init` creates: the `coordinator` and `implementer` agents, the `control` repository, and the `test` gate. Each was checked with `kxm init --json` and `kxm run <id> --dry-run` for this page. A new file under `.kxm/workflows/` is a permission expansion that `kxm trust check` asks you to review before you commit it.
|
|
1977
1977
|
- Writes `<scope dir>/workflows/<id>.yaml`. `kxm run` loads only `.kxm/workflows/`, so a `--scope global` definition is not runnable until it is copied into a project. `--dry-run` plans the write and writes nothing.
|
|
1978
|
-
-
|
|
1978
|
+
- Local scope belongs to a KXM project: the file lands in the project root's `.kxm/workflows/` from any subdirectory, and outside a project the command refuses with `project_not_found` and creates nothing. Before writing, the project loader checks the project with the new document in place of any file of that ID, using the parser, schema and bundle rules `kxm run` uses. If the project would not load, the command refuses with `workflow_invalid`, lists each issue and writes nothing, also under `--dry-run`. So `--file` or a picked global definition with a top-level `id` or a `role:` step, the shape `workflow add` wrote through 0.7.92, is refused, and `--overwrite` replaces a file left in that shape. Global scope is not checked, because no loader reads it.
|
|
1979
|
+
- Refusals exit 2 and honor `--json`: `workflow_template_unknown` (the text names the three templates), `workflow_id_required` (no workflow ID), `workflow_add_conflict` (`--template` combined with `--file` or `--pick`), `project_not_found`, and `workflow_invalid` (with `issues`, each `{phase, code, file, message}`). An existing definition without `--overwrite` exits 1 with a plain `workflow add failed: workflow_already_exists: ...` line, also under `--dry-run`.
|
|
1979
1980
|
- JSON keys: `workflowId`, `id`, `filePath`, `scope`.
|
|
1980
1981
|
|
|
1981
1982
|
Start a first workflow from a template:
|
|
@@ -2397,18 +2398,21 @@ kxm peer fanout --targets reviewer critic --content "Independent review of PR 42
|
|
|
2397
2398
|
kxm peer inbox
|
|
2398
2399
|
```
|
|
2399
2400
|
|
|
2400
|
-
List inbound peer requests
|
|
2401
|
+
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
2402
|
|
|
2402
2403
|
| Option | Argument | Default | Description |
|
|
2403
2404
|
|---|---|---|---|
|
|
2404
2405
|
| `--payload` | `<json>` | none | JSON payload |
|
|
2405
2406
|
|
|
2407
|
+
- 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`).
|
|
2408
|
+
- 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.
|
|
2409
|
+
|
|
2406
2410
|
```bash
|
|
2407
|
-
kxm peer inbox --json
|
|
2411
|
+
KXM_AGENT_NAME=codex kxm peer inbox --json
|
|
2408
2412
|
```
|
|
2409
2413
|
|
|
2410
2414
|
```text
|
|
2411
|
-
{"schema":"kxm.cli-result.v1","messages":[]}
|
|
2415
|
+
{"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
2416
|
```
|
|
2413
2417
|
|
|
2414
2418
|
### `kxm peer reply`
|
|
@@ -3590,7 +3594,6 @@ These are behaviors of the current build that differ from what the help text or
|
|
|
3590
3594
|
|
|
3591
3595
|
- `kxm routing benchmark` prints constant placeholder figures.
|
|
3592
3596
|
- `kxm task sync` does not contact GitHub or Jira.
|
|
3593
|
-
- `kxm peer inbox` always returns an empty list from the CLI.
|
|
3594
3597
|
- `kxm context` subcommands crash with a stack trace when the hub is unreachable, and they ignore the persisted hub credential.
|
|
3595
3598
|
- `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`.
|
|
3596
3599
|
- `kxm backup` JSON shows `manifestSha256` redacted.
|
|
@@ -889,8 +889,10 @@ compiles and pins the plan, then drives it live, or without models with
|
|
|
889
889
|
reads). Both are valid `kxm.workflow.v1` definitions that use only what
|
|
890
890
|
`kxm init` creates: the `coordinator` and `implementer` agents, the `control`
|
|
891
891
|
repository, and the `test` gate. The templates route gate failures on
|
|
892
|
-
`implementation-failure`.
|
|
893
|
-
|
|
892
|
+
`implementation-failure`. A local add is checked by the project loader first:
|
|
893
|
+
if the project would not load with the new file, it is refused with
|
|
894
|
+
`workflow_invalid` and nothing is written. Review the new file with
|
|
895
|
+
`kxm trust check` before committing it.
|
|
894
896
|
|
|
895
897
|
## `.kxm/gates.yaml` (`kxm.gate-registry.v1`)
|
|
896
898
|
|
|
@@ -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.
|
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
|
|
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.100",
|
|
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
|
{
|