@kontextmind/kxm 0.7.52 → 0.7.54

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.
@@ -17121,7 +17121,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
17121
17121
  }
17122
17122
 
17123
17123
  // plugins/kxm/src/mcp-server.ts
17124
- var VERSION = "0.7.52";
17124
+ var VERSION = "0.7.54";
17125
17125
  var inbox = /* @__PURE__ */ new Map();
17126
17126
  var notifiedInbox = /* @__PURE__ */ new Set();
17127
17127
  var meshClient;
@@ -16256,9 +16256,6 @@ var KxmSchemaRegistry = class {
16256
16256
  localBindingsValidator;
16257
16257
  templateProvenanceValidator;
16258
16258
  initOperationValidator;
16259
- migrationPlanValidator;
16260
- migrationDecisionValidator;
16261
- migrationReceiptValidator;
16262
16259
  permissionDiffValidator;
16263
16260
  runEventValidator;
16264
16261
  driveReceiptValidator;
@@ -16275,9 +16272,6 @@ var KxmSchemaRegistry = class {
16275
16272
  const localBindingsFile = "local-repository-bindings.schema.json";
16276
16273
  const templateProvenanceFile = "template-provenance.schema.json";
16277
16274
  const initOperationFile = "init-operation.schema.json";
16278
- const migrationPlanFile = "migration-plan.schema.json";
16279
- const migrationDecisionFile = "migration-decision.schema.json";
16280
- const migrationReceiptFile = "migration-receipt.schema.json";
16281
16275
  const permissionDiffFile = "permission-diff.schema.json";
16282
16276
  const runEventFile = "run-event.schema.json";
16283
16277
  const driveReceiptFile = "drive-receipt.schema.json";
@@ -16286,9 +16280,6 @@ var KxmSchemaRegistry = class {
16286
16280
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, localBindingsFile)));
16287
16281
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, templateProvenanceFile)));
16288
16282
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, initOperationFile)));
16289
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationPlanFile)));
16290
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationDecisionFile)));
16291
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationReceiptFile)));
16292
16283
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, permissionDiffFile)));
16293
16284
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, runEventFile)));
16294
16285
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, driveReceiptFile)));
@@ -16302,9 +16293,6 @@ var KxmSchemaRegistry = class {
16302
16293
  const localBindingsValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${localBindingsFile}`);
16303
16294
  const templateProvenanceValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${templateProvenanceFile}`);
16304
16295
  const initOperationValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${initOperationFile}`);
16305
- const migrationPlanValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${migrationPlanFile}`);
16306
- const migrationDecisionValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${migrationDecisionFile}`);
16307
- const migrationReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${migrationReceiptFile}`);
16308
16296
  const permissionDiffValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${permissionDiffFile}`);
16309
16297
  const runEventValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${runEventFile}`);
