@kontextmind/kxm 0.7.79 → 0.7.80

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.79",
14
+ "version": "0.7.80",
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.79",
3
+ "version": "0.7.80",
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.79",
5
+ "version": "0.7.80",
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",
@@ -23980,20 +23980,30 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
23980
23980
  integrity: "ok"
23981
23981
  };
23982
23982
  }
23983
+ var KXM_BACKUP_CEILINGS = {
23984
+ "hub-store": 5,
23985
+ registry: 1,
23986
+ "binding-store": 1,
23987
+ events: 7
23988
+ };
23989
+ function kxmBackupCeiling(storeId) {
23990
+ if (storeId.startsWith("events:")) return KXM_BACKUP_CEILINGS.events;
23991
+ return KXM_BACKUP_CEILINGS[storeId] ?? KXM_BACKUP_CEILINGS["hub-store"];
23992
+ }
23983
23993
  function discoverProjectStores(projectRoot, options = {}) {
23984
23994
  const root = resolve5(projectRoot);
23985
23995
  const stores = [];
23986
23996
  const hubPath = options.hubDataPath ? resolve5(options.hubDataPath) : join8(root, ".kxm", "state", "kxm.db");
23987
23997
  if (existsSync8(hubPath)) {
23988
- stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: 5 });
23998
+ stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: kxmBackupCeiling("hub-store") });
23989
23999
  }
23990
24000
  const registryPath = join8(root, ".kxm", "runtime", "registry.db");
23991
24001
  if (existsSync8(registryPath)) {
23992
- stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: 1 });
24002
+ stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: kxmBackupCeiling("registry") });
23993
24003
  }
23994
24004
  const bindingsPath = join8(root, ".kxm", "runtime", "bindings.db");
23995
24005
  if (existsSync8(bindingsPath)) {
23996
- stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: 1 });
24006
+ stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: kxmBackupCeiling("binding-store") });
23997
24007
  }
23998
24008
  const eventsDir = join8(root, ".kxm", "runtime", "events");
23999
24009
  if (existsSync8(eventsDir)) {
@@ -24004,7 +24014,7 @@ function discoverProjectStores(projectRoot, options = {}) {
24004
24014
  stores.push({
24005
24015
  storeId: `events:${key}`,
24006
24016
  sourcePath: join8(eventsDir, entry.name),
24007
- maxSupportedVersion: 6
24017
+ maxSupportedVersion: kxmBackupCeiling(`events:${key}`)
24008
24018
  });
24009
24019
  }
24010
24020
  }
@@ -24091,12 +24101,7 @@ function restoreBackup(manifestPathOrDir, options = {}) {
24091
24101
  `backup file ${store.backupFile} sha256 ${actualSha256} does not match manifest hash ${store.sha256}`
24092
24102
  );
24093
24103
  }
24094
- let maxSupported = 5;
24095
- if (store.storeId === "registry" || store.storeId === "binding-store") {
24096
- maxSupported = 1;
24097
- } else if (store.storeId.startsWith("events:")) {
24098
- maxSupported = 7;
24099
- }
24104
+ const maxSupported = kxmBackupCeiling(store.storeId);
24100
24105
  let targetPath = store.sourcePath;
24101
24106
  if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
24102
24107
  const rel = targetPath.slice(manifest.projectRoot.length).replace(/^[\\/]+/, "");
@@ -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.79";
17185
+ var VERSION = "0.7.80";
17186
17186
  var inbox = /* @__PURE__ */ new Map();
17187
17187
  var notifiedInbox = /* @__PURE__ */ new Set();
17188
17188
  var meshClient;
@@ -18326,20 +18326,30 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
18326
18326
  integrity: "ok"
18327
18327
  };
18328
18328
  }
18329
+ var KXM_BACKUP_CEILINGS = {
18330
+ "hub-store": 5,
18331
+ registry: 1,
18332
+ "binding-store": 1,
18333
+ events: 7
18334
+ };
18335
+ function kxmBackupCeiling(storeId) {
18336
+ if (storeId.startsWith("events:")) return KXM_BACKUP_CEILINGS.events;
18337
+ return KXM_BACKUP_CEILINGS[storeId] ?? KXM_BACKUP_CEILINGS["hub-store"];
18338
+ }
18329
18339
  function discoverProjectStores(projectRoot, options = {}) {
18330
18340
  const root = resolve3(projectRoot);
18331
18341
  const stores = [];
18332
18342
  const hubPath = options.hubDataPath ? resolve3(options.hubDataPath) : join4(root, ".kxm", "state", "kxm.db");
18333
18343
  if (existsSync4(hubPath)) {
18334
- stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: 5 });
18344
+ stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: kxmBackupCeiling("hub-store") });
18335
18345
  }
