@kontextmind/kxm 0.7.112 → 0.7.115

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.
@@ -11,7 +11,7 @@
11
11
  "name": "kxm",
12
12
  "source": "./plugins/kxm",
13
13
  "description": "Durable workflows, peer agents, and kxm tui",
14
- "version": "0.7.112",
14
+ "version": "0.7.115",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
@@ -3,7 +3,7 @@ purpose: Implement the approved change within the declared repository scope.
3
3
  harness: grok
4
4
  model:
5
5
  provider: xai
6
- model: grok-4.6
6
+ model: grok-4.7
7
7
  tools:
8
8
  preset: workspace-writer
9
9
  defaultRepositoryAccess: none
@@ -5,7 +5,7 @@ id: writer
5
5
  # Effort default: medium for implementation (AGENTS.md). agy ids bake in the
6
6
  # effort tier, so those entries carry no effort field.
7
7
  roster:
8
- - model: xai/grok-4.6
8
+ - model: xai/grok-4.7
9
9
  effort: medium
10
10
  enabled: true
11
11
  - model: openrouter/qwen/qwen3-coder-plus
@@ -33,7 +33,7 @@ permissions:
33
33
 
34
34
  | Role | Admitted route (harness / model) | Vendor | Permission |
35
35
  |---|---|---|---|
36
- | `writer` | `grok` / `grok-4.6`; relief: `pi` / `openrouter/qwen/qwen3-coder-plus` | `xai`; `alibaba` | `edit` |
36
+ | `writer` | `grok` / `grok-4.7`; relief: `pi` / `openrouter/qwen/qwen3-coder-plus` | `xai`; `alibaba` | `edit` |
37
37
  | `planner` | `claude` / `fable` | `anthropic` | `read-only` |
38
38
  | `reviewer-arch` | `claude` / `fable` | `anthropic` | `read-only` |
39
39
  | `reviewer-cli` | `codex` / `gpt-5.6-sol` | `openai` | `read-only` |
@@ -115,7 +115,7 @@ Write a closed `kxm.assignment.v1` manifest. Unknown keys are refused.
115
115
  "assignment_id": "asg-writer-1",
116
116
  "kind": "implement",
117
117
  "harness": "grok",
118
- "model": "grok-4.6",
118
+ "model": "grok-4.7",
119
119
  "effort": "medium",
120
120
  "permission": "edit",
121
121
  "cwd": "/abs/kxm-fix-improve-sources",
@@ -247,7 +247,7 @@ then is that `BLOCK` resolved.
247
247
  ├── output-schema.json # the structured-output schema given to the harness
248
248
  ├── pre-dispatch.json # written before spawn (kxm.assignment-dispatch.v1)
249
249
  ├── completion.json # kxm.assignment-completion.v1, or refusal.json
250
- ├── routing-record.json # read by kxm routing report
250
+ ├── routing-record.json # export with `node scripts/assignment-run.mjs routing-export --task-dir <abs>` and pass the JSONL to `kxm improve report --file` / `kxm routing report --file`
251
251
  ├── telemetry.jsonl # usage, latency and cost
252
252
  ├── runner-errors.jsonl # bounded failure codes
253
253
  ├── witness/ # latest.json and history/<receipt-id>.json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.112",
3
+ "version": "0.7.115",
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.112",
5
+ "version": "0.7.115",
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",
@@ -17313,7 +17313,7 @@ function sessionTokenFixHint(policy) {
17313
17313
  }
17314
17314
 
17315
17315
  // plugins/kxm/src/mcp-server.ts
17316
- var VERSION = "0.7.112";
17316
+ var VERSION = "0.7.115";
17317
17317
  var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
17318
17318
  var inbox = /* @__PURE__ */ new Map();
17319
17319
  var notifiedInbox = /* @__PURE__ */ new Set();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plugin",
3
- "version": "0.7.112",
3
+ "version": "0.7.115",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
@@ -11,7 +11,7 @@ import { deliverInboxNotification } from "./inbox.ts";
11
11
  import type { HubEvent, MessageRecord } from "./protocol.ts";
12
12
  import { sessionTokenFixHint } from "./session-token-hint.ts";
13
13
 
14
- const VERSION = "0.7.112";
14
+ const VERSION = "0.7.115";
15
15
  const CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
16
16
  const inbox = new Map<string, MessageRecord>();
17
17
  const notifiedInbox = new Set<string>();
@@ -339,6 +339,13 @@ export function changeReport(request: { taskDir: string }, deps?: Record<string,
339
339
  ranking: "not-ranked";
340
340
  orchestration_usage: "unavailable";
341
341
  };