16310
16298
  const driveReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${driveReceiptFile}`);
@@ -16313,9 +16301,6 @@ var KxmSchemaRegistry = class {
16313
16301
  if (!localBindingsValidator) throw new Error(`schema did not compile: ${localBindingsFile}`);
16314
16302
  if (!templateProvenanceValidator) throw new Error(`schema did not compile: ${templateProvenanceFile}`);
16315
16303
  if (!initOperationValidator) throw new Error(`schema did not compile: ${initOperationFile}`);
16316
- if (!migrationPlanValidator) throw new Error(`schema did not compile: ${migrationPlanFile}`);
16317
- if (!migrationDecisionValidator) throw new Error(`schema did not compile: ${migrationDecisionFile}`);
16318
- if (!migrationReceiptValidator) throw new Error(`schema did not compile: ${migrationReceiptFile}`);
16319
16304
  if (!permissionDiffValidator) throw new Error(`schema did not compile: ${permissionDiffFile}`);
16320
16305
  if (!runEventValidator) throw new Error(`schema did not compile: ${runEventFile}`);
16321
16306
  if (!driveReceiptValidator) throw new Error(`schema did not compile: ${driveReceiptFile}`);
@@ -16324,9 +16309,6 @@ var KxmSchemaRegistry = class {
16324
16309
  this.localBindingsValidator = localBindingsValidator;
16325
16310
  this.templateProvenanceValidator = templateProvenanceValidator;
16326
16311
  this.initOperationValidator = initOperationValidator;
16327
- this.migrationPlanValidator = migrationPlanValidator;
16328
- this.migrationDecisionValidator = migrationDecisionValidator;
16329
- this.migrationReceiptValidator = migrationReceiptValidator;
16330
16312
  this.permissionDiffValidator = permissionDiffValidator;
16331
16313
  this.runEventValidator = runEventValidator;
16332
16314
  this.driveReceiptValidator = driveReceiptValidator;
@@ -16352,15 +16334,6 @@ var KxmSchemaRegistry = class {
16352
16334
  validateInitOperation(value, file) {
16353
16335
  return this.validateAuxiliary(value, file, "kxm.init-operation.v1", this.initOperationValidator);
16354
16336
  }
16355
- validateMigrationPlan(value, file) {
16356
- return this.validateAuxiliary(value, file, "kxm.migration-plan.v1", this.migrationPlanValidator);
16357
- }
16358
- validateMigrationDecision(value, file) {
16359
- return this.validateAuxiliary(value, file, "kxm.migration-decision.v1", this.migrationDecisionValidator);
16360
- }
16361
- validateMigrationReceipt(value, file) {
16362
- return this.validateAuxiliary(value, file, "kxm.migration-receipt.v1", this.migrationReceiptValidator);
16363
- }
16364
16337
  validatePermissionDiff(value, file) {
16365
16338
  return this.validateAuxiliary(value, file, "kxm.permission-diff.v1", this.permissionDiffValidator);
16366
16339
  }
@@ -17178,11 +17151,14 @@ function assertNoRegisteredGates(options) {
17178
17151
  function loadKxmProject(projectRoot, options = {}) {
17179
17152
  assertNoRegisteredGates(options);
17180
17153
  const root = resolve(projectRoot);
17181
- let migrationReceipt;
17182
- if (legacyConfigFilesAt(root).length > 0 && options.allowUnreceiptedLegacyConfig !== true) {
17183
- const receiptCheck = readKxmMigrationReceipt(root, options);
17184
- if (receiptCheck.issues.length > 0) throw new KxmConfigError(receiptCheck.issues);
17185
- migrationReceipt = receiptCheck.receipt;
17154
+ const legacyPresent = legacyConfigFilesAt(root);
17155
+ if (legacyPresent.length > 0) {
17156
+ throw new KxmConfigError(legacyPresent.map((file) => issue2(
17157
+ "semantic",
17158
+ "legacy_state_unsupported",
17159
+ file,
17160
+ "legacy JSON configuration is present and this build does not migrate it: delete these files once their YAML replacements exist in .kxm/, or initialise a fresh project"
17161
+ )));
17186
17162
  }
17187
17163
  const registry = new KxmSchemaRegistry(options.schemasDir);
17188
17164
  const project = readResource(registry, root, join2(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
@@ -17195,9 +17171,6 @@ function loadKxmProject(projectRoot, options = {}) {
17195
17171
  earlyIssues.push(issue2("semantic", "template_provenance_project_mismatch", ".kxm/template-provenance.yaml", "template provenance belongs to a different project identity"));
17196
17172
  }
17197
17173
  }
17198
- if (migrationReceipt && stringValue(migrationReceipt.projectId) !== stringValue(project.value.id)) {
17199
- earlyIssues.push(issue2("semantic", "migration_project_mismatch", KXM_MIGRATION_RECEIPT_PATH, "migration receipt belongs to a different project identity"));
17200
- }
17201
17174
  const declaredRepositoryIds = new Set(valuesOf(project.value, "repositories").map((candidate) => stringValue(objectValue(candidate)?.id)).filter((candidate) => candidate !== void 0));
17202
17175
  for (const repositoryId of Object.keys(options.repositoryBindings ?? {}).sort(compareCodeUnits3)) {
17203
17176
  if (!resourceIdentifier(repositoryId)) {
@@ -17274,6 +17247,15 @@ function loadKxmProject(projectRoot, options = {}) {
17274
17247
  continue;
17275
17248
  }
17276
17249
  }
17250
+ const memberLegacy = binding === root ? [] : legacyConfigFilesAt(binding);
17251
+ if (memberLegacy.length > 0) {
17252
+ throw new KxmConfigError(memberLegacy.map((file) => issue2(
17253
+ "semantic",
17254
+ "legacy_state_unsupported",
17255
+ `${repositoryId}/${file}`,
17256
+ `repository ${repositoryId} holds legacy JSON configuration and this build does not migrate it: delete those files once their YAML replacements exist, or bind a clean worktree`
17257
+ )));
17258
+ }
17277
17259
  const foldedBinding = canonicalHostPath(binding).toLocaleLowerCase("en-US");
17278
17260
  const priorBinding = seenBindings.get(foldedBinding);
17279
17261
  if (priorBinding && priorBinding !== repositoryId) {
@@ -17327,12 +17309,10 @@ function loadKxmProject(projectRoot, options = {}) {
17327
17309
  environments,
17328
17310
  ...gateRegistry ? { gateRegistry } : {},
17329
17311
  ...templateProvenance === void 0 ? {} : { templateProvenance },
17330
- ...migrationReceipt === void 0 ? {} : { migrationReceipt },
17331
17312
  resources,
17332
17313
  configRevision: bundleRevision(resources)
17333
17314
  };
17334
17315
  }
17335
- var KXM_MIGRATION_RECEIPT_PATH = ".kxm/migration-receipt.yaml";
17336
17316
  var LEGACY_CONFIG_FILES = [".kxm/config/agents.json", ".kxm/config/gates.json"];
17337
17317
  function legacyConfigFilesAt(root) {
17338
17318
  const files = [];
@@ -17358,66 +17338,6 @@ function legacyConfigFilesAt(root) {
17358
17338
  }
17359
17339
  return files;
17360
17340
  }
17361
- function hashFileRecord(root, relativePath) {
17362
- const absolute = join2(root, ...relativePath.split("/"));
17363
- if (!existsSync3(absolute)) return void 0;
17364
- const bytes = readFileSync(absolute);
17365
- return {
17366
- path: relativePath,
17367
- sha256: `sha256:${createHash2("sha256").update(bytes).digest("hex")}`,
17368
- bytes: bytes.byteLength
17369
- };
17370
- }
17371
- function migrationReceiptSelfHash(receipt) {
17372
- const { receiptSha256: _ignored, ...unsigned } = receipt;
17373
- return `sha256:${createHash2("sha256").update(kxmCanonicalJson(unsigned), "utf8").digest("hex")}`;
17374
- }
17375
- function readKxmMigrationReceipt(root, options = {}) {
17376
- const receiptPath = join2(root, ...KXM_MIGRATION_RECEIPT_PATH.split("/"));
17377
- const legacyFiles = legacyConfigFilesAt(root);
17378
- if (!existsSync3(receiptPath)) {
17379
- return {
17380
- issues: legacyFiles.map((file) => issue2("semantic", "legacy_kxm_conflict", file, "legacy and KXM configuration cannot coexist before an accepted migration receipt"))
17381
- };
17382
- }
17383
- const receiptStat = lstatSync(receiptPath);
17384
- if (receiptStat.isSymbolicLink() || !receiptStat.isFile()) {
17385
- return { issues: [issue2("path", "migration_receipt_invalid", KXM_MIGRATION_RECEIPT_PATH, "migration receipt must be a regular file, not a link")] };
17386
- }
17387
- let receipt;
17388
- try {
17389
- receipt = parseRestrictedYaml2(readFileSync(receiptPath), KXM_MIGRATION_RECEIPT_PATH);
17390
- } catch (error) {
17391
- if (error instanceof KxmConfigError) return { issues: [...error.issues] };
17392
- throw error;
17393
- }
17394
- const registry = new KxmSchemaRegistry(options.schemasDir);
17395
- const schemaIssues = registry.validateMigrationReceipt(receipt, KXM_MIGRATION_RECEIPT_PATH);
17396
- if (schemaIssues.length > 0) return { issues: schemaIssues };
17397
- if (receipt.receiptSha256 !== migrationReceiptSelfHash(receipt)) {
17398
- return { issues: [issue2("semantic", "migration_receipt_hash_mismatch", KXM_MIGRATION_RECEIPT_PATH, "receipt self-hash does not match its content")] };
17399
- }
17400
- const sources = (Array.isArray(receipt.sources) ? receipt.sources : []).map((candidate) => candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate.path : void 0).filter((candidate) => typeof candidate === "string").sort(compareCodeUnits3);
17401
- const issues = [];
17402
- const declared = new Set(sources);
17403
- for (const file of legacyFiles) {
17404
- if (!declared.has(file)) {
17405
- issues.push(issue2("semantic", "migration_source_unmigrated", file, "legacy configuration file is not covered by the migration receipt"));
17406
- continue;
17407
- }
17408
- const record2 = (Array.isArray(receipt.sources) ? receipt.sources : []).map((candidate) => candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : void 0).find((candidate) => candidate?.path === file);
17409
- const current = hashFileRecord(root, file);
17410
- if (!current || current.sha256 !== record2?.sha256 || current.bytes !== record2?.bytes) {
17411
- issues.push(issue2("semantic", "migration_source_changed", file, "legacy configuration changed after the migration receipt was issued"));
17412
- }
17413
- }
17414
- for (const file of sources) {
17415
- if (!legacyFiles.includes(file)) {
17416
- issues.push(issue2("semantic", "migration_source_missing", file, "receipt covers a legacy configuration file that no longer exists"));
17417
- }
17418
- }
17419
- return issues.length > 0 ? { issues } : { receipt, issues: [] };
17420
- }
17421
17341
 
17422
17342
  // plugins/kxm/src/runtime-store.ts
17423
17343
  import { createHash as createHash3, randomUUID } from "node:crypto";
@@ -17612,20 +17532,11 @@ function openDatabase(file, description, spec) {
17612
17532
  database.exec(spec.schema);
17613
17533
  database.exec(`PRAGMA user_version = ${spec.version}`);
17614
17534
  } else if (version < spec.version) {
17615
- let currentVersion = version;
17616
- while (currentVersion < spec.version) {
17617
- const step = spec.migrations?.find((m) => m.fromVersion === currentVersion);
17618
- if (!step) {
17619
- throw databaseError(
17620
- "runtime_schema_outdated",
17621
- file,
17622
- `${description} schema version ${version} is older than ${spec.version}; no migration lane, backup and restore remain E6`
17623
- );
17624
- }
17625
- step.migrate(database);
17626
- currentVersion = step.toVersion;
17627
- database.exec(`PRAGMA user_version = ${currentVersion}`);
17628
- }
17535
+ throw databaseError(
17536
+ "runtime_schema_outdated",
17537
+ file,
17538
+ `${description} is schema version ${version}; this build requires ${spec.version}. Delete the state file to start fresh and let its owning process recreate it (\`kxm hub start\` for hub state, the Runtime for registry/event stores); \`kxm init\` is project-only and rebuilds no database \u2014 upgrading old state in place is deliberately unsupported`
17539
+ );
17629
17540
  }