18336
18346
  const registryPath = join4(root, ".kxm", "runtime", "registry.db");
18337
18347
  if (existsSync4(registryPath)) {
18338
- stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: 1 });
18348
+ stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: kxmBackupCeiling("registry") });
18339
18349
  }
18340
18350
  const bindingsPath = join4(root, ".kxm", "runtime", "bindings.db");
18341
18351
  if (existsSync4(bindingsPath)) {
18342
- stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: 1 });
18352
+ stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: kxmBackupCeiling("binding-store") });
18343
18353
  }
18344
18354
  const eventsDir = join4(root, ".kxm", "runtime", "events");
18345
18355
  if (existsSync4(eventsDir)) {
@@ -18350,7 +18360,7 @@ function discoverProjectStores(projectRoot, options = {}) {
18350
18360
  stores.push({
18351
18361
  storeId: `events:${key}`,
18352
18362
  sourcePath: join4(eventsDir, entry.name),
18353
- maxSupportedVersion: 6
18363
+ maxSupportedVersion: kxmBackupCeiling(`events:${key}`)
18354
18364
  });
18355
18365
  }
18356
18366
  }
@@ -18437,12 +18447,7 @@ function restoreBackup(manifestPathOrDir, options = {}) {
18437
18447
  `backup file ${store.backupFile} sha256 ${actualSha256} does not match manifest hash ${store.sha256}`
18438
18448
  );
18439
18449
  }
18440
- let maxSupported = 5;
18441
- if (store.storeId === "registry" || store.storeId === "binding-store") {
18442
- maxSupported = 1;
18443
- } else if (store.storeId.startsWith("events:")) {
18444
- maxSupported = 7;
18445
- }
18450
+ const maxSupported = kxmBackupCeiling(store.storeId);
18446
18451
  let targetPath = store.sourcePath;
18447
18452
  if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
18448
18453
  const rel = targetPath.slice(manifest.projectRoot.length).replace(/^[\\/]+/, "");