342
+ export const ROUTING_EXPORT_SCHEMA: "kxm.assignment-routing-export.v1";
343
+ export function exportAssignmentRoutingRecords(request: { taskDir: string }, deps?: Record<string, unknown>): {
344
+ schema: "kxm.assignment-routing-export.v1";
345
+ task_id: string;
346
+ records: Array<Record<string, any>>;
347
+ skipped: Array<{ assignment_id: string | null; reason: "acceptance_record_invalid" | "no_routing_record" | "routing_record_invalid" | "manifest_invalid" }>;
348
+ };
342
349
  export function writeCurrentPlan(request: {
343
350
  taskDir: string; plan: string; sha256: string; baseCommit: string; expectedGeneration: number; settledDecisions?: string[];
344
351
  }, deps?: Record<string, unknown>): {
@@ -2330,7 +2330,7 @@ export async function observeAssignment(outputDir, deps = {}) {
2330
2330
  return appended;
2331
2331
  }
2332
2332
 
2333
- const CLI_USAGE = "usage: assignment-run.mjs run --manifest <absolute-path> | observe --record-dir <absolute-path> | witness --record-dir <absolute-path> | accept --task-dir <absolute-path> --commit <commit> --record-dir <absolute-path> --critic <absolute-path> --critic <absolute-path> [--observed-pr <id>] [--observed-ci <id>] | attribute --task-dir <absolute-path> --record-dir <absolute-path> --class <orchestration|model|environment|unclassified> --explanation-file <absolute-path> | observe-cost --task-dir <absolute-path> --input <absolute-path> | plan-current --task-dir <absolute-path> --plan <absolute-path> --sha256 <hex64> --base-commit <commit> --expected-generation <n> | change-report --task-dir <absolute-path>";
2333
+ const CLI_USAGE = "usage: assignment-run.mjs run --manifest <absolute-path> | observe --record-dir <absolute-path> | witness --record-dir <absolute-path> | accept --task-dir <absolute-path> --commit <commit> --record-dir <absolute-path> --critic <absolute-path> --critic <absolute-path> [--observed-pr <id>] [--observed-ci <id>] | attribute --task-dir <absolute-path> --record-dir <absolute-path> --class <orchestration|model|environment|unclassified> --explanation-file <absolute-path> | observe-cost --task-dir <absolute-path> --input <absolute-path> | plan-current --task-dir <absolute-path> --plan <absolute-path> --sha256 <hex64> --base-commit <commit> --expected-generation <n> | change-report --task-dir <absolute-path> | routing-export --task-dir <absolute-path>";
2334
2334
 
2335
2335
  const WITNESS_RECEIPT_KEYS = Object.freeze([
2336
2336
  "schema",
@@ -4293,8 +4293,135 @@ export function writeCurrentPlan(request, deps = {}) {
4293
4293
  } catch (error) { throw observationFailure(error, "plan_ref_invalid"); }
4294
4294
  }
4295
4295
 
4296
+ export const ROUTING_EXPORT_SCHEMA = "kxm.assignment-routing-export.v1";
4297
+
4298
+ function contractExportable(contract) {
4299
+ return Boolean(contract)
4300
+ && typeof contract === "object"
4301
+ && !Array.isArray(contract)
4302
+ && typeof contract.boundary === "string"
4303
+ && Array.isArray(contract.deliverables)
4304
+ && contract.witness
4305
+ && typeof contract.witness === "object"
4306
+ && !Array.isArray(contract.witness)
4307
+ && typeof contract.witness.id === "string"
4308
+ && Array.isArray(contract.deferred);
4309
+ }
4310
+
4311
+ export function exportAssignmentRoutingRecords(request, deps = {}) {
4312
+ const io = ioDeps(deps);
4313
+ const taskDir = observationTask(request.taskDir, io);
4314
+ const taskId = basename(taskDir);
4315
+ const skipped = [];
4316
+ const acceptedIds = new Set();
4317
+ const acceptedPath = join(taskDir, ACCEPTED_FILENAME);
4318
+ if (lstatOrNull(acceptedPath, io.lstatSync)) {
4319
+ try {
4320
+ const value = privateRecord(acceptedPath, io).value;
4321
+ const valid = value.schema === ACCEPTED_SCHEMA
4322
+ && value.task_id === taskId
4323
+ && typeof value.writer?.assignment_id === "string"
4324
+ && Array.isArray(value.critics);
4325
+ if (!valid) throw new Error("acceptance invalid");
4326
+ acceptedIds.add(value.writer.assignment_id);
4327
+ for (const critic of value.critics) {
4328
+ if (typeof critic?.assignment_id === "string") acceptedIds.add(critic.assignment_id);
4329
+ }
4330
+ } catch {
4331
+ skipped.push({ assignment_id: null, reason: "acceptance_record_invalid" });
4332
+ }
4333
+ }
4334
+ const collected = [];
4335
+ const dirs = listDirectAssignmentDirs(taskDir, io).sort((left, right) => left.assignment_id < right.assignment_id ? -1 : left.assignment_id > right.assignment_id ? 1 : 0);
4336
+ for (const { assignment_id, path } of dirs) {
4337
+ const routingPath = join(path, "routing-record.json");
4338
+ if (!lstatOrNull(routingPath, io.lstatSync)) {
4339
+ skipped.push({ assignment_id, reason: "no_routing_record" });
4340
+ continue;
4341
+ }
4342
+ let record;
4343
+ try {
4344
+ record = parseRoutingRecord(privateRecord(routingPath, io).value);
4345
+ if (record.workflowRunId !== assignment_id) throw new Error("workflowRunId");
4346
+ } catch {
4347
+ skipped.push({ assignment_id, reason: "routing_record_invalid" });
4348
+ continue;
4349
+ }
4350
+ let contract;
4351
+ try {
4352
+ const manifest = privateRecord(join(path, "manifest.json"), io).value;
4353
+ contract = manifest.contract;
4354
+ if (!contractExportable(contract)) throw new Error("contract");
4355
+ } catch {
4356
+ skipped.push({ assignment_id, reason: "manifest_invalid" });
4357
+ continue;
4358
+ }
4359
+ collected.push({ id: assignment_id, record, contract });
4360
+ }
4361
+ const supersededBy = new Map();
4362
+ for (const entry of collected) {
4363
+ const reworkOf = entry.record.providerMetadata?.rework_of;
4364
+ if (typeof reworkOf === "string" && !supersededBy.has(reworkOf)) supersededBy.set(reworkOf, entry.id);
4365
+ }
4366
+ const records = [];
4367
+ for (const entry of collected) {
4368
+ const kind = entry.record.stageId;
4369
+ const role = entry.record.agentRole;
4370
+ const askSha256 = sha256Bytes(Buffer.from(JSON.stringify(["kxm.assignment-ask.v1", kind, role])));
4371
+ const objectiveSha256 = sha256Bytes(Buffer.from(JSON.stringify([
4372
+ "kxm.assignment-brief.v1",
4373
+ kind,
4374
+ entry.contract.boundary,
4375
+ entry.contract.deliverables,
4376
+ entry.contract.witness.id,
4377
+ entry.contract.deferred,
4378
+ ])));
4379
+ const finalOutcome = acceptedIds.has(entry.id) ? "accepted" : supersededBy.has(entry.id) ? "failed" : "pending";
4380
+ try {
4381
+ records.push(parseRoutingRecord({
4382
+ ...entry.record,
4383
+ workflowRunId: taskId,
4384
+ finalOutcome,
4385
+ providerMetadata: {
4386
+ ...entry.record.providerMetadata,
4387
+ workflowId: "assignment-runner",
4388
+ askSha256,
4389
+ objectiveSha256,
4390
+ stepWrites: WRITER_KINDS.includes(kind),
4391
+ assignmentId: entry.id,
4392
+ ...(finalOutcome === "failed" ? { supersededBy: supersededBy.get(entry.id) } : {}),
4393
+ },
4394
+ }));
4395
+ } catch {
4396
+ skipped.push({ assignment_id: entry.id, reason: "routing_record_invalid" });
4397
+ }
4398
+ }
4399
+ return { schema: ROUTING_EXPORT_SCHEMA, task_id: taskId, records, skipped };
4400
+ }
4401
+
4296
4402
  export async function main(argv = process.argv, io = { stdin: process.stdin, stdout: process.stdout, stderr: process.stderr }) {
4297
4403
  const args = argv.slice(2).filter((arg) => arg !== "--");
4404
+ if (args[0] === "routing-export") {
4405
+ try {
4406
+ const values = {};
4407
+ for (let i = 1; i < args.length; i += 2) {
4408
+ if (args[i] !== "--task-dir" || values[args[i]] !== undefined || args[i + 1] === undefined) throw failClosed("invalid report/plan arguments", "manifest_invalid");
4409
+ values[args[i]] = args[i + 1];
4410
+ }
4411
+ if (values["--task-dir"] === undefined) throw failClosed("missing report/plan arguments", "manifest_invalid");
4412
+ const result = exportAssignmentRoutingRecords({ taskDir: values["--task-dir"] });
4413
+ for (const record of result.records) io.stdout.write(`${JSON.stringify(record)}\n`);
4414
+ io.stderr.write(`${JSON.stringify({ schema: result.schema, task_id: result.task_id, records: result.records.length, skipped: result.skipped })}\n`);
4415
+ process.exitCode = 0;
4416
+ return result;
4417
+ } catch (error) {
4418
+ const failure = observationFailure(error);
4419
+ io.stderr.write(`${failure.runnerCode}: assignment routing export refused\n`);
4420
+ process.exitCode = 1;
4421
+ throw failure;
4422
+ }
4423
+ }
4424
+
4298
4425
  if (["change-report", "plan-current"].includes(args[0])) {
4299
4426
  try {
4300
4427
  const flags = args[0] === "change-report" ? ["--task-dir"] : ["--task-dir", "--plan", "--sha256", "--base-commit", "--expected-generation"];
@@ -137,7 +137,7 @@ export const ROUTES = Object.freeze({
137
137
  provider: "xai",
138
138
  roles: Object.freeze(["writer"]),
139
139
  permissions: Object.freeze(["edit"]),
140
- models: Object.freeze(["grok-4.6"]),
140
+ models: Object.freeze(["grok-4.7"]),
141
141
  efforts: Object.freeze(["low", "medium", "high"]),
142
142
  auth: Object.freeze({ args: ["models"], loginHint: "grok (OAuth to auth.x.ai)" }),
143
143
  },
@@ -153,7 +153,7 @@ export const ROUTES = Object.freeze({
153
153
  provider: "anthropic",
154
154
  roles: Object.freeze(["planner", "reviewer-arch"]),
155
155
  permissions: Object.freeze(["read-only"]),
156
- models: Object.freeze(["fable"]),
156
+ models: Object.freeze(["fable", "opus"]),
157
157
  efforts: Object.freeze(["low", "medium", "high", "xhigh", "max"]),
158
158
  auth: Object.freeze({ args: ["auth", "status"], loginHint: "claude auth login" }),
159
159
  },
@@ -8,13 +8,13 @@ import { buildArgv } from "./harness-run.mjs";
8
8
 
9
9
  // Launch intent only: these labels are not observed model identity or admission.
10
10
  export function nativeCriticLaunch(harness) {
11
- if (!["fable", "astra"].includes(harness)) {
12
- throw new Error("usage: native-critic.mjs <fable|astra> <prompt>");
11
+ if (!["fable", "astra", "opus"].includes(harness)) {
12
+ throw new Error("usage: native-critic.mjs <fable|astra|opus> <prompt>");
13
13
  }
14
- const model = harness === "fable" ? "fable" : "gpt-6-astra";
15
- const command = harness === "fable" ? "claude" : "codex";
16
- const args = harness === "fable"
17
- ? ["-p", "--model", model, "--output-format", "json", "--no-session-persistence", "--tools", "Read,Glob,Grep", "--setting-sources", "user"]
14
+ const model = harness === "fable" ? "fable" : harness === "opus" ? "opus" : "gpt-6-astra";
15
+ const command = harness === "fable" || harness === "opus" ? "claude" : "codex";
16
+ const args = harness === "fable" || harness === "opus"
17
+ ? ["-p", "--model", model, "--effort", "medium", "--output-format", "json", "--no-session-persistence", "--tools", "Read,Glob,Grep", "--setting-sources", "user"]
18
18
  : buildArgv({ harness: "codex", model, effort: "low", permission: "read-only", prompt_file: "-" });
19
19
  return { model, command, args };
20
20
  }
@@ -36,7 +36,7 @@ async function main() {
36
36
  mkdirSync(outDir, { recursive: true });
37
37
  const client = new HubClient({ serverUrl, authToken: env.KXM_AUTH_TOKEN, name: `${harness}-critic`, purpose: "independent CLI critic", project: env.KXM_PROJECT || ".kxm", model });
38
38
  const prompt = promptParts.join(" ");
39
- const agent = await client.start(() => {});
39
+ const agent = await client.start(() => { });
40
40
  const result = await new Promise((resolve) => {
41
41
  const child = spawn(command, args, { env, stdio: ["pipe", "pipe", "pipe"], shell: false });
42
42
  let stdout = "", stderr = "";