17630
17541
  if (spec.tables) {
17631
17542
  verifyExpectedTables(database, file, description, spec.tables);
@@ -18270,71 +18181,6 @@ CREATE TABLE project_controls (
18270
18181
  record TEXT NOT NULL
18271
18182
  ) STRICT;
18272
18183
  `;
18273
- var COORDINATOR_INTAKE_DDL = `
18274
- CREATE TABLE IF NOT EXISTS coordinators (
18275
- coordinator_id TEXT PRIMARY KEY,
18276
- project_id TEXT NOT NULL,
18277
- role TEXT NOT NULL,
18278
- channel TEXT NOT NULL,
18279
- ceiling_hash TEXT NOT NULL,
18280
- config_revision TEXT NOT NULL,
18281
- bound_at TEXT NOT NULL,
18282
- schema TEXT NOT NULL,
18283
- record TEXT NOT NULL
18284
- ) STRICT;
18285
- CREATE UNIQUE INDEX IF NOT EXISTS coordinators_slot ON coordinators(project_id, role, channel);
18286
- CREATE TABLE IF NOT EXISTS intake_messages (
18287
- message_id TEXT PRIMARY KEY,
18288
- project_id TEXT NOT NULL,
18289
- coordinator_id TEXT NOT NULL,
18290
- idempotency_key TEXT NOT NULL,
18291
- content_hash TEXT NOT NULL,
18292
- received_at TEXT NOT NULL,
18293
- dispatch_state TEXT NOT NULL CHECK (dispatch_state IN ('ready','held_paused','admitted','refused')),
18294
- schema TEXT NOT NULL,
18295
- record TEXT NOT NULL
18296
- ) STRICT;
18297
- CREATE UNIQUE INDEX IF NOT EXISTS intake_idempotency ON intake_messages(project_id, coordinator_id, idempotency_key);
18298
- CREATE INDEX IF NOT EXISTS intake_dispatch ON intake_messages(project_id, dispatch_state, received_at, message_id);
18299
- CREATE TABLE IF NOT EXISTS project_controls (
18300
- project_id TEXT PRIMARY KEY,
18301
- paused INTEGER NOT NULL CHECK (paused IN (0, 1)),
18302
- reason TEXT,
18303
- updated_at TEXT NOT NULL,
18304
- actor TEXT NOT NULL,
18305
- schema TEXT NOT NULL,
18306
- record TEXT NOT NULL
18307
- ) STRICT;
18308
- `;
18309
- var DRIVE_RECEIPTS_DDL = `
18310
- CREATE TABLE IF NOT EXISTS drive_receipts (
18311
- drive_id TEXT PRIMARY KEY,
18312
- run_id TEXT NOT NULL,
18313
- project_id TEXT NOT NULL,
18314
- opened_sequence INTEGER NOT NULL,
18315
- last_sequence INTEGER NOT NULL,
18316
- closed_at TEXT NOT NULL,
18317
- schema TEXT NOT NULL,
18318
- receipt TEXT NOT NULL
18319
- ) STRICT;
18320
- CREATE INDEX IF NOT EXISTS drive_receipts_run ON drive_receipts(run_id);
18321
- `;
18322
- var EVENT_STORE_MIGRATIONS = [
18323
- {
18324
- fromVersion: 3,
18325
- toVersion: 4,
18326
- migrate(database) {
18327
- database.exec(DRIVE_RECEIPTS_DDL);
18328
- }
18329
- },
18330
- {
18331
- fromVersion: 4,
18332
- toVersion: 5,
18333
- migrate(database) {
18334
- database.exec(COORDINATOR_INTAKE_DDL);
18335
- }
18336
- }
18337
- ];
18338
18184
  var KxmRunEventStore = class {
18339
18185
  path;
18340
18186
  database;
@@ -18343,8 +18189,7 @@ var KxmRunEventStore = class {
18343
18189
  this.database = openDatabase(this.path, "run event store", {
18344
18190
  schema: EVENT_STORE_SCHEMA,
18345
18191
  version: KXM_EVENT_STORE_SCHEMA_VERSION,
18346
- tables: EVENT_STORE_TABLES,
18347
- migrations: EVENT_STORE_MIGRATIONS
18192
+ tables: EVENT_STORE_TABLES
18348
18193
  });
18349
18194
  }
18350
18195
  close() {
@@ -16426,9 +16426,6 @@ var KxmSchemaRegistry = class {
16426
16426
  localBindingsValidator;
16427
16427
  templateProvenanceValidator;
16428
16428
  initOperationValidator;
16429
- migrationPlanValidator;
16430
- migrationDecisionValidator;
16431
- migrationReceiptValidator;
16432
16429
  permissionDiffValidator;
16433
16430
  runEventValidator;
16434
16431
  driveReceiptValidator;
@@ -16445,9 +16442,6 @@ var KxmSchemaRegistry = class {
16445
16442
  const localBindingsFile = "local-repository-bindings.schema.json";
16446
16443
  const templateProvenanceFile = "template-provenance.schema.json";
16447
16444
  const initOperationFile = "init-operation.schema.json";
16448
- const migrationPlanFile = "migration-plan.schema.json";
16449
- const migrationDecisionFile = "migration-decision.schema.json";
16450
- const migrationReceiptFile = "migration-receipt.schema.json";
16451
16445
  const permissionDiffFile = "permission-diff.schema.json";
16452
16446
  const runEventFile = "run-event.schema.json";
16453
16447
  const driveReceiptFile = "drive-receipt.schema.json";
@@ -16456,9 +16450,6 @@ var KxmSchemaRegistry = class {
16456
16450
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, localBindingsFile)));
16457
16451
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, templateProvenanceFile)));
16458
16452
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, initOperationFile)));
16459
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationPlanFile)));
16460
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationDecisionFile)));
16461
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationReceiptFile)));
16462
16453
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, permissionDiffFile)));
16463
16454
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, runEventFile)));
16464
16455
  this.ajv.addSchema(readJsonObject(join2(this.schemasDir, driveReceiptFile)));
@@ -16472,9 +16463,6 @@ var KxmSchemaRegistry = class {
16472
16463
  const localBindingsValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${localBindingsFile}`);
