@kontextmind/kxm 0.7.76 → 0.7.77

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.76",
14
+ "version": "0.7.77",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.76",
3
+ "version": "0.7.77",
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.76",
5
+ "version": "0.7.77",
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",
@@ -17182,7 +17182,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
17182
17182
  }
17183
17183
 
17184
17184
  // plugins/kxm/src/mcp-server.ts
17185
- var VERSION = "0.7.76";
17185
+ var VERSION = "0.7.77";
17186
17186
  var inbox = /* @__PURE__ */ new Map();
17187
17187
  var notifiedInbox = /* @__PURE__ */ new Set();
17188
17188
  var meshClient;
@@ -14781,9 +14781,9 @@ var require_dist = __commonJS({
14781
14781
  // plugins/kxm/src/runtime-supervisor.ts
14782
14782
  import { spawn as spawn3 } from "node:child_process";
14783
14783
  import { createHash as createHash12, createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
14784
- import { chmodSync as chmodSync2, existsSync as existsSync12, lstatSync as lstatSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
14784
+ import { chmodSync as chmodSync2, existsSync as existsSync12, lstatSync as lstatSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
14785
14785
  import { createServer } from "node:http";
14786
- import { dirname as dirname8, isAbsolute as isAbsolute6, join as join16 } from "node:path";
14786
+ import { dirname as dirname8, isAbsolute as isAbsolute6, join as join15 } from "node:path";
14787
14787
 
14788
14788
  // plugins/kxm/src/repo-root.ts
14789
14789
  import { existsSync } from "node:fs";
@@ -16919,8 +16919,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
16919
16919
  const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
16920
16920
  if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
16921
16921
  }
16922
- const join17 = objectValue(step.join);
16923
- const minimumPassed = join17 && typeof join17.minimumPassed === "number" ? join17.minimumPassed : void 0;
16922
+ const join16 = objectValue(step.join);
16923
+ const minimumPassed = join16 && typeof join16.minimumPassed === "number" ? join16.minimumPassed : void 0;
16924
16924
  if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
16925
16925
  const distinctBy = names(assignment?.distinctBy);
16926
16926
  if (distinctBy.length > 0) {
@@ -20987,7 +20987,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
20987
20987
  const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
20988
20988
  const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
20989
20989
  const assignments = compileAssignments(step, id, agent, sink);
20990
- const join17 = compileJoin(step, id, sink);
20990
+ const join16 = compileJoin(step, id, sink);
20991
20991
  const requiredEvidence = compileEvidence(step, id, sink);
20992
20992
  const transitions = compileTransitions(step, id, index, stepIndex, sink);
20993
20993
  const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
@@ -21015,7 +21015,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
21015
21015
  transitions: orderedTransitions,
21016
21016
  requiresPlanHash: requirePlanHash.includes(id),
21017
21017
  assignments,
21018
- join: join17
21018
+ join: join16
21019
21019
  };
21020
21020
  if (kind === "agent" || kind === "moa") {
21021
21021
  if (!agent) return void 0;
@@ -21065,15 +21065,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
21065
21065
  };
21066
21066
  }
21067
21067
  function compileJoin(step, stepId, sink) {
21068
- const join17 = objectValue2(step.join);
21069
- if (!join17) return { strategy: "all" };
21070
- const declared = stringValue2(join17.strategy);
21068
+ const join16 = objectValue2(step.join);
21069
+ if (!join16) return { strategy: "all" };
21070
+ const declared = stringValue2(join16.strategy);
21071
21071
  const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
21072
- const minimumPassed = compileOptionalCount(join17.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
21072
+ const minimumPassed = compileOptionalCount(join16.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
21073
21073
  const compiled = {
21074
21074
  strategy,
21075
21075
  ...minimumPassed !== void 0 ? { minimumPassed } : {},
21076
- ...typeof join17.cancelRemaining === "boolean" ? { cancelRemaining: join17.cancelRemaining } : {}
21076
+ ...typeof join16.cancelRemaining === "boolean" ? { cancelRemaining: join16.cancelRemaining } : {}
21077
21077
  };
21078
21078
  return compiled;
21079
21079
  }
@@ -27473,23 +27473,9 @@ function resolveClientHubAuthToken(env, project) {
27473
27473
  return record2?.projectTokens?.[project]?.trim() || record2?.authToken?.trim() || void 0;
27474
27474
  }
27475
27475
 
27476
- // plugins/kxm/src/project-name.ts
27477
- import { readFileSync as readFileSync10 } from "node:fs";
27478
- import { basename as basename3, join as join15 } from "node:path";
27479
- function defaultProjectName(cwd, env = process.env) {
27480
- const fromEnv = env.KXM_PROJECT?.trim();
27481
- if (fromEnv) return fromEnv;
27482
- try {
27483
- const pkg = JSON.parse(readFileSync10(join15(cwd, "package.json"), "utf8"));
27484
- if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
27485
- } catch {
27486
- }
27487
- return basename3(cwd);
27488
- }
27489
-
27490
27476
  // plugins/kxm/src/runtime-supervisor.ts
27491
27477
  function kxmSupervisorTokenFile(paths) {
27492
- return join16(paths.runtimeDir, "supervisor.token");
27478
+ return join15(paths.runtimeDir, "supervisor.token");
27493
27479
  }
27494
27480
  function publishKxmSupervisorToken(paths, token) {
27495
27481
  const file = kxmSupervisorTokenFile(paths);
@@ -27517,7 +27503,7 @@ function readKxmSupervisorToken(paths) {
27517
27503
  if (stat.isSymbolicLink() || !stat.isFile()) {
27518
27504
  throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
27519
27505
  }
27520
- const token = readFileSync11(file, "utf8").trim();
27506
+ const token = readFileSync10(file, "utf8").trim();
27521
27507
  return token.length >= 32 ? token : void 0;
27522
27508
  }
27523
27509
  function processAlive(pid) {
@@ -27531,7 +27517,7 @@ function processAlive(pid) {
27531
27517
  var HEARTBEAT_STALE_MS = 15e3;
27532
27518
  var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
27533
27519
  function supervisorErrorFile(paths) {
27534
- return join16(paths.runtimeDir, "supervisor.error");
27520
+ return join15(paths.runtimeDir, "supervisor.error");
27535
27521
  }
27536
27522
  function clearSupervisorError(paths) {
27537
27523
  const file = supervisorErrorFile(paths);
@@ -27552,7 +27538,7 @@ function readRecentSupervisorError(paths) {
27552
27538
  const ageMs = Date.now() - stat.mtimeMs;
27553
27539
  if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
27554
27540
  try {
27555
- return readFileSync11(file, "utf8").trim();
27541
+ return readFileSync10(file, "utf8").trim();
27556
27542
  } catch {
27557
27543
  return void 0;
27558
27544
  }
@@ -27628,7 +27614,7 @@ async function ensureKxmSupervisor(options = {}) {
27628
27614
  throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
27629
27615
  }
27630
27616
  clearSupervisorError(paths);
27631
- const scriptPath = join16(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
27617
+ const scriptPath = join15(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
27632
27618
  const spawnImpl = options.spawnImpl ?? ((script, env) => {
27633
27619
  const child = spawn3(process.execPath, [script], {
27634
27620
  detached: true,
@@ -27783,7 +27769,7 @@ async function syncKxmOutbox(eventStore, client, options = {}) {
27783
27769
  function runtimeHubClientFor(context, env) {
27784
27770
  const serverUrl = env.KXM_SERVER_URL?.trim() || readHubBinding(env)?.url;
27785
27771
  if (!serverUrl) return void 0;
27786
- const project = defaultProjectName(context.projectRoot, env);
27772
+ const project = context.projectId;
27787
27773
  const authToken = resolveClientHubAuthToken(env, project);
27788
27774
  return new RuntimeHubClient({
27789
27775
  serverUrl,
@@ -27815,7 +27801,7 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now) {
27815
27801
  let activeRuntimeId = runtimeId;
27816
27802
  const contexts = /* @__PURE__ */ new Map();
27817
27803
  const registerSyncCredentials = (context) => {
27818
- const hubToken = resolveClientHubAuthToken(process.env, defaultProjectName(context.projectRoot, process.env));
27804
+ const hubToken = resolveClientHubAuthToken(process.env, context.projectId);
27819
27805
  if (hubToken) context.eventStore.syncRedactor.register(hubToken);
27820
27806
  for (const key of Object.keys(process.env)) {
27821
27807
  if (key.startsWith("KXM_") && (key.endsWith("_TOKEN") || key.endsWith("_KEY")) || key.endsWith("_API_KEY") || key.endsWith("_SECRET")) {
@@ -17089,8 +17089,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17089
17089
  const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
17090
17090
  if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
17091
17091
  }
17092
- const join21 = objectValue(step.join);
17093
- const minimumPassed = join21 && typeof join21.minimumPassed === "number" ? join21.minimumPassed : void 0;
17092
+ const join20 = objectValue(step.join);
17093
+ const minimumPassed = join20 && typeof join20.minimumPassed === "number" ? join20.minimumPassed : void 0;
17094
17094
  if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
17095
17095
  const distinctBy = names(assignment?.distinctBy);
17096
17096
  if (distinctBy.length > 0) {
@@ -21422,7 +21422,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
21422
21422
  const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
21423
21423
  const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
21424
21424
  const assignments = compileAssignments(step, id, agent, sink);
21425
- const join21 = compileJoin(step, id, sink);
21425
+ const join20 = compileJoin(step, id, sink);
21426
21426
  const requiredEvidence = compileEvidence(step, id, sink);
21427
21427
  const transitions = compileTransitions(step, id, index, stepIndex, sink);
21428
21428
  const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
@@ -21450,7 +21450,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
21450
21450
  transitions: orderedTransitions,
21451
21451
  requiresPlanHash: requirePlanHash.includes(id),
21452
21452
  assignments,
21453
- join: join21
21453
+ join: join20
21454
21454
  };
21455
21455
  if (kind === "agent" || kind === "moa") {
21456
21456
  if (!agent) return void 0;
@@ -21500,15 +21500,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
21500
21500
  };
21501
21501
  }
21502
21502
  function compileJoin(step, stepId, sink) {
21503
- const join21 = objectValue2(step.join);
21504
- if (!join21) return { strategy: "all" };
21505
- const declared = stringValue2(join21.strategy);
21503
+ const join20 = objectValue2(step.join);
21504
+ if (!join20) return { strategy: "all" };
21505
+ const declared = stringValue2(join20.strategy);
21506
21506
  const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
21507
- const minimumPassed = compileOptionalCount(join21.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
21507
+ const minimumPassed = compileOptionalCount(join20.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
21508
21508
  const compiled = {
21509
21509
  strategy,
21510
21510
  ...minimumPassed !== void 0 ? { minimumPassed } : {},
21511
- ...typeof join21.cancelRemaining === "boolean" ? { cancelRemaining: join21.cancelRemaining } : {}
21511
+ ...typeof join20.cancelRemaining === "boolean" ? { cancelRemaining: join20.cancelRemaining } : {}
21512
21512
  };
21513
21513
  return compiled;
21514
21514
  }
@@ -23356,9 +23356,9 @@ function assertKxmConfigError(error) {
23356
23356
  // plugins/kxm/src/runtime-supervisor.ts
23357
23357
  import { spawn as spawn3 } from "node:child_process";
23358
23358
  import { createHash as createHash13, createHmac, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
23359
- import { chmodSync as chmodSync2, existsSync as existsSync12, lstatSync as lstatSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
23359
+ import { chmodSync as chmodSync2, existsSync as existsSync12, lstatSync as lstatSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
23360
23360
  import { createServer } from "node:http";
23361
- import { dirname as dirname8, isAbsolute as isAbsolute6, join as join16 } from "node:path";
23361
+ import { dirname as dirname8, isAbsolute as isAbsolute6, join as join15 } from "node:path";
23362
23362
 
23363
23363
  // plugins/kxm/src/oneshot-producer.ts
23364
23364
  import { join as join12 } from "node:path";
@@ -27988,23 +27988,9 @@ function resolveClientHubAuthToken(env, project) {
27988
27988
  return record2?.projectTokens?.[project]?.trim() || record2?.authToken?.trim() || void 0;
27989
27989
  }
27990
27990
 
27991
- // plugins/kxm/src/project-name.ts
27992
- import { readFileSync as readFileSync10 } from "node:fs";
27993
- import { basename as basename3, join as join15 } from "node:path";
27994
- function defaultProjectName(cwd, env = process.env) {
27995
- const fromEnv = env.KXM_PROJECT?.trim();
27996
- if (fromEnv) return fromEnv;
27997
- try {
27998
- const pkg = JSON.parse(readFileSync10(join15(cwd, "package.json"), "utf8"));
27999
- if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
28000
- } catch {
28001
- }
28002
- return basename3(cwd);
28003
- }
28004
-
28005
27991
  // plugins/kxm/src/runtime-supervisor.ts
28006
27992
  function kxmSupervisorTokenFile(paths) {
28007
- return join16(paths.runtimeDir, "supervisor.token");
27993
+ return join15(paths.runtimeDir, "supervisor.token");
28008
27994
  }
28009
27995
  function publishKxmSupervisorToken(paths, token) {
28010
27996
  const file = kxmSupervisorTokenFile(paths);
@@ -28032,7 +28018,7 @@ function readKxmSupervisorToken(paths) {
28032
28018
  if (stat.isSymbolicLink() || !stat.isFile()) {
28033
28019
  throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
28034
28020
  }
28035
- const token = readFileSync11(file, "utf8").trim();
28021
+ const token = readFileSync10(file, "utf8").trim();
28036
28022
  return token.length >= 32 ? token : void 0;
28037
28023
  }
28038
28024
  function processAlive(pid) {
@@ -28046,7 +28032,7 @@ function processAlive(pid) {
28046
28032
  var HEARTBEAT_STALE_MS = 15e3;
28047
28033
  var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
28048
28034
  function supervisorErrorFile(paths) {
28049
- return join16(paths.runtimeDir, "supervisor.error");
28035
+ return join15(paths.runtimeDir, "supervisor.error");
28050
28036
  }
28051
28037
  function clearSupervisorError(paths) {
28052
28038
  const file = supervisorErrorFile(paths);
@@ -28067,7 +28053,7 @@ function readRecentSupervisorError(paths) {
28067
28053
  const ageMs = Date.now() - stat.mtimeMs;
28068
28054
  if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
28069
28055
  try {
28070
- return readFileSync11(file, "utf8").trim();
28056
+ return readFileSync10(file, "utf8").trim();
28071
28057
  } catch {
28072
28058
  return void 0;
28073
28059
  }
@@ -28143,7 +28129,7 @@ async function ensureKxmSupervisor(options = {}) {
28143
28129
  throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
28144
28130
  }
28145
28131
  clearSupervisorError(paths);
28146
- const scriptPath = join16(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
28132
+ const scriptPath = join15(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
28147
28133
  const spawnImpl = options.spawnImpl ?? ((script, env) => {
28148
28134
  const child = spawn3(process.execPath, [script], {
28149
28135
  detached: true,
@@ -28298,7 +28284,7 @@ async function syncKxmOutbox(eventStore, client, options = {}) {
28298
28284
  function runtimeHubClientFor(context, env) {
28299
28285
  const serverUrl = env.KXM_SERVER_URL?.trim() || readHubBinding(env)?.url;
28300
28286
  if (!serverUrl) return void 0;
28301
- const project = defaultProjectName(context.projectRoot, env);
28287
+ const project = context.projectId;
28302
28288
  const authToken = resolveClientHubAuthToken(env, project);
28303
28289
  return new RuntimeHubClient({
28304
28290
  serverUrl,
@@ -28330,7 +28316,7 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now) {
28330
28316
  let activeRuntimeId = runtimeId;
28331
28317
  const contexts = /* @__PURE__ */ new Map();
28332
28318
  const registerSyncCredentials = (context) => {
28333
- const hubToken = resolveClientHubAuthToken(process.env, defaultProjectName(context.projectRoot, process.env));
28319
+ const hubToken = resolveClientHubAuthToken(process.env, context.projectId);
28334
28320
  if (hubToken) context.eventStore.syncRedactor.register(hubToken);
28335
28321
  for (const key of Object.keys(process.env)) {
28336
28322
  if (key.startsWith("KXM_") && (key.endsWith("_TOKEN") || key.endsWith("_KEY")) || key.endsWith("_API_KEY") || key.endsWith("_SECRET")) {
@@ -28774,7 +28760,7 @@ async function kxmRuntimeRequest(handle, method, path, body) {
28774
28760
 
28775
28761
  // plugins/kxm/src/pi-producer.ts
28776
28762
  import { spawn as spawn4 } from "node:child_process";
28777
- import { join as join17 } from "node:path";
28763
+ import { join as join16 } from "node:path";
28778
28764
  import { StringDecoder } from "node:string_decoder";
28779
28765
  function formatPiSessionKey(params) {
28780
28766
  if (params.agentId === "coordinator") {
@@ -29148,7 +29134,7 @@ function createKxmPiProducer(options = {}) {
29148
29134
  const args = ["--mode", "rpc", "--name", displayName];
29149
29135
  if (options.sessionDir) {
29150
29136
  const safeDirName = key.replace(/[^a-zA-Z0-9_-]/g, "_");
29151
- args.push("--session-dir", join17(options.sessionDir, request.runId, safeDirName));
29137
+ args.push("--session-dir", join16(options.sessionDir, request.runId, safeDirName));
29152
29138
  }
29153
29139
  if (model) {
29154
29140
  args.push("--model", model);
@@ -29427,7 +29413,7 @@ function createLogger(options) {
29427
29413
  // plugins/kxm/src/improve.ts
29428
29414
  import { createHash as createHash14 } from "node:crypto";
29429
29415
  import { existsSync as existsSync14, mkdirSync as mkdirSync8, writeFileSync as writeFileSync7 } from "node:fs";
29430
- import { join as join18, relative as relative4, resolve as resolve8 } from "node:path";
29416
+ import { join as join17, relative as relative4, resolve as resolve8 } from "node:path";
29431
29417
  var CANDIDATE_SCHEMA = "kxm.candidate.v1";
29432
29418
  var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
29433
29419
  var IMPROVEMENT_REPORT_V1_SCHEMA = "kxm.improvement-report.v1";
@@ -29600,7 +29586,7 @@ function groupRoutingRecords(records, options = {}) {
29600
29586
  }
29601
29587
  function buildImprovementReport(records, options = {}) {
29602
29588
  const projectRoot = options.projectRoot ? resolve8(options.projectRoot) : process.cwd();
29603
- const candidatesDir = options.candidatesDir ? resolve8(options.candidatesDir) : join18(projectRoot, ".kxm", "candidates");
29589
+ const candidatesDir = options.candidatesDir ? resolve8(options.candidatesDir) : join17(projectRoot, ".kxm", "candidates");
29604
29590
  const groups = groupRoutingRecords(records, options);
29605
29591
  const candidates = [];
29606
29592
  for (const group of groups) {
@@ -29612,7 +29598,7 @@ function buildImprovementReport(records, options = {}) {
29612
29598
  group.workflowHash
29613
29599
  );
29614
29600
  const diffFileName = `${group.candidateId}.diff`;
29615
- const diffFilePath = join18(candidatesDir, diffFileName);
29601
+ const diffFilePath = join17(candidatesDir, diffFileName);
29616
29602
  const relDiffPath = relative4(projectRoot, diffFilePath).replace(/\\/g, "/");
29617
29603
  const candidate = {
29618
29604
  schema: CANDIDATE_SCHEMA,
@@ -29638,7 +29624,7 @@ function buildImprovementReport(records, options = {}) {
29638
29624
  mkdirSync8(candidatesDir, { recursive: true });
29639
29625
  }
29640
29626
  writeFileSync7(diffFilePath, diff, "utf8");
29641
- const jsonFilePath = join18(candidatesDir, `${group.candidateId}.json`);
29627
+ const jsonFilePath = join17(candidatesDir, `${group.candidateId}.json`);
29642
29628
  writeFileSync7(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
29643
29629
  }
29644
29630
  candidates.push(candidate);
@@ -29654,7 +29640,7 @@ function buildImprovementReport(records, options = {}) {
29654
29640
  }
29655
29641
  function writeImprovementReport(improvementsDir, report, dryRun = false) {
29656
29642
  const stamp = report.createdAt.replace(/[:.]/g, "-");
29657
- const path = join18(improvementsDir, `${stamp}.json`);
29643
+ const path = join17(improvementsDir, `${stamp}.json`);
29658
29644
  if (!dryRun) {
29659
29645
  mkdirSync8(improvementsDir, { recursive: true });
29660
29646
  writeFileSync7(path, `${JSON.stringify(report, null, 2)}
@@ -30158,8 +30144,8 @@ Instructions for Operator:
30158
30144
 
30159
30145
  // plugins/kxm/src/modes.ts
30160
30146
  var import_yaml6 = __toESM(require_dist(), 1);
30161
- import { existsSync as existsSync15, readFileSync as readFileSync13 } from "node:fs";
30162
- import { join as join19 } from "node:path";
30147
+ import { existsSync as existsSync15, readFileSync as readFileSync12 } from "node:fs";
30148
+ import { join as join18 } from "node:path";
30163
30149
  var DEFAULT_MODES_CONFIG = Object.freeze({
30164
30150
  schema: "kxm.modes.v1",
30165
30151
  majorModes: {
@@ -30222,12 +30208,12 @@ function loadModesConfig(projectRoot) {
30222
30208
  if (!projectRoot) {
30223
30209
  return DEFAULT_MODES_CONFIG;
30224
30210
  }
30225
- const modesPath = join19(projectRoot, ".kxm", "modes.yaml");
30211
+ const modesPath = join18(projectRoot, ".kxm", "modes.yaml");
30226
30212
  if (!existsSync15(modesPath)) {
30227
30213
  return DEFAULT_MODES_CONFIG;
30228
30214
  }
30229
30215
  try {
30230
- const raw = readFileSync13(modesPath, "utf8");
30216
+ const raw = readFileSync12(modesPath, "utf8");
30231
30217
  const parsed = (0, import_yaml6.parse)(raw);
30232
30218
  if (parsed && parsed.schema === "kxm.modes.v1" && parsed.majorModes) {
30233
30219
  return {
@@ -30313,11 +30299,11 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
30313
30299
  estimatedTokens: estimateTokens(baseSystemPromptChars)
30314
30300
  });
30315
30301
  for (const relPath of resolved.contextFiles) {
30316
- const fullPath = join19(projectRoot, relPath);
30302
+ const fullPath = join18(projectRoot, relPath);
30317
30303
  let chars = 0;
30318
30304
  if (existsSync15(fullPath)) {
30319
30305
  try {
30320
- chars = readFileSync13(fullPath, "utf8").length;
30306
+ chars = readFileSync12(fullPath, "utf8").length;
30321
30307
  } catch {
30322
30308
  chars = 0;
30323
30309
  }
@@ -30449,9 +30435,9 @@ ${divider}
30449
30435
 
30450
30436
  // plugins/kxm/src/ssh-remote.ts
30451
30437
  import { spawnSync as spawnSync3 } from "node:child_process";
30452
- import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync14, readdirSync as readdirSync5, rmSync as rmSync4, statSync as statSync4 } from "node:fs";
30438
+ import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync13, readdirSync as readdirSync5, rmSync as rmSync4, statSync as statSync4 } from "node:fs";
30453
30439
  import { homedir as homedir4 } from "node:os";
30454
- import { join as join20, resolve as resolve9 } from "node:path";
30440
+ import { join as join19, resolve as resolve9 } from "node:path";
30455
30441
  var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
30456
30442
  var MAX_SSH_OUTPUT_LINES = 2e3;
30457
30443
  var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
@@ -30477,12 +30463,12 @@ function truncateSshOutput(raw) {
30477
30463
  return { text, truncated };
30478
30464
  }
30479
30465
  function parseSshConfig(configPath) {
30480
- const targetPath = configPath ?? join20(homedir4(), ".ssh", "config");
30466
+ const targetPath = configPath ?? join19(homedir4(), ".ssh", "config");
30481
30467
  if (!existsSync16(targetPath)) {
30482
30468
  return [];
30483
30469
  }
30484
30470
  try {
30485
- const content = readFileSync14(targetPath, "utf-8");
30471
+ const content = readFileSync13(targetPath, "utf-8");
30486
30472
  const lines = content.split("\n");
30487
30473
  const hosts = [];
30488
30474
  let currentHosts = [];
@@ -30567,7 +30553,7 @@ function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
30567
30553
  }
30568
30554
  function buildSshArgs(options) {
30569
30555
  const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
30570
- const controlPath = join20(socketDir, "%C");
30556
+ const controlPath = join19(socketDir, "%C");
30571
30557
  const persist2 = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
30572
30558
  const args = [
30573
30559
  "-o",
@@ -30592,7 +30578,7 @@ function buildSshArgs(options) {
30592
30578
  }
30593
30579
  function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync3) {
30594
30580
  const resolvedDir = ensureSocketDir(socketDir);
30595
- const controlPath = join20(resolvedDir, "%C");
30581
+ const controlPath = join19(resolvedDir, "%C");
30596
30582
  try {
30597
30583
  const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
30598
30584
  encoding: "utf-8"
@@ -30604,7 +30590,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
30604
30590
  }
30605
30591
  function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync3) {
30606
30592
  const resolvedDir = ensureSocketDir(socketDir);
30607
- const controlPath = join20(resolvedDir, "%C");
30593
+ const controlPath = join19(resolvedDir, "%C");
30608
30594
  try {
30609
30595
  const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
30610
30596
  encoding: "utf-8"
@@ -30620,7 +30606,7 @@ function pruneSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
30620
30606
  try {
30621
30607
  const entries = readdirSync5(resolvedDir);
30622
30608
  for (const entry of entries) {
30623
- const fullPath = join20(resolvedDir, entry);
30609
+ const fullPath = join19(resolvedDir, entry);
30624
30610
  try {
30625
30611
  const stat = statSync4(fullPath);
30626
30612
  if (stat.isSocket()) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plugin",
3
- "version": "0.7.76",
3
+ "version": "0.7.77",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
@@ -8,7 +8,7 @@ import { AGENT_COMMANDS_MAP, enforceToolPolicy, getMcpTools, reconcileInbox } fr
8
8
  import { deliverInboxNotification } from "./inbox.ts";
9
9
  import type { HubEvent, MessageRecord } from "./protocol.ts";
10
10
 
11
- const VERSION = "0.7.76";
11
+ const VERSION = "0.7.77";
12
12
  const inbox = new Map<string, MessageRecord>();
13
13
  const notifiedInbox = new Set<string>();
14
14
  let meshClient: HubClient | undefined;
@@ -436,7 +436,11 @@ export async function syncKxmOutbox(
436
436
  function runtimeHubClientFor(context: KxmRuntimeContext, env: NodeJS.ProcessEnv): RuntimeHubClient | undefined {
437
437
  const serverUrl = env.KXM_SERVER_URL?.trim() || readHubBinding(env)?.url;
438
438
  if (!serverUrl) return undefined;
439
- const project = defaultProjectName(context.projectRoot, env);
439
+ // Use the context's actual projectId — the same identity sync events carry — so the
440
+ // ops snapshot can join runs to their home Runtime. defaultProjectName() resolves to
441
+ // the npm package name (e.g. "@kontextmind/kxm"), which never matches project.yaml's
442
+ // prj_* id, leaving presence orphaned from the runs it owns.
443
+ const project = context.projectId;
440
444
  const authToken = resolveClientHubAuthToken(env, project);
441
445
  return new RuntimeHubClient({
442
446
  serverUrl,
@@ -495,7 +499,7 @@ async function startKxmRuntimeSupervisorInner(
495
499
  // BEFORE any event can be appended — so the very first outbox row is
496
500
  // already scrubbed. Registering on the sync tick leaves a window where
497
501
  // appended events retain credentials.
498
- const hubToken = resolveClientHubAuthToken(process.env, defaultProjectName(context.projectRoot, process.env));
502
+ const hubToken = resolveClientHubAuthToken(process.env, context.projectId);
499
503
  if (hubToken) context.eventStore.syncRedactor.register(hubToken);
500
504
  for (const key of Object.keys(process.env)) {
501
505
  if ((key.startsWith("KXM_") && (key.endsWith("_TOKEN") || key.endsWith("_KEY"))) || key.endsWith("_API_KEY") || key.endsWith("_SECRET")) {