@@ -31288,6 +31293,7 @@ export {
31288
31293
  IMPROVEMENT_REPORT_SCHEMA,
31289
31294
  IMPROVEMENT_REPORT_V1_SCHEMA,
31290
31295
  KXM_ABSENT_MEMORY_REVISION,
31296
+ KXM_BACKUP_CEILINGS,
31291
31297
  KXM_DRIVE_RECEIPT_SCHEMA,
31292
31298
  KXM_EVENT_STORE_SCHEMA_VERSION,
31293
31299
  KXM_EVENT_STORE_TABLE_NAMES,
@@ -31366,6 +31372,7 @@ export {
31366
31372
  isKxmRuntimeContextClosed,
31367
31373
  isTransactionContention,
31368
31374
  isWindowsHarnessShim,
31375
+ kxmBackupCeiling,
31369
31376
  kxmDeclaredExecutorIds,
31370
31377
  kxmDeclaredRepositoryIds,
31371
31378
  kxmEventBase,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plugin",
3
- "version": "0.7.79",
3
+ "version": "0.7.80",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
@@ -585,25 +585,50 @@ export function restoreDatabaseFile(
585
585
  };
586
586
  }
587
587
 
588
+ /**
589
+ * Per-store restore ceilings, held in **one** table read by both backup discovery
590
+ * and restore. Two copies of these numbers drifted once already: a schema bump
591
+ * raised the restore ceiling and left the discovery ceiling behind, and nothing
592
+ * caught it because nothing read the stale copy.
593
+ *
594
+ * Each value MUST track the version its store declares — `HUB_STORE_SCHEMA_VERSION`
595
+ * in `store.ts`, `KXM_REGISTRY_SCHEMA_VERSION` and `KXM_EVENT_STORE_SCHEMA_VERSION`
596
+ * in `runtime-store.ts`. Those modules import this one, so the constants cannot be
597
+ * named here; the gate is the named test
598
+ * `restore ceilings track every store's own schema version` in
599
+ * `test/core/e6-backup-restore-migrations.test.ts`, which is what the deleted
600
+ * "must track" comments were only pretending to be.
601
+ */
602
+ export const KXM_BACKUP_CEILINGS = {
603
+ "hub-store": 5,
604
+ registry: 1,
605
+ "binding-store": 1,
606
+ events: 7,
607
+ } as const;
608
+
609
+ export function kxmBackupCeiling(storeId: string): number {
610
+ if (storeId.startsWith("events:")) return KXM_BACKUP_CEILINGS.events;
611
+ // An id this build does not know keeps the ceiling restore has always defaulted to.
612
+ return KXM_BACKUP_CEILINGS[storeId as keyof typeof KXM_BACKUP_CEILINGS] ?? KXM_BACKUP_CEILINGS["hub-store"];
613
+ }
614
+
588
615
  export function discoverProjectStores(projectRoot: string, options: { hubDataPath?: string } = {}): Array<{ storeId: string; sourcePath: string; maxSupportedVersion: number }> {
589
616
  const root = resolve(projectRoot);
590
617
  const stores: Array<{ storeId: string; sourcePath: string; maxSupportedVersion: number }> = [];
591
618
 
592
619
  const hubPath = options.hubDataPath ? resolve(options.hubDataPath) : join(root, ".kxm", "state", "kxm.db");
593
620
  if (existsSync(hubPath)) {
594
- // Must track HUB_STORE_SCHEMA_VERSION in store.ts: the hub's own fresh backup is
595
- // restored through this ceiling, so a bump left behind here refuses it.
596
- stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: 5 });
621
+ stores.push({ storeId: "hub-store", sourcePath: hubPath, maxSupportedVersion: kxmBackupCeiling("hub-store") });
597
622
  }
598
623
 
599
624
  const registryPath = join(root, ".kxm", "runtime", "registry.db");
600
625
  if (existsSync(registryPath)) {
601
- stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: 1 });
626
+ stores.push({ storeId: "registry", sourcePath: registryPath, maxSupportedVersion: kxmBackupCeiling("registry") });
602
627
  }
603
628
 
604
629
  const bindingsPath = join(root, ".kxm", "runtime", "bindings.db");
605
630
  if (existsSync(bindingsPath)) {
606
- stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: 1 });
631
+ stores.push({ storeId: "binding-store", sourcePath: bindingsPath, maxSupportedVersion: kxmBackupCeiling("binding-store") });
607
632
  }
608
633
 
609
634
  const eventsDir = join(root, ".kxm", "runtime", "events");
@@ -615,7 +640,7 @@ export function discoverProjectStores(projectRoot: string, options: { hubDataPat
615
640
  stores.push({
616
641
  storeId: `events:${key}`,
617
642
  sourcePath: join(eventsDir, entry.name),
618
- maxSupportedVersion: 6,
643
+ maxSupportedVersion: kxmBackupCeiling(`events:${key}`),
619
644
  });
620
645
  }
621
646
  }
@@ -729,17 +754,7 @@ export function restoreBackup(
729
754
  );
730
755
  }
731
756
 
732
- // The hub-store ceiling. Must track HUB_STORE_SCHEMA_VERSION in store.ts for the
733
- // same reason as the events ceiling below.
734
- let maxSupported = 5;
735
- if (store.storeId === "registry" || store.storeId === "binding-store") {
736
- maxSupported = 1;
737
- } else if (store.storeId.startsWith("events:")) {
738
- // Must track KXM_EVENT_STORE_SCHEMA_VERSION in runtime-store.ts. The pin is
739
- // the e6 backup/restore round-trip test: bump one without the other and it
740
- // refuses its own fresh backup.
741
- maxSupported = 7;
742
- }
757
+ const maxSupported = kxmBackupCeiling(store.storeId);
743
758
 
744
759
  let targetPath = store.sourcePath;
745
760
  if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
@@ -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.79";
11
+ const VERSION = "0.7.80";
12
12
  const inbox = new Map<string, MessageRecord>();
13
13
  const notifiedInbox = new Set<string>();
14
14
  let meshClient: HubClient | undefined;