16473
16464
  const templateProvenanceValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${templateProvenanceFile}`);
16474
16465
  const initOperationValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${initOperationFile}`);
16475
- const migrationPlanValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${migrationPlanFile}`);
16476
- const migrationDecisionValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${migrationDecisionFile}`);
16477
- const migrationReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${migrationReceiptFile}`);
16478
16466
  const permissionDiffValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${permissionDiffFile}`);
16479
16467
  const runEventValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${runEventFile}`);
16480
16468
  const driveReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/${driveReceiptFile}`);
@@ -16483,9 +16471,6 @@ var KxmSchemaRegistry = class {
16483
16471
  if (!localBindingsValidator) throw new Error(`schema did not compile: ${localBindingsFile}`);
16484
16472
  if (!templateProvenanceValidator) throw new Error(`schema did not compile: ${templateProvenanceFile}`);
16485
16473
  if (!initOperationValidator) throw new Error(`schema did not compile: ${initOperationFile}`);
16486
- if (!migrationPlanValidator) throw new Error(`schema did not compile: ${migrationPlanFile}`);
16487
- if (!migrationDecisionValidator) throw new Error(`schema did not compile: ${migrationDecisionFile}`);
16488
- if (!migrationReceiptValidator) throw new Error(`schema did not compile: ${migrationReceiptFile}`);
16489
16474
  if (!permissionDiffValidator) throw new Error(`schema did not compile: ${permissionDiffFile}`);
16490
16475
  if (!runEventValidator) throw new Error(`schema did not compile: ${runEventFile}`);
16491
16476
  if (!driveReceiptValidator) throw new Error(`schema did not compile: ${driveReceiptFile}`);
@@ -16494,9 +16479,6 @@ var KxmSchemaRegistry = class {
16494
16479
  this.localBindingsValidator = localBindingsValidator;
16495
16480
  this.templateProvenanceValidator = templateProvenanceValidator;
16496
16481
  this.initOperationValidator = initOperationValidator;
16497
- this.migrationPlanValidator = migrationPlanValidator;
16498
- this.migrationDecisionValidator = migrationDecisionValidator;
16499
- this.migrationReceiptValidator = migrationReceiptValidator;
16500
16482
  this.permissionDiffValidator = permissionDiffValidator;
16501
16483
  this.runEventValidator = runEventValidator;
16502
16484
  this.driveReceiptValidator = driveReceiptValidator;
@@ -16522,15 +16504,6 @@ var KxmSchemaRegistry = class {
16522
16504
  validateInitOperation(value, file) {
16523
16505
  return this.validateAuxiliary(value, file, "kxm.init-operation.v1", this.initOperationValidator);
16524
16506
  }
16525
- validateMigrationPlan(value, file) {
16526
- return this.validateAuxiliary(value, file, "kxm.migration-plan.v1", this.migrationPlanValidator);
16527
- }
16528
- validateMigrationDecision(value, file) {
16529
- return this.validateAuxiliary(value, file, "kxm.migration-decision.v1", this.migrationDecisionValidator);
16530
- }
16531
- validateMigrationReceipt(value, file) {
16532
- return this.validateAuxiliary(value, file, "kxm.migration-receipt.v1", this.migrationReceiptValidator);
16533
- }
16534
16507
  validatePermissionDiff(value, file) {
16535
16508
  return this.validateAuxiliary(value, file, "kxm.permission-diff.v1", this.permissionDiffValidator);
16536
16509
  }
@@ -17348,11 +17321,14 @@ function assertNoRegisteredGates(options) {
17348
17321
  function loadKxmProject(projectRoot, options = {}) {
17349
17322
  assertNoRegisteredGates(options);
17350
17323
  const root = resolve(projectRoot);
17351
- let migrationReceipt;
17352
- if (legacyConfigFilesAt(root).length > 0 && options.allowUnreceiptedLegacyConfig !== true) {
17353
- const receiptCheck = readKxmMigrationReceipt(root, options);
17354
- if (receiptCheck.issues.length > 0) throw new KxmConfigError(receiptCheck.issues);
17355
- migrationReceipt = receiptCheck.receipt;
17324
+ const legacyPresent = legacyConfigFilesAt(root);
17325
+ if (legacyPresent.length > 0) {
17326
+ throw new KxmConfigError(legacyPresent.map((file) => issue2(
17327
+ "semantic",
17328
+ "legacy_state_unsupported",
17329
+ file,
17330
+ "legacy JSON configuration is present and this build does not migrate it: delete these files once their YAML replacements exist in .kxm/, or initialise a fresh project"
17331
+ )));
17356
17332
  }
17357
17333
  const registry = new KxmSchemaRegistry(options.schemasDir);
17358
17334
  const project = readResource(registry, root, join2(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
@@ -17365,9 +17341,6 @@ function loadKxmProject(projectRoot, options = {}) {
17365
17341
  earlyIssues.push(issue2("semantic", "template_provenance_project_mismatch", ".kxm/template-provenance.yaml", "template provenance belongs to a different project identity"));
17366
17342
  }
17367
17343
  }
17368
- if (migrationReceipt && stringValue(migrationReceipt.projectId) !== stringValue(project.value.id)) {
17369
- earlyIssues.push(issue2("semantic", "migration_project_mismatch", KXM_MIGRATION_RECEIPT_PATH, "migration receipt belongs to a different project identity"));
17370
- }
17371
17344
  const declaredRepositoryIds = new Set(valuesOf(project.value, "repositories").map((candidate) => stringValue(objectValue(candidate)?.id)).filter((candidate) => candidate !== void 0));
17372
17345
  for (const repositoryId of Object.keys(options.repositoryBindings ?? {}).sort(compareCodeUnits3)) {
17373
17346
  if (!resourceIdentifier(repositoryId)) {
@@ -17444,6 +17417,15 @@ function loadKxmProject(projectRoot, options = {}) {
17444
17417
  continue;
17445
17418
  }
17446
17419
  }
17420
+ const memberLegacy = binding === root ? [] : legacyConfigFilesAt(binding);
17421
+ if (memberLegacy.length > 0) {
17422
+ throw new KxmConfigError(memberLegacy.map((file) => issue2(
17423
+ "semantic",
17424
+ "legacy_state_unsupported",
17425
+ `${repositoryId}/${file}`,
17426
+ `repository ${repositoryId} holds legacy JSON configuration and this build does not migrate it: delete those files once their YAML replacements exist, or bind a clean worktree`
17427
+ )));
17428
+ }
17447
17429
  const foldedBinding = canonicalHostPath(binding).toLocaleLowerCase("en-US");
17448
17430
  const priorBinding = seenBindings.get(foldedBinding);
17449
17431
  if (priorBinding && priorBinding !== repositoryId) {
@@ -17497,12 +17479,10 @@ function loadKxmProject(projectRoot, options = {}) {
17497
17479
  environments,
17498
17480
  ...gateRegistry ? { gateRegistry } : {},
17499
17481
  ...templateProvenance === void 0 ? {} : { templateProvenance },
17500
- ...migrationReceipt === void 0 ? {} : { migrationReceipt },
17501
17482
  resources,
17502
17483
  configRevision: bundleRevision(resources)
17503
17484
  };
17504
17485
  }
17505
- var KXM_MIGRATION_RECEIPT_PATH = ".kxm/migration-receipt.yaml";
17506
17486
  var LEGACY_CONFIG_FILES = [".kxm/config/agents.json", ".kxm/config/gates.json"];
17507
17487
  function legacyConfigFilesAt(root) {
17508
17488
  const files = [];
@@ -17528,66 +17508,6 @@ function legacyConfigFilesAt(root) {
17528
17508
  }
17529
17509
  return files;
17530
17510
  }
17531
- function hashFileRecord(root, relativePath) {
17532
- const absolute = join2(root, ...relativePath.split("/"));
17533
- if (!existsSync3(absolute)) return void 0;
17534
- const bytes = readFileSync(absolute);
17535
- return {
17536
- path: relativePath,
17537
- sha256: `sha256:${createHash2("sha256").update(bytes).digest("hex")}`,
17538
- bytes: bytes.byteLength
17539
- };
17540
- }
17541
- function migrationReceiptSelfHash(receipt) {
17542
- const { receiptSha256: _ignored, ...unsigned } = receipt;
17543
- return `sha256:${createHash2("sha256").update(kxmCanonicalJson(unsigned), "utf8").digest("hex")}`;
17544
- }
17545
- function readKxmMigrationReceipt(root, options = {}) {
17546
- const receiptPath = join2(root, ...KXM_MIGRATION_RECEIPT_PATH.split("/"));
17547
- const legacyFiles = legacyConfigFilesAt(root);
17548
- if (!existsSync3(receiptPath)) {
17549
- return {
17550
- issues: legacyFiles.map((file) => issue2("semantic", "legacy_kxm_conflict", file, "legacy and KXM configuration cannot coexist before an accepted migration receipt"))
17551
- };
17552
- }
17553
- const receiptStat = lstatSync(receiptPath);
17554
- if (receiptStat.isSymbolicLink() || !receiptStat.isFile()) {
17555
- return { issues: [issue2("path", "migration_receipt_invalid", KXM_MIGRATION_RECEIPT_PATH, "migration receipt must be a regular file, not a link")] };
17556
- }
17557
- let receipt;
17558
- try {
17559
- receipt = parseRestrictedYaml2(readFileSync(receiptPath), KXM_MIGRATION_RECEIPT_PATH);
17560
- } catch (error) {
17561
- if (error instanceof KxmConfigError) return { issues: [...error.issues] };
17562
- throw error;
17563
- }
17564
- const registry = new KxmSchemaRegistry(options.schemasDir);
17565
- const schemaIssues = registry.validateMigrationReceipt(receipt, KXM_MIGRATION_RECEIPT_PATH);
17566
- if (schemaIssues.length > 0) return { issues: schemaIssues };
17567
- if (receipt.receiptSha256 !== migrationReceiptSelfHash(receipt)) {
17568
- return { issues: [issue2("semantic", "migration_receipt_hash_mismatch", KXM_MIGRATION_RECEIPT_PATH, "receipt self-hash does not match its content")] };
17569
- }
17570
- const sources = (Array.isArray(receipt.sources) ? receipt.sources : []).map((candidate) => candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate.path : void 0).filter((candidate) => typeof candidate === "string").sort(compareCodeUnits3);
17571
- const issues = [];
17572
- const declared = new Set(sources);
17573
- for (const file of legacyFiles) {
17574
- if (!declared.has(file)) {
17575
- issues.push(issue2("semantic", "migration_source_unmigrated", file, "legacy configuration file is not covered by the migration receipt"));
17576
- continue;
17577
- }
17578
- const record2 = (Array.isArray(receipt.sources) ? receipt.sources : []).map((candidate) => candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : void 0).find((candidate) => candidate?.path === file);
17579
- const current = hashFileRecord(root, file);
17580
- if (!current || current.sha256 !== record2?.sha256 || current.bytes !== record2?.bytes) {
17581
- issues.push(issue2("semantic", "migration_source_changed", file, "legacy configuration changed after the migration receipt was issued"));
17582
- }
17583
- }
17584
- for (const file of sources) {
17585
- if (!legacyFiles.includes(file)) {
17586
- issues.push(issue2("semantic", "migration_source_missing", file, "receipt covers a legacy configuration file that no longer exists"));
17587
- }
17588
- }
17589
- return issues.length > 0 ? { issues } : { receipt, issues: [] };
17590
- }
17591
17511
 
17592
17512
  // plugins/kxm/src/runtime-store.ts
17593
17513
  import { createHash as createHash4, randomUUID } from "node:crypto";
@@ -17783,20 +17703,11 @@ function openDatabase(file, description, spec) {
17783
17703
  database.exec(spec.schema);
17784
17704
  database.exec(`PRAGMA user_version = ${spec.version}`);
17785
17705
  } else if (version < spec.version) {
17786
- let currentVersion = version;
17787
- while (currentVersion < spec.version) {
17788
- const step = spec.migrations?.find((m) => m.fromVersion === currentVersion);
17789
- if (!step) {
17790
- throw databaseError(
17791
- "runtime_schema_outdated",
17792
- file,
17793
- `${description} schema version ${version} is older than ${spec.version}; no migration lane, backup and restore remain E6`
17794
- );
17795
- }
17796
- step.migrate(database);
17797
- currentVersion = step.toVersion;
17798
- database.exec(`PRAGMA user_version = ${currentVersion}`);
17799
- }
17706
+ throw databaseError(
17707
+ "runtime_schema_outdated",
17708
+ file,
17709
+ `${description} is schema version ${version}; this build requires ${spec.version}. Delete the state file to start fresh and let its owning process recreate it (\`kxm hub start\` for hub state, the Runtime for registry/event stores); \`kxm init\` is project-only and rebuilds no database \u2014 upgrading old state in place is deliberately unsupported`
17710
+ );
17800
17711
  }
17801
17712
  if (spec.tables) {
17802
17713
  verifyExpectedTables(database, file, description, spec.tables);
@@ -18710,71 +18621,6 @@ CREATE TABLE project_controls (
18710
18621
  record TEXT NOT NULL
18711
18622
  ) STRICT;
18712
18623
  `;
18713
- var COORDINATOR_INTAKE_DDL = `
18714
- CREATE TABLE IF NOT EXISTS coordinators (
18715
- coordinator_id TEXT PRIMARY KEY,
18716
- project_id TEXT NOT NULL,
18717
- role TEXT NOT NULL,
18718
- channel TEXT NOT NULL,
18719
- ceiling_hash TEXT NOT NULL,
18720
- config_revision TEXT NOT NULL,
18721
- bound_at TEXT NOT NULL,
18722
- schema TEXT NOT NULL,
18723
- record TEXT NOT NULL
18724
- ) STRICT;
18725
- CREATE UNIQUE INDEX IF NOT EXISTS coordinators_slot ON coordinators(project_id, role, channel);
18726
- CREATE TABLE IF NOT EXISTS intake_messages (
18727
- message_id TEXT PRIMARY KEY,
18728
- project_id TEXT NOT NULL,
18729
- coordinator_id TEXT NOT NULL,
18730
- idempotency_key TEXT NOT NULL,
18731
- content_hash TEXT NOT NULL,
18732
- received_at TEXT NOT NULL,
18733
- dispatch_state TEXT NOT NULL CHECK (dispatch_state IN ('ready','held_paused','admitted','refused')),
18734
- schema TEXT NOT NULL,
18735
- record TEXT NOT NULL
18736
- ) STRICT;
18737
- CREATE UNIQUE INDEX IF NOT EXISTS intake_idempotency ON intake_messages(project_id, coordinator_id, idempotency_key);
18738
- CREATE INDEX IF NOT EXISTS intake_dispatch ON intake_messages(project_id, dispatch_state, received_at, message_id);
18739
- CREATE TABLE IF NOT EXISTS project_controls (
18740
- project_id TEXT PRIMARY KEY,
18741
- paused INTEGER NOT NULL CHECK (paused IN (0, 1)),
18742
- reason TEXT,
18743
- updated_at TEXT NOT NULL,
18744
- actor TEXT NOT NULL,
18745
- schema TEXT NOT NULL,
18746
- record TEXT NOT NULL
18747
- ) STRICT;
18748
- `;
18749
- var DRIVE_RECEIPTS_DDL = `
18750
- CREATE TABLE IF NOT EXISTS drive_receipts (
18751
- drive_id TEXT PRIMARY KEY,
18752
- run_id TEXT NOT NULL,
18753
- project_id TEXT NOT NULL,
18754
- opened_sequence INTEGER NOT NULL,
18755
- last_sequence INTEGER NOT NULL,
18756
- closed_at TEXT NOT NULL,
18757
- schema TEXT NOT NULL,
18758
- receipt TEXT NOT NULL
18759
- ) STRICT;
18760
- CREATE INDEX IF NOT EXISTS drive_receipts_run ON drive_receipts(run_id);
18761
- `;
18762
- var EVENT_STORE_MIGRATIONS = [
18763
- {
18764
- fromVersion: 3,
18765
- toVersion: 4,
18766
- migrate(database) {
18767
- database.exec(DRIVE_RECEIPTS_DDL);
18768
- }
18769
- },
18770
- {
18771
- fromVersion: 4,
18772
- toVersion: 5,
18773
- migrate(database) {
18774
- database.exec(COORDINATOR_INTAKE_DDL);
18775
- }
18776
- }
18777
- ];
18778
18624
  var KxmRunEventStore = class {
18779
18625
  path;
18780
18626
  database;
@@ -18783,8 +18629,7 @@ var KxmRunEventStore = class {
18783
18629
  this.database = openDatabase(this.path, "run event store", {
18784
18630
  schema: EVENT_STORE_SCHEMA,
18785
18631
  version: KXM_EVENT_STORE_SCHEMA_VERSION,
18786
- tables: EVENT_STORE_TABLES,
18787
- migrations: EVENT_STORE_MIGRATIONS
18632
+ tables: EVENT_STORE_TABLES
18788
18633
  });
18789
18634
  }
18790
18635
  close() {