@kontextmind/kxm 0.7.145 → 0.7.146

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.
Files changed (48) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.kxm/README.md +20 -2
  3. package/.kxm/agents/{coordinator.yaml → planner.yaml} +2 -0
  4. package/.kxm/agents/{critic-arch.yaml → reviewer-arch.yaml} +2 -0
  5. package/.kxm/agents/{critic-cli.yaml → reviewer-cli.yaml} +2 -0
  6. package/.kxm/agents/{implementer.yaml → writer.yaml} +2 -0
  7. package/.kxm/roles/planner.yaml +4 -2
  8. package/.kxm/roles/reviewer-arch.yaml +4 -2
  9. package/.kxm/roles/reviewer-cli.yaml +4 -2
  10. package/.kxm/roles/writer.yaml +6 -3
  11. package/.kxm/workflows/default.yaml +20 -12
  12. package/.kxm/workflows/land.yaml +1 -1
  13. package/.kxm/workflows/{review-arch-only.yaml → reviewer-arch-only.yaml} +7 -3
  14. package/.kxm/workflows/{review-cli-only.yaml → reviewer-cli-only.yaml} +7 -3
  15. package/.kxm/workflows/{implement-only.yaml → writer-only.yaml} +8 -4
  16. package/CHANGELOG.md +22 -5
  17. package/docs/contributing/harness-routing-internals.md +17 -11
  18. package/docs/reference/cli-reference.md +23 -24
  19. package/docs/reference/config-reference.md +69 -62
  20. package/docs/reference/harness-routing.md +6 -5
  21. package/docs/reference/workflow-catalog.md +3 -3
  22. package/package.json +3 -3
  23. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  24. package/plugins/kxm/dist/cli.js +1144 -804
  25. package/plugins/kxm/dist/mcp-server.js +1 -1
  26. package/plugins/kxm/dist/runtime-supervisor.js +636 -308
  27. package/plugins/kxm/dist/runtime.js +707 -379
  28. package/plugins/kxm/dist/server.js +49 -5
  29. package/plugins/kxm/package.json +1 -1
  30. package/plugins/kxm/skills/kxm-project-setup/SKILL.md +3 -3
  31. package/plugins/kxm/src/cli/project.ts +2 -1
  32. package/plugins/kxm/src/cli/roles.ts +3 -4
  33. package/plugins/kxm/src/engine.ts +9 -6
  34. package/plugins/kxm/src/mcp-server.ts +1 -1
  35. package/plugins/kxm/src/policy-draft.mjs +11 -5
  36. package/plugins/kxm/src/project-config.ts +49 -11
  37. package/plugins/kxm/src/runtime-service.ts +2 -1
  38. package/plugins/kxm/src/template.ts +39 -10
  39. package/plugins/kxm/src/workflow-manager.ts +34 -28
  40. package/plugins/kxm/src/workforce-names.d.mts +38 -0
  41. package/plugins/kxm/src/workforce-names.mjs +317 -0
  42. package/schemas/agent.schema.json +7 -0
  43. package/schemas/model.schema.json +12 -0
  44. package/schemas/workflow.schema.json +14 -0
  45. package/scripts/harness-run.mjs +1 -1
  46. package/scripts/native-critic.mjs +5 -5
  47. package/scripts/roster-policy.mjs +9 -3
  48. package/scripts/workforce-lint.mjs +18 -0
@@ -14779,15 +14779,15 @@ var require_dist = __commonJS({
14779
14779
 
14780
14780
  // plugins/kxm/src/runtime-service.ts
14781
14781
  import { createHash as createHash9 } from "node:crypto";
14782
- import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync4 } from "node:fs";
14783
- import { join as join7 } from "node:path";
14782
+ import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
14783
+ import { join as join8 } from "node:path";
14784
14784
 
14785
14785
  // plugins/kxm/src/project-config.ts
14786
14786
  var import__ = __toESM(require__(), 1);
14787
14787
  import { spawnSync as spawnSync2 } from "node:child_process";
14788
14788
  import { createHash as createHash3 } from "node:crypto";
14789
- import { existsSync as existsSync3, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
14790
- import { basename, dirname as dirname2, extname, isAbsolute, join as join2, relative, resolve, sep } from "node:path";
14789
+ import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync2, readdirSync as readdirSync2, realpathSync } from "node:fs";
14790
+ import { basename, dirname as dirname2, extname, isAbsolute, join as join3, relative, resolve, sep } from "node:path";
14791
14791
 
14792
14792
  // plugins/kxm/src/restricted-yaml.mjs
14793
14793
  var import_yaml = __toESM(require_dist(), 1);
@@ -14939,6 +14939,7 @@ var MODES = Object.freeze(["headless", "interactive", "either"]);
14939
14939
  var MODEL_KEYS = Object.freeze([
14940
14940
  "schema",
14941
14941
  "id",
14942
+ "aliases",
14942
14943
  "harness",
14943
14944
  "model",
14944
14945
  "vendor",
@@ -15139,6 +15140,9 @@ function validateModelShape(document, id, label, issues) {
15139
15140
  if (document.id !== void 0 && document.id !== id) {
15140
15141
  issues.push(issue2("schema", "identity_mismatch", label, `declared id ${String(document.id)} does not match ${id}`));
15141
15142
  }
15143
+ if (document.aliases !== void 0 && !identifierList(document.aliases)) {
15144
+ issues.push(issue2("schema", "schema_pattern", label, "aliases must be unique identifiers"));
15145
+ }
15142
15146
  if (document.harness !== void 0 && !identifier(document.harness)) {
15143
15147
  issues.push(issue2("schema", "schema_pattern", label, "harness must be an identifier"));
15144
15148
  }
@@ -15401,9 +15405,9 @@ function validateRoleSemantics(role, id, label, models, options, issues) {
15401
15405
  }
15402
15406
  if (id === role.purpose && CRITIC_PURPOSES.includes(role.purpose)) {
15403
15407
  const admitted = role.roster.map((entry) => models.get(entry.route)).filter((model) => model && admittedRoute(model));
15404
- if (admitted.length !== 1) {
15405
- issues.push(issue2("semantic", "critic_route_count", label, "required critic purpose files must list exactly one admitted route"));
15406
- } else if (admitted[0].permissions.length !== 1 || admitted[0].permissions[0] !== "read-only" || role.permission !== "read-only") {
15408
+ if (admitted.length < 1) {
15409
+ issues.push(issue2("semantic", "critic_route_count", label, "required critic purpose files must list at least one admitted route"));
15410
+ } else if (role.permission !== "read-only" || admitted.some((model) => model.permissions.length !== 1 || model.permissions[0] !== "read-only")) {
15407
15411
  issues.push(issue2("semantic", "permission_escalation", label, "critic purpose files must be read-only"));
15408
15412
  }
15409
15413
  }
@@ -15435,7 +15439,7 @@ function validateCriticVendors(roles, models, options, issues) {
15435
15439
  const role = roles.get(purpose);
15436
15440
  if (!role || role.purpose !== purpose) continue;
15437
15441
  const admitted = (role.roster ?? []).map((entry) => models.get(entry.route)).filter((model) => model && admittedRoute(model));
15438
- if (admitted.length === 1) critics.push({ purpose, vendor: canonicalVendor(admitted[0].vendor, aliases) });
15442
+ if (admitted.length >= 1) critics.push({ purpose, vendor: canonicalVendor(admitted[0].vendor, aliases) });
15439
15443
  }
15440
15444
  if (critics.length === 2 && critics[0].vendor === critics[1].vendor) {
15441
15445
  issues.push(issue2("semantic", "critic_vendor_collision", "roles/reviewer-arch", "required critics must have independent vendors"));
@@ -15498,8 +15502,272 @@ function validatePolicyDraft(input, options) {
15498
15502
  return { ok: true, data };
15499
15503
  }
15500
15504
 
15501
- // plugins/kxm/src/template.ts
15505
+ // plugins/kxm/src/workforce-names.mjs
15502
15506
  var import_yaml2 = __toESM(require_dist(), 1);
15507
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
15508
+ import { join } from "node:path";
15509
+ var ROSTER_EFFORTS = /* @__PURE__ */ new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
15510
+ var ROLE_IDS = Object.freeze([
15511
+ "writer",
15512
+ "planner",
15513
+ "reviewer-arch",
15514
+ "reviewer-cli",
15515
+ "experiment"
15516
+ ]);
15517
+ var ROUTE_RENAMES = Object.freeze([
15518
+ ["grok-native", "grok-grok-4-7"],
15519
+ ["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
15520
+ ["gemini-agy", "agy-gemini-3-8-flash-high"],
15521
+ ["fable-claude", "claude-fable"],
15522
+ ["sol-codex", "codex-gpt-5-6-sol"],
15523
+ ["grok-default", "grok-grok-4-6"],
15524
+ ["fable-default", "claude-fable"]
15525
+ ]);
15526
+ var AGENT_RENAMES = Object.freeze([
15527
+ ["coordinator", "planner"],
15528
+ ["implementer", "writer"],
15529
+ ["critic-arch", "reviewer-arch"],
15530
+ ["critic-cli", "reviewer-cli"]
15531
+ ]);
15532
+ var WORKFLOW_RENAMES = Object.freeze([
15533
+ ["implement-only", "writer-only"],
15534
+ ["review-arch-only", "reviewer-arch-only"],
15535
+ ["review-cli-only", "reviewer-cli-only"]
15536
+ ]);
15537
+ var STEP_RENAMES = Object.freeze([
15538
+ ["implement", "writer"],
15539
+ ["critic-arch", "reviewer-arch"],
15540
+ ["review-arch", "reviewer-arch"],
15541
+ ["critic-cli", "reviewer-cli"],
15542
+ ["review-cli", "reviewer-cli"]
15543
+ ]);
15544
+ var RENAMES = Object.freeze({
15545
+ route: ROUTE_RENAMES,
15546
+ agent: AGENT_RENAMES,
15547
+ workflow: WORKFLOW_RENAMES,
15548
+ step: STEP_RENAMES
15549
+ });
15550
+ var RESERVED_WORKFLOW_IDS = /* @__PURE__ */ new Set(["default", "land"]);
15551
+ var warned = /* @__PURE__ */ new Set();
15552
+ function noteDeprecatedId(kind, from, to) {
15553
+ const key = `${kind}\0${from}\0${to}`;
15554
+ if (warned.has(key)) return;
15555
+ warned.add(key);
15556
+ if (process.env.KXM_QUIET_ALIASES === "1") return;
15557
+ console.warn(`kxm: deprecated ${kind} id '${from}' resolves to '${to}'`);
15558
+ }
15559
+ function resolveRenamedId(requested, knownIds, pairs) {
15560
+ if (typeof requested !== "string" || knownIds.has(requested)) return requested;
15561
+ for (const [oldId, newId2] of pairs) {
15562
+ if (requested === oldId && knownIds.has(newId2)) return newId2;
15563
+ if (requested === newId2 && knownIds.has(oldId)) return oldId;
15564
+ }
15565
+ return requested;
15566
+ }
15567
+ function canonicalRouteId(harness, model) {
15568
+ if (typeof harness !== "string" || typeof model !== "string" || !harness || !model) return void 0;
15569
+ const parts = model.split("/").filter((part) => part.length > 0);
15570
+ if (parts.length === 0) return void 0;
15571
+ const slug = parts[parts.length - 1].replaceAll(".", "-").toLowerCase();
15572
+ const provider = parts.length > 1 ? parts[0].replaceAll(".", "-").toLowerCase() : void 0;
15573
+ const id = provider ? `${harness}-${slug}-${provider}` : `${harness}-${slug}`;
15574
+ return /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(id) && id.length <= 64 ? id : void 0;
15575
+ }
15576
+ function aliasList(value) {
15577
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
15578
+ }
15579
+ function lookupById(records, requested, kind) {
15580
+ const list = [...records].filter((record2) => typeof record2?.id === "string" && record2.id.length > 0);
15581
+ const known = new Set(list.map((record2) => record2.id));
15582
+ const direct = list.find((record2) => record2.id === requested);
15583
+ if (direct) return { record: direct, viaAlias: false };
15584
+ for (const record2 of list) {
15585
+ if (aliasList(record2.aliases).includes(requested)) {
15586
+ noteDeprecatedId(kind, requested, record2.id);
15587
+ return { record: record2, viaAlias: true };
15588
+ }
15589
+ }
15590
+ const renamed = resolveRenamedId(requested, known, RENAMES[kind] ?? []);
15591
+ if (renamed !== requested) {
15592
+ const record2 = list.find((item) => item.id === renamed);
15593
+ if (record2) {
15594
+ noteDeprecatedId(kind, requested, renamed);
15595
+ return { record: record2, viaAlias: true };
15596
+ }
15597
+ }
15598
+ return void 0;
15599
+ }
15600
+ function findYamlBasename(directory, requested, kind) {
15601
+ if (typeof requested !== "string" || !requested) return void 0;
15602
+ if (existsSync(join(directory, `${requested}.yaml`))) return requested;
15603
+ if (!existsSync(directory)) return void 0;
15604
+ const found = [];
15605
+ for (const name of readdirSync(directory)) {
15606
+ if (!name.endsWith(".yaml") || name === "inventory.yaml") continue;
15607
+ const id = name.slice(0, -5);
15608
+ let doc;
15609
+ try {
15610
+ doc = import_yaml2.default.parse(readFileSync(join(directory, name), "utf8"));
15611
+ } catch {
15612
+ continue;
15613
+ }
15614
+ const aliases = doc && typeof doc === "object" ? aliasList(doc.aliases) : [];
15615
+ found.push({ id, aliases });
15616
+ }
15617
+ const hit = lookupById(found, requested, kind);
15618
+ return hit?.record.id;
15619
+ }
15620
+ function readYamlDir(directory, skipInventory) {
15621
+ if (!existsSync(directory)) return [];
15622
+ const docs = [];
15623
+ for (const name of readdirSync(directory)) {
15624
+ if (!name.endsWith(".yaml")) continue;
15625
+ const id = name.slice(0, -5);
15626
+ if (skipInventory && id === "inventory") continue;
15627
+ let doc;
15628
+ try {
15629
+ doc = import_yaml2.default.parse(readFileSync(join(directory, name), "utf8"));
15630
+ } catch (error) {
15631
+ docs.push({ id, file: `${directory}/${name}`, error: error instanceof Error ? error.message : "invalid YAML" });
15632
+ continue;
15633
+ }
15634
+ if (!doc || typeof doc !== "object" || Array.isArray(doc)) {
15635
+ docs.push({ id, file: `${directory}/${name}`, error: "root must be a mapping" });
15636
+ continue;
15637
+ }
15638
+ docs.push({ id, file: name, doc });
15639
+ }
15640
+ return docs;
15641
+ }
15642
+ function push(bucket, severity, code, file, message) {
15643
+ bucket.push({ severity, code, file, message });
15644
+ }
15645
+ function selectorsFor(doc) {
15646
+ const model = typeof doc.model === "string" ? doc.model : "";
15647
+ const vendor = typeof doc.vendor === "string" ? doc.vendor : "";
15648
+ const harness = typeof doc.harness === "string" ? doc.harness : "";
15649
+ return [model, vendor && model ? `${vendor}/${model}` : "", harness && model ? `${harness}/${model}` : ""].filter(Boolean);
15650
+ }
15651
+ function lintWorkforce(root) {
15652
+ const errors = [];
15653
+ const warnings = [];
15654
+ const models = readYamlDir(join(root, ".kxm", "models"), true).filter((entry) => !entry.error);
15655
+ for (const entry of readYamlDir(join(root, ".kxm", "models"), true)) {
15656
+ if (entry.error) push(errors, "error", "invalid_yaml", `.kxm/models/${entry.id}.yaml`, entry.error);
15657
+ }
15658
+ const roles = readYamlDir(join(root, ".kxm", "roles"), false).filter((entry) => !entry.error);
15659
+ const agents = readYamlDir(join(root, ".kxm", "agents"), false).filter((entry) => !entry.error);
15660
+ const workflows = readYamlDir(join(root, ".kxm", "workflows"), false).filter((entry) => !entry.error);
15661
+ let admitted = [];
15662
+ const routesFile = join(root, ".kxm", "routes.yaml");
15663
+ if (existsSync(routesFile)) {
15664
+ try {
15665
+ const policy = import_yaml2.default.parse(readFileSync(routesFile, "utf8"));
15666
+ admitted = Array.isArray(policy?.admitted) ? policy.admitted.filter((item) => typeof item === "string") : [];
15667
+ } catch (error) {
15668
+ push(errors, "error", "invalid_yaml", ".kxm/routes.yaml", error instanceof Error ? error.message : "invalid YAML");
15669
+ }
15670
+ }
15671
+ const modelRecords = models.map((entry) => ({ id: entry.id, aliases: aliasList(entry.doc.aliases), entry }));
15672
+ const used = /* @__PURE__ */ new Set();
15673
+ for (const role of roles) {
15674
+ const purpose = role.doc.purpose;
15675
+ if (typeof purpose === "string" && role.id !== purpose) {
15676
+ push(errors, "error", "role_id_convention", `.kxm/roles/${role.id}.yaml`, `role id '${role.id}' must equal purpose '${purpose}'`);
15677
+ }
15678
+ const roster = Array.isArray(role.doc.roster) ? role.doc.roster : [];
15679
+ for (const item of roster) {
15680
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
15681
+ const route = item.route;
15682
+ const effort = item.effort;
15683
+ const routeLabel = typeof route === "string" && route ? route : "(missing route)";
15684
+ if (typeof effort !== "string" || !ROSTER_EFFORTS.has(effort)) {
15685
+ const detail = typeof effort === "string" ? `effort '${effort}' is not one of off, minimal, low, medium, high, xhigh, max` : "has no effort";
15686
+ push(errors, "error", "roster_effort_required", `.kxm/roles/${role.id}.yaml`, `roster route '${routeLabel}' ${detail}`);
15687
+ }
15688
+ if (typeof route !== "string" || !route) continue;
15689
+ const found = lookupById(modelRecords, route, "route");
15690
+ if (!found) {
15691
+ push(errors, "error", "route_unknown", `.kxm/roles/${role.id}.yaml`, `roster route '${route}' does not match a model file`);
15692
+ continue;
15693
+ }
15694
+ used.add(found.record.id);
15695
+ if (found.viaAlias) {
15696
+ push(warnings, "warning", "deprecated_id", `.kxm/roles/${role.id}.yaml`, `roster route '${route}' is a deprecated alias of '${found.record.id}'`);
15697
+ }
15698
+ }
15699
+ }
15700
+ const covered = /* @__PURE__ */ new Set();
15701
+ for (const model of models) {
15702
+ const doc = model.doc;
15703
+ if (typeof doc.id === "string" && doc.id !== model.id) {
15704
+ push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `declared id '${doc.id}' does not match the filename`);
15705
+ }
15706
+ const expected = canonicalRouteId(doc.harness, doc.model);
15707
+ if (!expected || model.id !== expected) {
15708
+ push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
15709
+ }
15710
+ if (!used.has(model.id)) {
15711
+ push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
15712
+ }
15713
+ const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
15714
+ if (!selectorHit) {
15715
+ push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
15716
+ } else {
15717
+ covered.add(selectorHit);
15718
+ }
15719
+ }
15720
+ for (const selector of admitted) {
15721
+ if (!covered.has(selector)) {
15722
+ push(warnings, "warning", "admitted_unrouted", ".kxm/routes.yaml", `admitted model '${selector}' is not used by any route`);
15723
+ }
15724
+ }
15725
+ const agentRecords = agents.map((entry) => ({ id: entry.id, aliases: aliasList(entry.doc.aliases), entry }));
15726
+ for (const agent of agents) {
15727
+ const role = agent.doc.role;
15728
+ if (typeof role !== "string" || agent.id !== role) {
15729
+ push(errors, "error", "agent_id_convention", `.kxm/agents/${agent.id}.yaml`, `agent id '${agent.id}' must equal its role '${role ?? ""}'`);
15730
+ }
15731
+ }
15732
+ for (const workflow of workflows) {
15733
+ if (!RESERVED_WORKFLOW_IDS.has(workflow.id) && !ROLE_IDS.some((role) => workflow.id === `${role}-only`)) {
15734
+ push(errors, "error", "workflow_id_convention", `.kxm/workflows/${workflow.id}.yaml`, `workflow id '${workflow.id}' must be default, land, or <role>-only`);
15735
+ }
15736
+ const steps = Array.isArray(workflow.doc.steps) ? workflow.doc.steps : [];
15737
+ const realIds = new Set(steps.map((step) => step && typeof step.id === "string" ? step.id : "").filter(Boolean));
15738
+ for (const step of steps) {
15739
+ if (!step || typeof step !== "object" || typeof step.id !== "string") continue;
15740
+ if (step.kind === "agent" || step.kind === "moa") {
15741
+ const agentName = typeof step.agent === "string" ? step.agent : "";
15742
+ const found = agentName ? lookupById(agentRecords, agentName, "agent") : void 0;
15743
+ if (!found) {
15744
+ push(errors, "error", "agent_unknown", `.kxm/workflows/${workflow.id}.yaml`, `step '${step.id}' references unknown agent '${agentName}'`);
15745
+ } else if (found.viaAlias) {
15746
+ push(warnings, "warning", "deprecated_id", `.kxm/workflows/${workflow.id}.yaml`, `step '${step.id}' agent '${agentName}' is a deprecated alias of '${found.record.id}'`);
15747
+ }
15748
+ const role = found?.record.entry.doc.role;
15749
+ if (typeof role === "string" && step.id !== role) {
15750
+ push(errors, "error", "step_id_convention", `.kxm/workflows/${workflow.id}.yaml`, `agent step '${step.id}' must use the role id '${role}'`);
15751
+ }
15752
+ } else if (step.kind === "gate") {
15753
+ const gate = typeof step.gate === "string" ? step.gate : "";
15754
+ const allowed = step.id === "verify" || step.id === gate || step.id.startsWith(`${workflow.id}-`);
15755
+ if (!allowed) {
15756
+ push(errors, "error", "step_id_convention", `.kxm/workflows/${workflow.id}.yaml`, `gate step '${step.id}' must be verify, the gate id, or ${workflow.id}-<name>`);
15757
+ }
15758
+ }
15759
+ for (const alias of aliasList(step.aliases)) {
15760
+ if (realIds.has(alias) && alias !== step.id) {
15761
+ push(errors, "error", "step_id_convention", `.kxm/workflows/${workflow.id}.yaml`, `step alias '${alias}' collides with another step id`);
15762
+ }
15763
+ }
15764
+ }
15765
+ }
15766
+ return { errors, warnings };
15767
+ }
15768
+
15769
+ // plugins/kxm/src/template.ts
15770
+ var import_yaml3 = __toESM(require_dist(), 1);
15503
15771
  import { createHash as createHash2 } from "node:crypto";
15504
15772
  var KXM_TEMPLATE_ID = "builtin-minimal";
15505
15773
  var KXM_TEMPLATE_PROVENANCE_PATH = ".kxm/template-provenance.yaml";
@@ -15636,33 +15904,60 @@ function coreTemplate(projectId, projectName, variant) {
15636
15904
  ]);
15637
15905
  if (variant === "v4-registry") {
15638
15906
  const coordinator = files.get(".kxm/agents/coordinator.yaml");
15639
- if (coordinator) files.set(".kxm/agents/coordinator.yaml", { ...coordinator, role: "planner" });
15907
+ if (coordinator) {
15908
+ files.delete(".kxm/agents/coordinator.yaml");
15909
+ files.set(".kxm/agents/planner.yaml", { ...coordinator, role: "planner", aliases: ["coordinator"] });
15910
+ }
15640
15911
  const implementer = files.get(".kxm/agents/implementer.yaml");
15641
- if (implementer) files.set(".kxm/agents/implementer.yaml", { ...implementer, role: "writer" });
15912
+ if (implementer) {
15913
+ files.delete(".kxm/agents/implementer.yaml");
15914
+ files.set(".kxm/agents/writer.yaml", { ...implementer, role: "writer", aliases: ["implementer"] });
15915
+ }
15642
15916
  const workflow = files.get(".kxm/workflows/default.yaml");
15643
15917
  if (workflow) {
15644
15918
  const limits = { ...workflow.limits };
15645
15919
  delete limits.maxAgentTimeMs;
15646
- files.set(".kxm/workflows/default.yaml", { ...workflow, limits });
15920
+ const steps = workflow.steps.map((step) => {
15921
+ if (step.id === "plan") {
15922
+ const on = { ...step.on, passed: "writer" };
15923
+ return { ...step, agent: "planner", on };
15924
+ }
15925
+ if (step.id === "implement") {
15926
+ const assignments = { ...step.assignments, allowedAgents: ["writer"] };
15927
+ return { ...step, id: "writer", aliases: ["implement"], agent: "writer", assignments };
15928
+ }
15929
+ if (step.id === "verify") {
15930
+ const on = { ...step.on };
15931
+ const failure = on["implementation-failure"];
15932
+ if (failure && typeof failure === "object" && !Array.isArray(failure)) {
15933
+ on["implementation-failure"] = { ...failure, target: "writer" };
15934
+ }
15935
+ return { ...step, on };
15936
+ }
15937
+ return step;
15938
+ });
15939
+ files.set(".kxm/workflows/default.yaml", { ...workflow, coordinator: "planner", limits, steps });
15647
15940
  }
15648
15941
  files.set(".kxm/routes.yaml", {
15649
15942
  schema: "kxm.routes.v2",
15650
- updatedAt: "2026-09-23T00:00:00.000Z",
15943
+ updatedAt: "2026-09-27T00:00:00.000Z",
15651
15944
  admitted: ["anthropic/fable", "xai/grok-4.6"],
15652
15945
  disabled: []
15653
15946
  });
15654
- files.set(".kxm/models/grok-default.yaml", {
15947
+ files.set(".kxm/models/grok-grok-4-6.yaml", {
15655
15948
  schema: "kxm.model.v2",
15656
- id: "grok-default",
15949
+ id: "grok-grok-4-6",
15950
+ aliases: ["grok-default"],
15657
15951
  harness: "grok",
15658
15952
  model: "grok-4.6",
15659
15953
  vendor: "xai",
15660
15954
  status: "admitted",
15661
15955
  permissions: ["edit"]
15662
15956
  });
15663
- files.set(".kxm/models/fable-default.yaml", {
15957
+ files.set(".kxm/models/claude-fable.yaml", {
15664
15958
  schema: "kxm.model.v2",
15665
- id: "fable-default",
15959
+ id: "claude-fable",
15960
+ aliases: ["fable-default"],
15666
15961
  harness: "claude",
15667
15962
  model: "fable",
15668
15963
  vendor: "anthropic",
@@ -15675,7 +15970,7 @@ function coreTemplate(projectId, projectName, variant) {
15675
15970
  purpose: "writer",
15676
15971
  permission: "edit",
15677
15972
  description: "Primary implementation agent.",
15678
- roster: [{ route: "grok-default" }]
15973
+ roster: [{ route: "grok-grok-4-6", effort: "medium" }]
15679
15974
  });
15680
15975
  files.set(".kxm/roles/planner.yaml", {
15681
15976
  schema: "kxm.role.v2",
@@ -15683,7 +15978,7 @@ function coreTemplate(projectId, projectName, variant) {
15683
15978
  purpose: "planner",
15684
15979
  permission: "read-only",
15685
15980
  description: "Plans the change before implementation.",
15686
- roster: [{ route: "fable-default" }]
15981
+ roster: [{ route: "claude-fable", effort: "medium" }]
15687
15982
  });
15688
15983
  files.set(".kxm/gates.yaml", {
15689
15984
  schema: "kxm.gate-registry.v1",
@@ -15704,7 +15999,7 @@ function renderKxmTemplate(projectId, projectName, variant = CURRENT_KXM_TEMPLAT
15704
15999
  const values = coreTemplate(projectId, projectName, variant);
15705
16000
  const coreFiles = /* @__PURE__ */ new Map();
15706
16001
  const records = [...values.entries()].map(([path, value]) => {
15707
- const bytes = Buffer.from((0, import_yaml2.stringify)(value, { lineWidth: 0 }), "utf8");
16002
+ const bytes = Buffer.from((0, import_yaml3.stringify)(value, { lineWidth: 0 }), "utf8");
15708
16003
  coreFiles.set(path, bytes);
15709
16004
  return {
15710
16005
  path,
@@ -15724,7 +16019,7 @@ function renderKxmTemplate(projectId, projectName, variant = CURRENT_KXM_TEMPLAT
15724
16019
  const fileEntries = [...coreFiles.entries()];
15725
16020
  fileEntries.push([
15726
16021
  KXM_TEMPLATE_PROVENANCE_PATH,
15727
- Buffer.from((0, import_yaml2.stringify)(provenance, { lineWidth: 0 }), "utf8")
16022
+ Buffer.from((0, import_yaml3.stringify)(provenance, { lineWidth: 0 }), "utf8")
15728
16023
  ]);
15729
16024
  fileEntries.sort(([left], [right]) => compareCodeUnits3(left, right));
15730
16025
  const files = new Map(fileEntries);
@@ -15748,15 +16043,15 @@ function resolveKxmTemplateBaseline(value) {
15748
16043
  }
15749
16044
 
15750
16045
  // plugins/kxm/src/repo-root.ts
15751
- import { existsSync } from "node:fs";
15752
- import { dirname, join } from "node:path";
16046
+ import { existsSync as existsSync2 } from "node:fs";
16047
+ import { dirname, join as join2 } from "node:path";
15753
16048
  import { fileURLToPath } from "node:url";
15754
16049
  var ROOT_MARKERS = ["scripts/kxm-hub.mjs", "scripts/kxm.mjs"];
15755
16050
  var MAX_WALK_DEPTH = 10;
15756
16051
  function tryFindKxmRepoRoot(fromUrl = import.meta.url) {
15757
16052
  let dir = dirname(fileURLToPath(fromUrl));
15758
16053
  for (let depth = 0; depth < MAX_WALK_DEPTH; depth += 1) {
15759
- if (ROOT_MARKERS.some((marker) => existsSync(join(dir, marker)))) return dir;
16054
+ if (ROOT_MARKERS.some((marker) => existsSync2(join2(dir, marker)))) return dir;
15760
16055
  const parent = dirname(dir);
15761
16056
  if (parent === dir) break;
15762
16057
  dir = parent;
@@ -15773,7 +16068,7 @@ function findKxmRepoRoot(fromUrl = import.meta.url) {
15773
16068
 
15774
16069
  // plugins/kxm/src/harness.ts
15775
16070
  import { spawnSync } from "node:child_process";
15776
- import { existsSync as existsSync2 } from "node:fs";
16071
+ import { existsSync as existsSync3 } from "node:fs";
15777
16072
  import { win32 as win32Path } from "node:path";
15778
16073
 
15779
16074
  // plugins/kxm/src/oneshot-process.ts
@@ -16412,7 +16707,7 @@ function findWinNpmInnerExe(cliId, options = {}) {
16412
16707
  if ((options.platform ?? process.platform) !== "win32") return void 0;
16413
16708
  const segments = WIN_NPM_INNER_EXE[cliId];
16414
16709
  if (!segments) return void 0;
16415
- const exists = options.existsSync ?? existsSync2;
16710
+ const exists = options.existsSync ?? existsSync3;
16416
16711
  const pathEnv = options.pathEnv ?? process.env.PATH ?? "";
16417
16712
  for (const dir of pathEnv.split(";").filter(Boolean)) {
16418
16713
  if (!exists(win32Path.join(dir, `${cliId}.cmd`))) continue;
@@ -17113,7 +17408,7 @@ var KxmConfigError = class extends Error {
17113
17408
  }
17114
17409
  };
17115
17410
  function defaultKxmSchemaDir() {
17116
- return join2(findKxmRepoRoot(import.meta.url), "schemas");
17411
+ return join3(findKxmRepoRoot(import.meta.url), "schemas");
17117
17412
  }
17118
17413
  var DEFAULT_SCHEMA_DIR = defaultKxmSchemaDir();
17119
17414
  var RESOURCE_SCHEMA = Object.freeze({
@@ -17162,7 +17457,7 @@ function parseRestrictedYaml2(input, label = "<yaml>", limits = KXM_YAML_LIMITS)
17162
17457
  }
17163
17458
  }
17164
17459
  function readJsonObject(file) {
17165
- const parsed = JSON.parse(readFileSync(file, "utf8"));
17460
+ const parsed = JSON.parse(readFileSync2(file, "utf8"));
17166
17461
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${file} is not a JSON object`);
17167
17462
  return parsed;
17168
17463
  }
@@ -17182,10 +17477,10 @@ var KxmSchemaRegistry = class {
17182
17477
  constructor(schemasDir = DEFAULT_SCHEMA_DIR) {
17183
17478
  this.schemasDir = resolve(schemasDir);
17184
17479
  this.ajv = new import__.Ajv2020({ allErrors: true, strict: true, strictRequired: false });
17185
- const common = readJsonObject(join2(this.schemasDir, "common.schema.json"));
17480
+ const common = readJsonObject(join3(this.schemasDir, "common.schema.json"));
17186
17481
  this.ajv.addSchema(common);
17187
17482
  for (const definition of Object.values(RESOURCE_SCHEMA)) {
17188
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, definition.file)));
17483
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, definition.file)));
17189
17484
  }
17190
17485
  const localBindingsFile = "local-repository-bindings.schema.json";
17191
17486
  const templateProvenanceFile = "template-provenance.schema.json";
@@ -17196,15 +17491,15 @@ var KxmSchemaRegistry = class {
17196
17491
  const coordinatorFile = "coordinator.schema.json";
17197
17492
  const intakeMessageFile = "intake-message.schema.json";
17198
17493
  const syncEventFile = "sync-event.schema.json";
17199
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, localBindingsFile)));
17200
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, templateProvenanceFile)));
17201
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, initOperationFile)));
17202
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, permissionDiffFile)));
17203
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, runEventFile)));
17204
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, driveReceiptFile)));
17205
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, coordinatorFile)));
17206
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, intakeMessageFile)));
17207
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, syncEventFile)));
17494
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, localBindingsFile)));
17495
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, templateProvenanceFile)));
17496
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, initOperationFile)));
17497
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, permissionDiffFile)));
17498
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, runEventFile)));
17499
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, driveReceiptFile)));
17500
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, coordinatorFile)));
17501
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, intakeMessageFile)));
17502
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, syncEventFile)));
17208
17503
  for (const [kind, definition] of Object.entries(RESOURCE_SCHEMA)) {
17209
17504
  const validator = this.ajv.getSchema(`https://schemas.kxm.dev/${definition.file}`);
17210
17505
  if (!validator) throw new Error(`schema did not compile: ${definition.file}`);
@@ -17360,15 +17655,15 @@ function containedHostPath(root, candidate) {
17360
17655
  function portableBindingIssue(root, pathHint, repositoryId) {
17361
17656
  let current = root;
17362
17657
  for (const segment of pathHint === "." ? [] : pathHint.split("/")) {
17363
- current = join2(current, segment);
17364
- if (!existsSync3(current)) break;
17658
+ current = join3(current, segment);
17659
+ if (!existsSync4(current)) break;
17365
17660
  const stat = lstatSync(current);
17366
17661
  if (stat.isSymbolicLink()) {
17367
17662
  return issue3("path", "repository_binding_path_link", ".kxm/project.yaml", `portable pathHint for ${repositoryId} traverses a symbolic link or junction`);
17368
17663
  }
17369
17664
  }
17370
17665
  const binding = resolve(root, ...pathHint.split("/"));
17371
- if (existsSync3(binding)) {
17666
+ if (existsSync4(binding)) {
17372
17667
  const realRoot = canonicalHostPath(root);
17373
17668
  const realBinding = canonicalHostPath(binding);
17374
17669
  if (!containedHostPath(realRoot, realBinding)) {
@@ -17419,7 +17714,7 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
17419
17714
  parent = dirname2(parent);
17420
17715
  }
17421
17716
  if (!stat.isFile()) fail2("path", "resource_not_file", label, "configuration resource must be a regular file");
17422
- return { kind, ...id === void 0 ? {} : { id }, file, logicalPath, value: resourceValue(registry, readFileSync(file), label, kind) };
17717
+ return { kind, ...id === void 0 ? {} : { id }, file, logicalPath, value: resourceValue(registry, readFileSync2(file), label, kind) };
17423
17718
  }
17424
17719
  function resourceValue(registry, input, label, kind) {
17425
17720
  const value = parseRestrictedYaml2(input, label);
@@ -17428,14 +17723,14 @@ function resourceValue(registry, input, label, kind) {
17428
17723
  return value;
17429
17724
  }
17430
17725
  function readTemplateProvenance(registry, root) {
17431
- const file = join2(root, ".kxm", "template-provenance.yaml");
17432
- if (!existsSync3(file)) return void 0;
17726
+ const file = join3(root, ".kxm", "template-provenance.yaml");
17727
+ if (!existsSync4(file)) return void 0;
17433
17728
  const label = ".kxm/template-provenance.yaml";
17434
17729
  const stat = lstatSync(file);
17435
17730
  if (stat.isSymbolicLink() || !stat.isFile()) {
17436
17731
  fail2("path", "resource_not_file", label, "template provenance must be a regular file, not a link or directory");
17437
17732
  }
17438
- const configRoot = join2(root, ".kxm");
17733
+ const configRoot = join3(root, ".kxm");
17439
17734
  let parent = dirname2(file);
17440
17735
  while (parent !== root) {
17441
17736
  const parentStat = lstatSync(parent);
@@ -17445,7 +17740,7 @@ function readTemplateProvenance(registry, root) {
17445
17740
  if (parent === configRoot) break;
17446
17741
  parent = dirname2(parent);
17447
17742
  }
17448
- const value = parseRestrictedYaml2(readFileSync(file), label);
17743
+ const value = parseRestrictedYaml2(readFileSync2(file), label);
17449
17744
  const issues = registry.validateTemplateProvenance(value, label);
17450
17745
  if (issues.length > 0) throw new KxmConfigError(issues);
17451
17746
  if (!resolveKxmTemplateBaseline(value)) {
@@ -17476,37 +17771,37 @@ function readTemplateProvenance(registry, root) {
17476
17771
  }
17477
17772
  function listNamedResources(registry, root, directory, logicalDirectory, kind, replacedId, collected) {
17478
17773
  const resources = /* @__PURE__ */ new Map();
17479
- if (!existsSync3(directory)) return resources;
17774
+ if (!existsSync4(directory)) return resources;
17480
17775
  const stat = lstatSync(directory);
17481
17776
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
17482
17777
  fail2("path", "resource_directory_invalid", displayPath(root, directory), "resource directory must be a regular directory");
17483
17778
  }
17484
17779
  const issues = [];
17485
- const entries = readdirSync(directory, { withFileTypes: true }).sort((left, right) => compareCodeUnits4(left.name, right.name));
17780
+ const entries = readdirSync2(directory, { withFileTypes: true }).sort((left, right) => compareCodeUnits4(left.name, right.name));
17486
17781
  for (const entry of entries) {
17487
17782
  if (entry.isDirectory()) {
17488
- issues.push(issue3("path", "nested_resource_directory", displayPath(root, join2(directory, entry.name)), "nested resource directories are not allowed"));
17783
+ issues.push(issue3("path", "nested_resource_directory", displayPath(root, join3(directory, entry.name)), "nested resource directories are not allowed"));
17489
17784
  continue;
17490
17785
  }
17491
17786
  if (!entry.name.toLowerCase().endsWith(".yaml") && !entry.name.toLowerCase().endsWith(".yml")) continue;
17492
17787
  if (!entry.isFile() || extname(entry.name) !== ".yaml") {
17493
- issues.push(issue3("path", "resource_filename_invalid", displayPath(root, join2(directory, entry.name)), "resource must be a regular file with the exact .yaml extension"));
17788
+ issues.push(issue3("path", "resource_filename_invalid", displayPath(root, join3(directory, entry.name)), "resource must be a regular file with the exact .yaml extension"));
17494
17789
  continue;
17495
17790
  }
17496
17791
  const id = basename(entry.name, ".yaml");
17497
17792
  if (kind === "model" && id === "inventory") continue;
17498
17793
  if (id === replacedId) continue;
17499
17794
  if (!resourceIdentifier(id)) {
17500
- issues.push(issue3("path", "resource_id_invalid", displayPath(root, join2(directory, entry.name)), `filename-derived identity ${id} is invalid or platform-reserved`));
17795
+ issues.push(issue3("path", "resource_id_invalid", displayPath(root, join3(directory, entry.name)), `filename-derived identity ${id} is invalid or platform-reserved`));
17501
17796
  continue;
17502
17797
  }
17503
17798
  const collision = [...resources.keys()].find((candidate) => candidate.toLocaleLowerCase("en-US") === id.toLocaleLowerCase("en-US"));
17504
17799
  if (collision) {
17505
- issues.push(issue3("path", "resource_id_collision", displayPath(root, join2(directory, entry.name)), `${id} case-folds to existing ${collision}`));
17800
+ issues.push(issue3("path", "resource_id_collision", displayPath(root, join3(directory, entry.name)), `${id} case-folds to existing ${collision}`));
17506
17801
  continue;
17507
17802
  }
17508
17803
  try {
17509
- const resource = readResource(registry, root, join2(directory, entry.name), `${logicalDirectory}/${id}.yaml`, kind, id);
17804
+ const resource = readResource(registry, root, join3(directory, entry.name), `${logicalDirectory}/${id}.yaml`, kind, id);
17510
17805
  resources.set(id, resource);
17511
17806
  } catch (error) {
17512
17807
  if (error instanceof KxmConfigError) issues.push(...error.issues);
@@ -17535,6 +17830,14 @@ function numberValue(value, fallback) {
17535
17830
  function names(value) {
17536
17831
  return Array.isArray(value) ? value.filter((candidate) => typeof candidate === "string") : [];
17537
17832
  }
17833
+ function lookupKxmResource(resources, requested, kind) {
17834
+ const records = [...resources].map((resource) => ({
17835
+ id: resource.id,
17836
+ aliases: names(resource.value.aliases),
17837
+ resource
17838
+ }));
17839
+ return lookupById(records, requested, kind)?.record.resource;
17840
+ }
17538
17841
  function mapResource(resource, map, issues) {
17539
17842
  const id = resource.id;
17540
17843
  if (!id) return;
@@ -17725,14 +18028,31 @@ function transition(value) {
17725
18028
  function validateWorkflow(workflow, agents, models, repositories, gates, issues) {
17726
18029
  const file = workflow.logicalPath;
17727
18030
  const coordinator = stringValue(workflow.value.coordinator) ?? "coordinator";
17728
- if (!agents.has(coordinator)) issues.push(issue3("reference", "coordinator_unknown", file, `coordinator ${coordinator} does not exist`));
18031
+ if (!lookupKxmResource(agents.values(), coordinator, "agent")) issues.push(issue3("reference", "coordinator_unknown", file, `coordinator ${coordinator} does not exist`));
17729
18032
  const steps = valuesOf(workflow.value, "steps").map((candidate) => objectValue(candidate)).filter((candidate) => Boolean(candidate));
17730
18033
  const stepIndex = /* @__PURE__ */ new Map();
18034
+ const primarySteps = /* @__PURE__ */ new Set();
17731
18035
  for (const [index, step] of steps.entries()) {
17732
18036
  const id = stringValue(step.id);
17733
18037
  if (!id) continue;
17734
18038
  if (stepIndex.has(id)) issues.push(issue3("semantic", "step_id_duplicate", file, `step ${id} is duplicated`));
17735
- else stepIndex.set(id, index);
18039
+ else {
18040
+ stepIndex.set(id, index);
18041
+ primarySteps.add(id);
18042
+ }
18043
+ }
18044
+ for (const [index, step] of steps.entries()) {
18045
+ const id = stringValue(step.id);
18046
+ if (!id) continue;
18047
+ const aliases = new Set(names(step.aliases));
18048
+ for (const [oldId, newId2] of STEP_RENAMES) {
18049
+ if (id === newId2) aliases.add(oldId);
18050
+ if (id === oldId) aliases.add(newId2);
18051
+ }
18052
+ for (const alias of aliases) {
18053
+ if (alias === id || primarySteps.has(alias) || stepIndex.has(alias)) continue;
18054
+ stepIndex.set(alias, index);
18055
+ }
17736
18056
  }
17737
18057
  for (const field of ["reproOracle", "planHash"]) {
17738
18058
  const oracle = objectValue(workflow.value[field]);
@@ -17761,7 +18081,7 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17761
18081
  const kind = stringValue(step.kind);
17762
18082
  validateToolPolicy(workflow, objectValue(step.tools), `${stepId}.tools`, issues);
17763
18083
  const primaryAgentId = stringValue(step.agent);
17764
- if ((kind === "agent" || kind === "moa") && primaryAgentId && !agents.has(primaryAgentId)) {
18084
+ if ((kind === "agent" || kind === "moa") && primaryAgentId && !lookupKxmResource(agents.values(), primaryAgentId, "agent")) {
17765
18085
  issues.push(issue3("reference", "agent_unknown", file, `${stepId} references unknown agent ${primaryAgentId}`));
17766
18086
  }
17767
18087
  const gate = stringValue(step.gate);
@@ -17788,7 +18108,7 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17788
18108
  const declaredAgents = assignment ? names(assignment.allowedAgents) : [];
17789
18109
  const allowedAgents = declaredAgents.length > 0 ? declaredAgents : primaryAgentId ? [primaryAgentId] : [];
17790
18110
  for (const agentId of allowedAgents) {
17791
- const agent = agents.get(agentId);
18111
+ const agent = lookupKxmResource(agents.values(), agentId, "agent");
17792
18112
  if (!agent) issues.push(issue3("reference", "assignment_agent_unknown", file, `${stepId} allows unknown agent ${agentId}`));
17793
18113
  else {
17794
18114
  validateAgentScope(agent, step, repositories, file, stepId, issues);
@@ -17819,8 +18139,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17819
18139
  const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
17820
18140
  if (maxWriteRepositories > writable) issues.push(issue3("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
17821
18141
  }
17822
- const join23 = objectValue(step.join);
17823
- const minimumPassed = join23 && typeof join23.minimumPassed === "number" ? join23.minimumPassed : void 0;
18142
+ const join24 = objectValue(step.join);
18143
+ const minimumPassed = join24 && typeof join24.minimumPassed === "number" ? join24.minimumPassed : void 0;
17824
18144
  if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue3("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
17825
18145
  const distinctBy = names(assignment?.distinctBy);
17826
18146
  if (distinctBy.length > 0) {
@@ -17845,7 +18165,7 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17845
18165
  const producerMinimum = numberValue(policy.minimumProducers, 1);
17846
18166
  if (producerMinimum > target || producerMinimum > eligible.length) issues.push(issue3("semantic", "producer_minimum_impossible", file, `${stepId}.${String(key)} producer minimum exceeds its eligible or target pool`));
17847
18167
  for (const agentId of eligible) {
17848
- if (!agents.has(agentId)) issues.push(issue3("reference", "producer_agent_unknown", file, `${stepId}.${String(key)} references unknown producer ${agentId}`));
18168
+ if (!lookupKxmResource(agents.values(), agentId, "agent")) issues.push(issue3("reference", "producer_agent_unknown", file, `${stepId}.${String(key)} references unknown producer ${agentId}`));
17849
18169
  if (allowedAgents.length > 0 && !allowedAgents.includes(agentId)) issues.push(issue3("semantic", "producer_agent_ineligible", file, `${stepId}.${String(key)} producer ${agentId} is outside allowedAgents`));
17850
18170
  }
17851
18171
  const degradation = objectValue(policy.degradation);
@@ -17866,6 +18186,10 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17866
18186
  if (parsed.terminalStatus === "completed") completedTerminalSources.add(index);
17867
18187
  continue;
17868
18188
  }
18189
+ if (parsed.target && parsed.target !== "$terminal" && !primarySteps.has(parsed.target) && stepIndex.has(parsed.target)) {
18190
+ const canonical = stringValue(steps[stepIndex.get(parsed.target) ?? -1]?.id);
18191
+ if (canonical) noteDeprecatedId("step", parsed.target, canonical);
18192
+ }
17869
18193
  const targetIndex = parsed.target === void 0 ? void 0 : stepIndex.get(parsed.target);
17870
18194
  if (targetIndex === void 0) {
17871
18195
  issues.push(issue3("reference", "transition_target_unknown", file, `${stepId}.${outcome} references unknown target ${String(parsed.target)}`));
@@ -18020,12 +18344,12 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
18020
18344
  }
18021
18345
  validateModelReferences(models, issues);
18022
18346
  const defaultWorkflow = stringValue(project.value.defaultWorkflow) ?? "default";
18023
- if (!workflows.has(defaultWorkflow)) issues.push(issue3("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
18347
+ if (!lookupKxmResource(workflows.values(), defaultWorkflow, "workflow")) issues.push(issue3("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
18024
18348
  for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
18025
- if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roster.yaml"))) {
18349
+ if (projectRoot && existsSync4(join3(projectRoot, ".kxm", "roster.yaml"))) {
18026
18350
  issues.push(issue3("semantic", "retired_roster_file", ".kxm/roster.yaml", "create the role and model files and delete roster.yaml"));
18027
18351
  }
18028
- if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roles"))) {
18352
+ if (projectRoot && existsSync4(join3(projectRoot, ".kxm", "roles"))) {
18029
18353
  issues.push(...developerRolePolicyIssues(projectRoot));
18030
18354
  }
18031
18355
  if (projectRoot) {
@@ -18040,11 +18364,12 @@ function rosterModelIssues(projectRoot, roles) {
18040
18364
  for (const entry of valuesOf(role.value, "roster")) {
18041
18365
  const route = stringValue(objectValue(entry)?.route);
18042
18366
  if (!route) continue;
18043
- const logical = `.kxm/models/${route}.yaml`;
18044
- const file = join2(projectRoot, ".kxm", "models", `${route}.yaml`);
18367
+ const resolved = findYamlBasename(join3(projectRoot, ".kxm", "models"), route, "route") ?? route;
18368
+ const logical = `.kxm/models/${resolved}.yaml`;
18369
+ const file = join3(projectRoot, ".kxm", "models", `${resolved}.yaml`);
18045
18370
  let harness;
18046
18371
  try {
18047
- if (existsSync3(file)) harness = stringValue(parseRestrictedYaml2(readFileSync(file, "utf8"), logical).harness);
18372
+ if (existsSync4(file)) harness = stringValue(parseRestrictedYaml2(readFileSync2(file, "utf8"), logical).harness);
18048
18373
  } catch {
18049
18374
  harness = void 0;
18050
18375
  }
@@ -18070,7 +18395,7 @@ function originHashIssues(projectRoot, models) {
18070
18395
  }
18071
18396
  let actual;
18072
18397
  try {
18073
- actual = createHash3("sha256").update(readFileSync(file, "utf8"), "utf8").digest("hex");
18398
+ actual = createHash3("sha256").update(readFileSync2(file, "utf8"), "utf8").digest("hex");
18074
18399
  } catch (error) {
18075
18400
  const code = error.code;
18076
18401
  if (code === "ENOENT" || code === "EACCES" || code === "EPERM" || code === "EISDIR") {
@@ -18086,7 +18411,7 @@ function originHashIssues(projectRoot, models) {
18086
18411
  return issues;
18087
18412
  }
18088
18413
  function developerCeilings() {
18089
- const script = join2(findKxmRepoRoot(import.meta.url), "scripts", "harness-run.mjs");
18414
+ const script = join3(findKxmRepoRoot(import.meta.url), "scripts", "harness-run.mjs");
18090
18415
  let loaded;
18091
18416
  try {
18092
18417
  loaded = spawnSync2(process.execPath, ["--input-type=module", "-e", `const m = await import(${JSON.stringify(pathToFileURL(script).href)}); process.stdout.write(JSON.stringify({ROUTES:m.ROUTES,NATIVE_PI_BRAKE_PROVIDERS:m.NATIVE_PI_BRAKE_PROVIDERS,PI_ALLOWED_PROVIDERS:m.PI_ALLOWED_PROVIDERS,PI_NATIVE_VENDOR_PROVIDERS:m.PI_NATIVE_VENDOR_PROVIDERS}))`], {
@@ -18113,20 +18438,21 @@ function developerCeilings() {
18113
18438
  }
18114
18439
  function developerRolePolicyIssues(projectRoot) {
18115
18440
  if (resolve(projectRoot) !== findKxmRepoRoot(import.meta.url)) return [];
18116
- const rolesDir = join2(projectRoot, ".kxm", "roles");
18117
- const modelsDir = join2(projectRoot, ".kxm", "models");
18441
+ const lintIssues = lintWorkforce(projectRoot).errors.map((entry) => issue3("semantic", entry.code, entry.file, entry.message));
18442
+ const rolesDir = join3(projectRoot, ".kxm", "roles");
18443
+ const modelsDir = join3(projectRoot, ".kxm", "models");
18118
18444
  const roles = {};
18119
18445
  const models = {};
18120
18446
  const evidence = {};
18121
18447
  const parseIssues = [];
18122
18448
  const readMap = (dir, into, skipInventory) => {
18123
- if (!existsSync3(dir)) return;
18124
- for (const name of readdirSync(dir)) {
18449
+ if (!existsSync4(dir)) return;
18450
+ for (const name of readdirSync2(dir)) {
18125
18451
  if (!name.endsWith(".yaml")) continue;
18126
18452
  const id = basename(name, ".yaml");
18127
18453
  if (skipInventory && id === "inventory") continue;
18128
18454
  try {
18129
- const value = parseRestrictedYaml2(readFileSync(join2(dir, name), "utf8"), `${dir}/${name}`);
18455
+ const value = parseRestrictedYaml2(readFileSync2(join3(dir, name), "utf8"), `${dir}/${name}`);
18130
18456
  into[id] = value;
18131
18457
  } catch (error) {
18132
18458
  if (error instanceof KxmConfigError) {
@@ -18143,12 +18469,12 @@ function developerRolePolicyIssues(projectRoot) {
18143
18469
  const origin = objectValue(model.origin);
18144
18470
  const source = origin ? stringValue(origin.source) : void 0;
18145
18471
  if (!source || evidence[source] !== void 0) continue;
18146
- const evidenceFile = isAbsolute(source) ? source : join2(projectRoot, source);
18147
- if (existsSync3(evidenceFile)) evidence[source] = readFileSync(evidenceFile, "utf8");
18472
+ const evidenceFile = isAbsolute(source) ? source : join3(projectRoot, source);
18473
+ if (existsSync4(evidenceFile)) evidence[source] = readFileSync2(evidenceFile, "utf8");
18148
18474
  }
18149
18475
  const ceilings = developerCeilings();
18150
18476
  if (!ceilings.ok) {
18151
- return [...parseIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/models", `developer ceilings could not be loaded: ${ceilings.detail}`)];
18477
+ return [...parseIssues, ...lintIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/models", `developer ceilings could not be loaded: ${ceilings.detail}`)];
18152
18478
  }
18153
18479
  const result = validatePolicyDraft({ models, roles, evidence }, {
18154
18480
  ceilings: ceilings.ROUTES,
@@ -18157,8 +18483,8 @@ function developerRolePolicyIssues(projectRoot) {
18157
18483
  piNativeVendorProviders: ceilings.PI_NATIVE_VENDOR_PROVIDERS,
18158
18484
  vendorAliases: { "x-ai": "xai", moonshotai: "moonshot", "google-ai": "google", qwen: "alibaba" }
18159
18485
  });
18160
- if (result.ok) return parseIssues;
18161
- return [...parseIssues, ...result.issues.map((entry) => issue3(entry.phase, entry.code, entry.file, entry.message))];
18486
+ if (result.ok) return [...parseIssues, ...lintIssues];
18487
+ return [...parseIssues, ...lintIssues, ...result.issues.map((entry) => issue3(entry.phase, entry.code, entry.file, entry.message))];
18162
18488
  }
18163
18489
  function kxmCanonicalJson(value) {
18164
18490
  if (value === null || typeof value !== "object") return JSON.stringify(value);
@@ -18183,7 +18509,7 @@ function gitEnvironment() {
18183
18509
  }
18184
18510
  function discoverGitRoot(start = process.cwd()) {
18185
18511
  let current = resolve(start);
18186
- if (existsSync3(current) && !lstatSync(current).isDirectory()) current = dirname2(current);
18512
+ if (existsSync4(current) && !lstatSync(current).isDirectory()) current = dirname2(current);
18187
18513
  const result = spawnSync2("git", ["-C", current, "rev-parse", "--show-toplevel"], {
18188
18514
  encoding: "utf8",
18189
18515
  env: gitEnvironment(),
@@ -18192,7 +18518,7 @@ function discoverGitRoot(start = process.cwd()) {
18192
18518
  });
18193
18519
  if (result.status !== 0 || result.error || !result.stdout.trim()) return void 0;
18194
18520
  const root = resolve(result.stdout.trim());
18195
- return existsSync3(root) && lstatSync(root).isDirectory() ? root : void 0;
18521
+ return existsSync4(root) && lstatSync(root).isDirectory() ? root : void 0;
18196
18522
  }
18197
18523
  function assertNoRegisteredGates(options) {
18198
18524
  if ("registeredGates" in options) {
@@ -18217,7 +18543,7 @@ function loadProjectBundle(projectRoot, options, candidate) {
18217
18543
  )));
18218
18544
  }
18219
18545
  const registry = new KxmSchemaRegistry(options.schemasDir);
18220
- const project = readResource(registry, root, join2(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
18546
+ const project = readResource(registry, root, join3(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
18221
18547
  const earlyIssues = [];
18222
18548
  validatePortablePaths(project, earlyIssues);
18223
18549
  const templateProvenance = readTemplateProvenance(registry, root);
@@ -18236,30 +18562,30 @@ function loadProjectBundle(projectRoot, options, candidate) {
18236
18562
  }
18237
18563
  }
18238
18564
  if (earlyIssues.length > 0) throw new KxmConfigError(earlyIssues);
18239
- const agents = listNamedResources(registry, root, join2(root, ".kxm", "agents"), ".kxm/agents", "agent");
18565
+ const agents = listNamedResources(registry, root, join3(root, ".kxm", "agents"), ".kxm/agents", "agent");
18240
18566
  const modelIssues = [];
18241
- const models = listNamedResources(registry, root, join2(root, ".kxm", "models"), ".kxm/models", "model", void 0, modelIssues);
18242
- const roles = listNamedResources(registry, root, join2(root, ".kxm", "roles"), ".kxm/roles", "role", writerRole === void 0 ? void 0 : "writer");
18567
+ const models = listNamedResources(registry, root, join3(root, ".kxm", "models"), ".kxm/models", "model", void 0, modelIssues);
18568
+ const roles = listNamedResources(registry, root, join3(root, ".kxm", "roles"), ".kxm/roles", "role", writerRole === void 0 ? void 0 : "writer");
18243
18569
  if (writerRole !== void 0) {
18244
18570
  const logicalPath = ".kxm/roles/writer.yaml";
18245
- roles.set("writer", { kind: "role", id: "writer", file: join2(root, logicalPath), logicalPath, value: resourceValue(registry, writerRole, logicalPath, "role") });
18571
+ roles.set("writer", { kind: "role", id: "writer", file: join3(root, logicalPath), logicalPath, value: resourceValue(registry, writerRole, logicalPath, "role") });
18246
18572
  }
18247
- const workflows = listNamedResources(registry, root, join2(root, ".kxm", "workflows"), ".kxm/workflows", "workflow", workflowCandidate?.id);
18573
+ const workflows = listNamedResources(registry, root, join3(root, ".kxm", "workflows"), ".kxm/workflows", "workflow", workflowCandidate?.id);
18248
18574
  if (workflowCandidate) {
18249
18575
  const { id, document } = workflowCandidate;
18250
18576
  const logicalPath = `.kxm/workflows/${id}.yaml`;
18251
18577
  if (!resourceIdentifier(id)) fail2("path", "resource_id_invalid", logicalPath, `filename-derived identity ${id} is invalid or platform-reserved`);
18252
18578
  const collision = [...workflows.keys()].find((candidate2) => candidate2.toLocaleLowerCase("en-US") === id.toLocaleLowerCase("en-US"));
18253
18579
  if (collision) fail2("path", "resource_id_collision", logicalPath, `${id} case-folds to existing ${collision}`);
18254
- workflows.set(id, { kind: "workflow", id, file: join2(root, logicalPath), logicalPath, value: resourceValue(registry, document, logicalPath, "workflow") });
18580
+ workflows.set(id, { kind: "workflow", id, file: join3(root, logicalPath), logicalPath, value: resourceValue(registry, document, logicalPath, "workflow") });
18255
18581
  }
18256
- const gatePath = join2(root, ".kxm", "gates.yaml");
18257
- const gateRegistry = existsSync3(gatePath) ? readResource(registry, root, gatePath, ".kxm/gates.yaml", "gate-registry") : void 0;
18582
+ const gatePath = join3(root, ".kxm", "gates.yaml");
18583
+ const gateRegistry = existsSync4(gatePath) ? readResource(registry, root, gatePath, ".kxm/gates.yaml", "gate-registry") : void 0;
18258
18584
  const environments = [];
18259
18585
  const repositories = /* @__PURE__ */ new Map();
18260
18586
  const loadIssues = [];
18261
- const projectEnvironment = join2(root, ".kxm", "project", "env.yaml");
18262
- if (existsSync3(projectEnvironment)) {
18587
+ const projectEnvironment = join3(root, ".kxm", "project", "env.yaml");
18588
+ if (existsSync4(projectEnvironment)) {
18263
18589
  try {
18264
18590
  environments.push(readResource(registry, root, projectEnvironment, ".kxm/project/env.yaml", "environment"));
18265
18591
  } catch (error) {
@@ -18301,7 +18627,7 @@ function loadProjectBundle(projectRoot, options, candidate) {
18301
18627
  if (required2) loadIssues.push(issue3("discovery", "repository_binding_missing", ".kxm/project.yaml", `required repository ${repositoryId} has no portable pathHint or host-local binding`));
18302
18628
  continue;
18303
18629
  }
18304
- if (!existsSync3(binding)) {
18630
+ if (!existsSync4(binding)) {
18305
18631
  if (required2 || hasLocalBinding) loadIssues.push(issue3("discovery", "repository_binding_unavailable", ".kxm/project.yaml", `${hasLocalBinding ? "explicit" : "required"} repository binding ${repositoryId} is unavailable`));
18306
18632
  continue;
18307
18633
  }
@@ -18333,9 +18659,9 @@ function loadProjectBundle(projectRoot, options, candidate) {
18333
18659
  continue;
18334
18660
  }
18335
18661
  seenBindings.set(foldedBinding, repositoryId);
18336
- const repositoryFile = join2(binding, ".kxm", "repo", "repo.yaml");
18662
+ const repositoryFile = join3(binding, ".kxm", "repo", "repo.yaml");
18337
18663
  let definitionValidated = false;
18338
- if (existsSync3(repositoryFile)) {
18664
+ if (existsSync4(repositoryFile)) {
18339
18665
  try {
18340
18666
  const resource = readResource(registry, root, repositoryFile, `.kxm/repositories/${repositoryId}/repo.yaml`, "repository", repositoryId, binding);
18341
18667
  if (resource.value.repositoryId !== repositoryId) {
@@ -18351,8 +18677,8 @@ function loadProjectBundle(projectRoot, options, candidate) {
18351
18677
  } else if (required2 || hasLocalBinding) {
18352
18678
  loadIssues.push(issue3("discovery", "repository_definition_missing", `.kxm/repositories/${repositoryId}/repo.yaml`, `${hasLocalBinding ? "explicit" : "required"} repository ${repositoryId} has no repo.yaml`));
18353
18679
  }
18354
- const environmentFile = join2(binding, ".kxm", "repo", "env.yaml");
18355
- if (existsSync3(environmentFile)) {
18680
+ const environmentFile = join3(binding, ".kxm", "repo", "env.yaml");
18681
+ if (existsSync4(environmentFile)) {
18356
18682
  if (!definitionValidated) {
18357
18683
  loadIssues.push(issue3("reference", "repository_environment_without_definition", `.kxm/repositories/${repositoryId}/env.yaml`, `repository ${repositoryId} environment requires a validated matching repo.yaml`));
18358
18684
  } else {
@@ -18388,21 +18714,21 @@ var LEGACY_CONFIG_FILES = [".kxm/config/agents.json", ".kxm/config/gates.json"];
18388
18714
  function legacyConfigFilesAt(root) {
18389
18715
  const files = [];
18390
18716
  for (const component of [".kxm", ".kxm/config"]) {
18391
- const absolute = join2(root, ...component.split("/"));
18392
- if (existsSync3(absolute) && lstatSync(absolute).isSymbolicLink()) return [component];
18717
+ const absolute = join3(root, ...component.split("/"));
18718
+ if (existsSync4(absolute) && lstatSync(absolute).isSymbolicLink()) return [component];
18393
18719
  }
18394
18720
  for (const candidate of LEGACY_CONFIG_FILES) {
18395
- if (existsSync3(join2(root, ...candidate.split("/")))) files.push(candidate);
18721
+ if (existsSync4(join3(root, ...candidate.split("/")))) files.push(candidate);
18396
18722
  }
18397
- const workflowsDir = join2(root, ".kxm", "config", "workflows");
18398
- if (existsSync3(workflowsDir)) {
18723
+ const workflowsDir = join3(root, ".kxm", "config", "workflows");
18724
+ if (existsSync4(workflowsDir)) {
18399
18725
  const stat = lstatSync(workflowsDir);
18400
18726
  if (stat.isSymbolicLink()) {
18401
18727
  files.push(".kxm/config/workflows");
18402
18728
  return files;
18403
18729
  }
18404
18730
  if (stat.isDirectory()) {
18405
- for (const entry of readdirSync(workflowsDir, { withFileTypes: true }).filter((candidate) => (candidate.isFile() || candidate.isSymbolicLink()) && candidate.name.endsWith(".json")).sort((left, right) => compareCodeUnits4(left.name, right.name))) {
18731
+ for (const entry of readdirSync2(workflowsDir, { withFileTypes: true }).filter((candidate) => (candidate.isFile() || candidate.isSymbolicLink()) && candidate.name.endsWith(".json")).sort((left, right) => compareCodeUnits4(left.name, right.name))) {
18406
18732
  files.push(`.kxm/config/workflows/${entry.name}`);
18407
18733
  }
18408
18734
  }
@@ -18413,11 +18739,11 @@ function legacyConfigFilesAt(root) {
18413
18739
  // plugins/kxm/src/runtime-store.ts
18414
18740
  import { spawnSync as spawnSync3 } from "node:child_process";
18415
18741
  import { createHash as createHash7, randomUUID } from "node:crypto";
18416
- import { existsSync as existsSync6, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, realpathSync as realpathSync3, statSync, writeFileSync as writeFileSync2 } from "node:fs";
18742
+ import { existsSync as existsSync7, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, realpathSync as realpathSync3, statSync, writeFileSync as writeFileSync2 } from "node:fs";
18417
18743
  import { dirname as dirname5, isAbsolute as isAbsolute4, resolve as resolve6 } from "node:path";
18418
18744
 
18419
18745
  // plugins/kxm/src/sqlite.ts
18420
- import { existsSync as existsSync4 } from "node:fs";
18746
+ import { existsSync as existsSync5 } from "node:fs";
18421
18747
  import { createRequire } from "node:module";
18422
18748
  import { resolve as resolve2 } from "node:path";
18423
18749
  import { pathToFileURL as pathToFileURL2 } from "node:url";
@@ -18458,7 +18784,7 @@ var DatabaseSync = class {
18458
18784
  }
18459
18785
  };
18460
18786
  function openReadOnlyDatabase(path) {
18461
- if (existsSync4(`${path}-wal`)) return new DatabaseSync(path, { readOnly: true });
18787
+ if (existsSync5(`${path}-wal`)) return new DatabaseSync(path, { readOnly: true });
18462
18788
  const uri = pathToFileURL2(resolve2(path));
18463
18789
  uri.searchParams.set("immutable", "1");
18464
18790
  return new DatabaseSync(uri.href, { readOnly: true });
@@ -18467,11 +18793,11 @@ function openReadOnlyDatabase(path) {
18467
18793
  // plugins/kxm/src/runtime-paths.ts
18468
18794
  import { createHash as createHash4 } from "node:crypto";
18469
18795
  import { realpathSync as realpathSync2 } from "node:fs";
18470
- import { join as join4, resolve as resolve4 } from "node:path";
18796
+ import { join as join5, resolve as resolve4 } from "node:path";
18471
18797
 
18472
18798
  // plugins/kxm/src/bindings.ts
18473
18799
  import { homedir } from "node:os";
18474
- import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, parse, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
18800
+ import { dirname as dirname3, isAbsolute as isAbsolute2, join as join4, parse, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
18475
18801
  var MAX_BINDING_RECORD_BYTES = 256 * 1024;
18476
18802
  var BINDING_LABEL = "Runtime-local repository bindings";
18477
18803
  function bindingIssue(phase, code, message) {
@@ -18491,24 +18817,24 @@ function kxmUserStateRoot(options = {}) {
18491
18817
  }
18492
18818
  if (platform === "win32") {
18493
18819
  const localAppData = env.LOCALAPPDATA?.trim();
18494
- const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join3(home, "AppData", "Local");
18820
+ const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join4(home, "AppData", "Local");
18495
18821
  return resolve3(base2, "KXM");
18496
18822
  }
18497
18823
  if (platform === "darwin") return resolve3(home, "Library", "Application Support", "KXM");
18498
18824
  const xdgState = env.XDG_STATE_HOME?.trim();
18499
- const base = xdgState && isAbsolute2(xdgState) ? xdgState : join3(home, ".local", "state");
18825
+ const base = xdgState && isAbsolute2(xdgState) ? xdgState : join4(home, ".local", "state");
18500
18826
  return resolve3(base, "kxm");
18501
18827
  }
18502
18828
 
18503
18829
  // plugins/kxm/src/runtime-paths.ts
18504
18830
  function kxmRuntimePaths(options = {}) {
18505
18831
  const stateRoot = options.stateRoot ? resolve4(options.stateRoot) : kxmUserStateRoot({ ...options.env ? { env: options.env } : {}, ...options.homeDir ? { homeDir: options.homeDir } : {} });
18506
- const runtimeDir = join4(stateRoot, "runtime");
18832
+ const runtimeDir = join5(stateRoot, "runtime");
18507
18833
  return {
18508
18834
  stateRoot,
18509
18835
  runtimeDir,
18510
- registryDb: join4(runtimeDir, "registry.db"),
18511
- projectsDir: join4(runtimeDir, "projects")
18836
+ registryDb: join5(runtimeDir, "registry.db"),
18837
+ projectsDir: join5(runtimeDir, "projects")
18512
18838
  };
18513
18839
  }
18514
18840
  function projectRuntimeKey(projectRoot) {
@@ -18522,7 +18848,7 @@ function projectRuntimeKey(projectRoot) {
18522
18848
  return createHash4("sha256").update(folded, "utf8").digest("hex").slice(0, 24);
18523
18849
  }
18524
18850
  function kxmProjectRunEventsPath(projectRoot, env) {
18525
- return join4(kxmRuntimePaths({ env }).projectsDir, projectRuntimeKey(projectRoot), "run-events.db");
18851
+ return join5(kxmRuntimePaths({ env }).projectsDir, projectRuntimeKey(projectRoot), "run-events.db");
18526
18852
  }
18527
18853
 
18528
18854
  // plugins/kxm/src/sync-transform.ts
@@ -18861,22 +19187,22 @@ import { createHash as createHash6, randomBytes } from "node:crypto";
18861
19187
  import {
18862
19188
  chmodSync,
18863
19189
  copyFileSync,
18864
- existsSync as existsSync5,
19190
+ existsSync as existsSync6,
18865
19191
  lstatSync as lstatSync2,
18866
19192
  mkdirSync,
18867
- readdirSync as readdirSync2,
18868
- readFileSync as readFileSync2,
19193
+ readdirSync as readdirSync3,
19194
+ readFileSync as readFileSync3,
18869
19195
  unlinkSync,
18870
19196
  writeFileSync
18871
19197
  } from "node:fs";
18872
- import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute3, join as join5, relative as relative3, resolve as resolve5, sep as sep3 } from "node:path";
19198
+ import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute3, join as join6, relative as relative3, resolve as resolve5, sep as sep3 } from "node:path";
18873
19199
  function databaseError(code, file, message) {
18874
19200
  const issue4 = { phase: "semantic", code, file, message };
18875
19201
  return new KxmConfigError([issue4]);
18876
19202
  }
18877
19203
  function checkedParent(path, description) {
18878
19204
  const parent = dirname4(path);
18879
- if (!existsSync5(parent)) mkdirSync(parent, { recursive: true, mode: 448 });
19205
+ if (!existsSync6(parent)) mkdirSync(parent, { recursive: true, mode: 448 });
18880
19206
  const stat = lstatSync2(parent, { throwIfNoEntry: false });
18881
19207
  if (!stat || stat.isSymbolicLink() || !stat.isDirectory()) {
18882
19208
  throw databaseError("runtime_path_invalid", description, `${description} parent must be a regular directory, not a link`);
@@ -19097,7 +19423,7 @@ function checkIntegrity(database) {
19097
19423
  return rows.length === 1 && rows[0]?.integrity_check === "ok";
19098
19424
  }
19099
19425
  function fileSha256(filePath) {
19100
- const bytes = readFileSync2(filePath);
19426
+ const bytes = readFileSync3(filePath);
19101
19427
  return `sha256:${createHash6("sha256").update(bytes).digest("hex")}`;
19102
19428
  }
19103
19429
  function backupDatabaseFile(sourcePath2, targetPath, storeId) {
@@ -19108,7 +19434,7 @@ function backupDatabaseFile(sourcePath2, targetPath, storeId) {
19108
19434
  throw databaseError("runtime_path_invalid", resolvedSource, `source database ${resolvedSource} must be a regular file, not a link or directory`);
19109
19435
  }
19110
19436
  checkedParent(resolvedTarget, "backup target");
19111
- if (existsSync5(resolvedTarget)) {
19437
+ if (existsSync6(resolvedTarget)) {
19112
19438
  unlinkSync(resolvedTarget);
19113
19439
  }
19114
19440
  const sourceDb = new DatabaseSync(resolvedSource);
@@ -19186,7 +19512,7 @@ function restoreDatabaseFile(backupPath, targetPath, storeId, expectedSchemaVers
19186
19512
  }
19187
19513
  checkedParent(resolvedTarget, "restore target");
19188
19514
  for (const file of [resolvedTarget, `${resolvedTarget}-wal`, `${resolvedTarget}-shm`]) {
19189
- if (existsSync5(file)) {
19515
+ if (existsSync6(file)) {
19190
19516
  try {
19191
19517
  unlinkSync(file);
19192
19518
  } catch {
@@ -19231,14 +19557,14 @@ function pushStore(stores, storeId, sourcePath2) {
19231
19557
  stores.push({ storeId, sourcePath: sourcePath2, maxSupportedVersion: kxmBackupCeiling(storeId) });
19232
19558
  }
19233
19559
  function pushEventStore(stores, files, paths, key) {
19234
- const dbPath = join5(paths.projectsDir, key, "run-events.db");
19235
- if (!existsSync5(dbPath)) return;
19560
+ const dbPath = join6(paths.projectsDir, key, "run-events.db");
19561
+ if (!existsSync6(dbPath)) return;
19236
19562
  const safe = key.replace(/[^a-zA-Z0-9_.-]/g, "_");
19237
19563
  let storeId = `events:${safe}`;
19238
19564
  if (stores.some((store) => store.storeId === storeId)) storeId = `events:runtime:${safe}`;
19239
19565
  pushStore(stores, storeId, dbPath);
19240
19566
  const sidecar = `${dbPath}.run-prompts.json`;
19241
- if (existsSync5(sidecar)) {
19567
+ if (existsSync6(sidecar)) {
19242
19568
  const id = `${storeId}:run-prompts`;
19243
19569
  if (!files.some((file) => file.id === id || file.sourcePath === sidecar)) {
19244
19570
  files.push({ id, sourcePath: sidecar });
@@ -19256,14 +19582,14 @@ function discoverUserRuntime(runtimeProjectKey, options, stores, files) {
19256
19582
  pushEventStore(stores, files, paths, runtimeProjectKey);
19257
19583
  return paths.stateRoot;
19258
19584
  }
19259
- if (existsSync5(paths.registryDb)) {
19585
+ if (existsSync6(paths.registryDb)) {
19260
19586
  const storeId = stores.some((store) => store.storeId === "registry") ? "runtime-registry" : "registry";
19261
19587
  pushStore(stores, storeId, paths.registryDb);
19262
19588
  }
19263
- if (!existsSync5(paths.projectsDir)) return paths.stateRoot;
19589
+ if (!existsSync6(paths.projectsDir)) return paths.stateRoot;
19264
19590
  let entries;
19265
19591
  try {
19266
- entries = readdirSync2(paths.projectsDir, { withFileTypes: true });
19592
+ entries = readdirSync3(paths.projectsDir, { withFileTypes: true });
19267
19593
  } catch {
19268
19594
  return paths.stateRoot;
19269
19595
  }
@@ -19276,19 +19602,19 @@ function discoverBackupSources(projectRoot, options = {}) {
19276
19602
  const root = resolve5(projectRoot);
19277
19603
  const stores = [];
19278
19604
  const files = [];
19279
- const hubPath = options.hubDataPath ? resolve5(options.hubDataPath) : join5(root, ".kxm", "state", "kxm.db");
19280
- if (existsSync5(hubPath)) pushStore(stores, "hub-store", hubPath);
19281
- const registryPath = join5(root, ".kxm", "runtime", "registry.db");
19282
- if (existsSync5(registryPath)) pushStore(stores, "registry", registryPath);
19283
- const bindingsPath = join5(root, ".kxm", "runtime", "bindings.db");
19284
- if (existsSync5(bindingsPath)) pushStore(stores, "binding-store", bindingsPath);
19285
- const eventsDir = join5(root, ".kxm", "runtime", "events");
19286
- if (existsSync5(eventsDir)) {
19287
- const entries = readdirSync2(eventsDir, { withFileTypes: true });
19605
+ const hubPath = options.hubDataPath ? resolve5(options.hubDataPath) : join6(root, ".kxm", "state", "kxm.db");
19606
+ if (existsSync6(hubPath)) pushStore(stores, "hub-store", hubPath);
19607
+ const registryPath = join6(root, ".kxm", "runtime", "registry.db");
19608
+ if (existsSync6(registryPath)) pushStore(stores, "registry", registryPath);
19609
+ const bindingsPath = join6(root, ".kxm", "runtime", "bindings.db");
19610
+ if (existsSync6(bindingsPath)) pushStore(stores, "binding-store", bindingsPath);
19611
+ const eventsDir = join6(root, ".kxm", "runtime", "events");
19612
+ if (existsSync6(eventsDir)) {
19613
+ const entries = readdirSync3(eventsDir, { withFileTypes: true });
19288
19614
  for (const entry of entries) {
19289
19615
  if (entry.isFile() && entry.name.endsWith(".db")) {
19290
19616
  const key = entry.name.replace(/\.db$/, "").replace(/[^a-zA-Z0-9_.-]/g, "_");
19291
- pushStore(stores, `events:${key}`, join5(eventsDir, entry.name));
19617
+ pushStore(stores, `events:${key}`, join6(eventsDir, entry.name));
19292
19618
  }
19293
19619
  }
19294
19620
  }
@@ -19303,7 +19629,7 @@ function backupPlainFile(sourcePath2, targetPath, id) {
19303
19629
  throw databaseError("runtime_path_invalid", resolvedSource, `backup file ${resolvedSource} must be a regular file, not a link or directory`);
19304
19630
  }
19305
19631
  checkedParent(targetPath, "backup target");
19306
- if (existsSync5(targetPath)) unlinkSync(targetPath);
19632
+ if (existsSync6(targetPath)) unlinkSync(targetPath);
19307
19633
  copyFileSync(resolvedSource, targetPath);
19308
19634
  try {
19309
19635
  chmodSync(targetPath, 384);
@@ -19327,7 +19653,7 @@ function backupFilename(sourcePath2, id, used) {
19327
19653
  }
19328
19654
  function restorePlainFile(backupFilePath, targetPath) {
19329
19655
  checkedParent(targetPath, "restore target");
19330
- if (existsSync5(targetPath)) unlinkSync(targetPath);
19656
+ if (existsSync6(targetPath)) unlinkSync(targetPath);
19331
19657
  copyFileSync(backupFilePath, targetPath);
19332
19658
  try {
19333
19659
  chmodSync(targetPath, 384);
@@ -19352,7 +19678,7 @@ function planBackup(options = {}) {
19352
19678
  }
19353
19679
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
19354
19680
  const timestamp = createdAt.replace(/[:.]/g, "-");
19355
- const outDir = options.outDir ? resolve5(options.outDir) : join5(projectRoot, ".kxm", "backups", `backup-${timestamp}`);
19681
+ const outDir = options.outDir ? resolve5(options.outDir) : join6(projectRoot, ".kxm", "backups", `backup-${timestamp}`);
19356
19682
  const usedFilenames = /* @__PURE__ */ new Set();
19357
19683
  const stores = discovered.stores.map((store) => ({
19358
19684
  storeId: store.storeId,
@@ -19378,7 +19704,7 @@ function planBackup(options = {}) {
19378
19704
  function createBackup(options = {}) {
19379
19705
  const { projectRoot, outDir, createdAt, scope, stateRoot, runtimeProjectKey, stores, files } = planBackup(options);
19380
19706
  const backupId = `bk_${randomBytes(8).toString("hex")}`;
19381
- if (!existsSync5(outDir)) {
19707
+ if (!existsSync6(outDir)) {
19382
19708
  mkdirSync(outDir, { recursive: true, mode: 448 });
19383
19709
  }
19384
19710
  const backedUpStores = [];
@@ -19386,14 +19712,14 @@ function createBackup(options = {}) {
19386
19712
  const omitted = [];
19387
19713
  for (const store of stores) {
19388
19714
  try {
19389
- backedUpStores.push(backupDatabaseFile(store.sourcePath, join5(outDir, store.backupFile), store.storeId));
19715
+ backedUpStores.push(backupDatabaseFile(store.sourcePath, join6(outDir, store.backupFile), store.storeId));
19390
19716
  } catch {
19391
19717
  omitted.push(store.storeId);
19392
19718
  }
19393
19719
  }
19394
19720
  for (const file of files) {
19395
19721
  try {
19396
- backedUpFiles.push(backupPlainFile(file.sourcePath, join5(outDir, file.backupFile), file.id));
19722
+ backedUpFiles.push(backupPlainFile(file.sourcePath, join6(outDir, file.backupFile), file.id));
19397
19723
  } catch {
19398
19724
  omitted.push(file.id);
19399
19725
  }
@@ -19429,7 +19755,7 @@ function createBackup(options = {}) {
19429
19755
  const manifestSha256 = `sha256:${createHash6("sha256").update(manifestJson, "utf8").digest("hex")}`;
19430
19756
  manifest.manifestSha256 = manifestSha256;
19431
19757
  const finalJson = JSON.stringify(manifest, null, 2) + "\n";
19432
- const manifestPath = join5(outDir, "manifest.json");
19758
+ const manifestPath = join6(outDir, "manifest.json");
19433
19759
  writeFileSync(manifestPath, finalJson, "utf8");
19434
19760
  return { manifest, outDir };
19435
19761
  }
@@ -19443,16 +19769,16 @@ function restoreTarget(manifest, sourcePath2, id, options, currentStateRoot) {
19443
19769
  const stateRel = pathUnder(manifest.stateRoot, sourcePath2);
19444
19770
  const projectRel = pathUnder(manifest.projectRoot, sourcePath2);
19445
19771
  if (stateRel !== void 0 && (projectRel === void 0 || stateRel.length <= projectRel.length)) {
19446
- const ownEvents = manifest.runtimeProjectKey !== void 0 ? join5("runtime", "projects", manifest.runtimeProjectKey, "run-events.db") : void 0;
19772
+ const ownEvents = manifest.runtimeProjectKey !== void 0 ? join6("runtime", "projects", manifest.runtimeProjectKey, "run-events.db") : void 0;
19447
19773
  const own2 = ownEvents !== void 0 && (stateRel === ownEvents || stateRel === `${ownEvents}.run-prompts.json`);
19448
19774
  if (own2 && !options.allProjects && options.projectRoot !== void 0) {
19449
19775
  const eventsPath = kxmProjectRunEventsPath(resolve5(options.projectRoot), options.env ?? process.env);
19450
19776
  return { targetPath: stateRel === ownEvents ? eventsPath : `${eventsPath}.run-prompts.json`, machineWide: false };
19451
19777
  }
19452
- return { targetPath: join5(currentStateRoot(), stateRel), machineWide: !own2 };
19778
+ return { targetPath: join6(currentStateRoot(), stateRel), machineWide: !own2 };
19453
19779
  }
19454
19780
  if (projectRel !== void 0) {
19455
- return { targetPath: options.projectRoot ? join5(resolve5(options.projectRoot), projectRel) : sourcePath2, machineWide: false };
19781
+ return { targetPath: options.projectRoot ? join6(resolve5(options.projectRoot), projectRel) : sourcePath2, machineWide: false };
19456
19782
  }
19457
19783
  return { targetPath: sourcePath2, machineWide: id !== "hub-store" };
19458
19784
  }
@@ -19463,13 +19789,13 @@ function planRestore(manifestPathOrDir, options = {}) {
19463
19789
  throw databaseError("runtime_path_invalid", manifestPath, `manifest path ${manifestPath} does not exist`);
19464
19790
  }
19465
19791
  if (stat.isDirectory()) {
19466
- manifestPath = join5(manifestPath, "manifest.json");
19792
+ manifestPath = join6(manifestPath, "manifest.json");
19467
19793
  }
19468
- if (!existsSync5(manifestPath)) {
19794
+ if (!existsSync6(manifestPath)) {
19469
19795
  throw databaseError("runtime_path_invalid", manifestPath, `backup manifest ${manifestPath} not found`);
19470
19796
  }
19471
19797
  const manifestDir = dirname4(manifestPath);
19472
- const rawText = readFileSync2(manifestPath, "utf8");
19798
+ const rawText = readFileSync3(manifestPath, "utf8");
19473
19799
  let manifest;
19474
19800
  try {
19475
19801
  manifest = JSON.parse(rawText);
@@ -19487,8 +19813,8 @@ function planRestore(manifestPathOrDir, options = {}) {
19487
19813
  const machineWide = [];
19488
19814
  const stores = [];
19489
19815
  for (const store of manifest.stores) {
19490
- const backupFilePath = join5(manifestDir, store.backupFile);
19491
- if (!existsSync5(backupFilePath)) {
19816
+ const backupFilePath = join6(manifestDir, store.backupFile);
19817
+ if (!existsSync6(backupFilePath)) {
19492
19818
  throw databaseError("restore_file_missing", backupFilePath, `backup file ${store.backupFile} missing from ${manifestDir}`);
19493
19819
  }
19494
19820
  const actualSha256 = fileSha256(backupFilePath);
@@ -19513,8 +19839,8 @@ function planRestore(manifestPathOrDir, options = {}) {
19513
19839
  }
19514
19840
  const files = [];
19515
19841
  for (const file of manifest.files ?? []) {
19516
- const backupFilePath = join5(manifestDir, file.backupFile);
19517
- if (!existsSync5(backupFilePath)) {
19842
+ const backupFilePath = join6(manifestDir, file.backupFile);
19843
+ if (!existsSync6(backupFilePath)) {
19518
19844
  throw databaseError("restore_file_missing", backupFilePath, `backup file ${file.backupFile} missing from ${manifestDir}`);
19519
19845
  }
19520
19846
  const actualSha256 = fileSha256(backupFilePath);
@@ -19574,7 +19900,7 @@ function runtimeError(code, file, message) {
19574
19900
  }
19575
19901
  function projectRuntimeOwnsRun(projectRoot, runId, env) {
19576
19902
  const path = kxmProjectRunEventsPath(projectRoot, env);
19577
- if (!existsSync6(path)) return false;
19903
+ if (!existsSync7(path)) return false;
19578
19904
  const database = openReadOnlyDatabase(path);
19579
19905
  try {
19580
19906
  database.exec("PRAGMA busy_timeout = 5000");
@@ -20438,9 +20764,9 @@ var KxmRunEventStore = class {
20438
20764
  }
20439
20765
  readRunPrompts() {
20440
20766
  const sidecar = this.runPromptSidecarPath();
20441
- if (!existsSync6(sidecar)) return {};
20767
+ if (!existsSync7(sidecar)) return {};
20442
20768
  try {
20443
- const parsed = JSON.parse(readFileSync3(sidecar, "utf8"));
20769
+ const parsed = JSON.parse(readFileSync4(sidecar, "utf8"));
20444
20770
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
20445
20771
  return Object.fromEntries(
20446
20772
  Object.entries(parsed).filter((entry) => typeof entry[1] === "string")
@@ -22884,7 +23210,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
22884
23210
  const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
22885
23211
  const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
22886
23212
  const assignments = compileAssignments(step, id, agent, sink);
22887
- const join23 = compileJoin(step, id, sink);
23213
+ const join24 = compileJoin(step, id, sink);
22888
23214
  const requiredEvidence = compileEvidence(step, id, sink);
22889
23215
  const transitions = compileTransitions(step, id, index, stepIndex, sink);
22890
23216
  const outcomes = Object.keys(transitions).sort(compareCodeUnits5);
@@ -22912,7 +23238,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
22912
23238
  transitions: orderedTransitions,
22913
23239
  requiresPlanHash: requirePlanHash.includes(id),
22914
23240
  assignments,
22915
- join: join23
23241
+ join: join24
22916
23242
  };
22917
23243
  if (kind === "agent" || kind === "moa") {
22918
23244
  if (!agent) return void 0;
@@ -22962,15 +23288,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
22962
23288
  };
22963
23289
  }
22964
23290
  function compileJoin(step, stepId, sink) {
22965
- const join23 = objectValue2(step.join);
22966
- if (!join23) return { strategy: "all" };
22967
- const declared = stringValue2(join23.strategy);
23291
+ const join24 = objectValue2(step.join);
23292
+ if (!join24) return { strategy: "all" };
23293
+ const declared = stringValue2(join24.strategy);
22968
23294
  const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
22969
- const minimumPassed = compileOptionalCount(join23.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
23295
+ const minimumPassed = compileOptionalCount(join24.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
22970
23296
  const compiled = {
22971
23297
  strategy,
22972
23298
  ...minimumPassed !== void 0 ? { minimumPassed } : {},
22973
- ...typeof join23.cancelRemaining === "boolean" ? { cancelRemaining: join23.cancelRemaining } : {}
23299
+ ...typeof join24.cancelRemaining === "boolean" ? { cancelRemaining: join24.cancelRemaining } : {}
22974
23300
  };
22975
23301
  return compiled;
22976
23302
  }
@@ -24389,11 +24715,11 @@ function kxmToolPolicyRevision(bundle) {
24389
24715
  return sha256Of(kxmCanonicalJson({ policies, gateRegistry: bundle.gateRegistry?.value ?? null }));
24390
24716
  }
24391
24717
  function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Set()) {
24392
- if (!existsSync7(dir)) return [];
24393
- const entries = readdirSync3(dir, { withFileTypes: true });
24718
+ if (!existsSync8(dir)) return [];
24719
+ const entries = readdirSync4(dir, { withFileTypes: true });
24394
24720
  const results = [];
24395
24721
  for (const entry of entries) {
24396
- const fullPath = join7(dir, entry.name);
24722
+ const fullPath = join8(dir, entry.name);
24397
24723
  if (entry.isDirectory()) {
24398
24724
  if (ignoreSubdirs.has(entry.name)) continue;
24399
24725
  results.push(...collectMemoryFiles(fullPath, baseDir, ignoreSubdirs));
@@ -24406,19 +24732,19 @@ function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Se
24406
24732
  }
24407
24733
  function computeKxmMemoryRevision(bundle, options = {}) {
24408
24734
  const hash = createHash9("sha256");
24409
- const memoryDir = options.memoryDir ?? join7(bundle.projectRoot, ".kxm", "memory");
24735
+ const memoryDir = options.memoryDir ?? join8(bundle.projectRoot, ".kxm", "memory");
24410
24736
  const memoryFiles = collectMemoryFiles(memoryDir, memoryDir, /* @__PURE__ */ new Set(["candidates"])).sort((left, right) => compareCodeUnits6(left.relPath, right.relPath));
24411
24737
  for (const file of memoryFiles) {
24412
24738
  hash.update(`memory:${file.relPath}\0`, "utf8");
24413
- hash.update(readFileSync4(file.fullPath));
24739
+ hash.update(readFileSync5(file.fullPath));
24414
24740
  hash.update("\0", "utf8");
24415
24741
  }
24416
- const skillsDir = options.skillsDir ?? join7(bundle.projectRoot, ".kxm", "skills");
24417
- const promotedSkillsDir = join7(skillsDir, "promoted");
24742
+ const skillsDir = options.skillsDir ?? join8(bundle.projectRoot, ".kxm", "skills");
24743
+ const promotedSkillsDir = join8(skillsDir, "promoted");
24418
24744
  const skillFiles = collectMemoryFiles(promotedSkillsDir, promotedSkillsDir).sort((left, right) => compareCodeUnits6(left.relPath, right.relPath));
24419
24745
  for (const file of skillFiles) {
24420
24746
  hash.update(`skill:${file.relPath}\0`, "utf8");
24421
- hash.update(readFileSync4(file.fullPath));
24747
+ hash.update(readFileSync5(file.fullPath));
24422
24748
  hash.update("\0", "utf8");
24423
24749
  }
24424
24750
  if (options.promotedState && options.promotedState.length > 0) {
@@ -24504,7 +24830,7 @@ function openKxmRuntimeContext(projectRoot, options) {
24504
24830
  now: options.now ?? (/* @__PURE__ */ new Date()).toISOString(),
24505
24831
  ...options.logger ? { logger: options.logger } : {}
24506
24832
  });
24507
- const eventStore = new KxmRunEventStore(join7(paths.projectsDir, registration.projectKey, "run-events.db"));
24833
+ const eventStore = new KxmRunEventStore(join8(paths.projectsDir, registration.projectKey, "run-events.db"));
24508
24834
  registerKxmRuntimeHandle(eventStore.path);
24509
24835
  return {
24510
24836
  registry,
@@ -24565,7 +24891,7 @@ function acceptKxmRun(context, bundle, request, options = {}) {
24565
24891
  const commandId = request.commandId ?? newKxmCommandId();
24566
24892
  const now = options.now ?? (/* @__PURE__ */ new Date()).toISOString();
24567
24893
  const monotonicNs = options.monotonicNs ?? kxmMonotonicNs();
24568
- const workflow = bundle.workflows.get(request.workflowId);
24894
+ const workflow = lookupKxmResource(bundle.workflows.values(), request.workflowId, "workflow");
24569
24895
  if (!workflow) {
24570
24896
  throw runtimeError("run_workflow_unknown", ".kxm/workflows", `workflow ${request.workflowId} does not exist in this project`);
24571
24897
  }
@@ -24763,7 +25089,7 @@ function cancelKxmRun(context, runId, options = {}) {
24763
25089
  const events = [];
24764
25090
  let sequence = context.eventStore.nextSequence(runId);
24765
25091
  let nextMono = monotonicNs;
24766
- const push = (eventType, payload) => {
25092
+ const push2 = (eventType, payload) => {
24767
25093
  const event = {
24768
25094
  ...kxmEventBase(context, run, now, nextMono, commandId),
24769
25095
  eventId: newKxmEventId(),
@@ -24787,11 +25113,11 @@ function cancelKxmRun(context, runId, options = {}) {
24787
25113
  }
24788
25114
  cancelPayload.budget = options.budget;
24789
25115
  }
24790
- push("run.cancel_requested", cancelPayload);
25116
+ push2("run.cancel_requested", cancelPayload);
24791
25117
  let status = "cancelled";
24792
25118
  if (folded.status === "running" && activeAttempt) {
24793
25119
  status = "cancelling";
24794
- push("run.status_changed", { status: "cancelling", reason: cancelReason });
25120
+ push2("run.status_changed", { status: "cancelling", reason: cancelReason });
24795
25121
  const attemptIds = new Set(kxmFoldPanelAttemptIds(folded.currentStep));
24796
25122
  if (folded.currentStep?.attemptId) attemptIds.add(folded.currentStep.attemptId);
24797
25123
  for (const attemptId of attemptIds) {
@@ -24804,7 +25130,7 @@ function cancelKxmRun(context, runId, options = {}) {
24804
25130
  abortControllers.push(owned.controller);
24805
25131
  }
24806
25132
  } else if (folded.status === "blocked_uncertain") {
24807
- push("run.status_changed", { status: "cancelling", reason: cancelReason });
25133
+ push2("run.status_changed", { status: "cancelling", reason: cancelReason });
24808
25134
  const attemptId = folded.currentStep?.attemptId;
24809
25135
  if (attemptId) {
24810
25136
  const capability = context.eventStore.capabilityByAttempt(attemptId);
@@ -24816,13 +25142,13 @@ function cancelKxmRun(context, runId, options = {}) {
24816
25142
  for (const owned of kxmAttemptControllers(context.eventStore.path, runId)) {
24817
25143
  abortControllers.push(owned.controller);
24818
25144
  }
24819
- push("run.status_changed", { status: "cancelled", reason: cancelReason });
25145
+ push2("run.status_changed", { status: "cancelled", reason: cancelReason });
24820
25146
  status = "cancelled";
24821
25147
  } else if (folded.status === "running" && !activeAttempt) {
24822
- push("run.status_changed", { status: "cancelling", reason: cancelReason });
24823
- push("run.status_changed", { status: "cancelled", reason: cancelReason });
25148
+ push2("run.status_changed", { status: "cancelling", reason: cancelReason });
25149
+ push2("run.status_changed", { status: "cancelled", reason: cancelReason });
24824
25150
  } else {
24825
- push("run.status_changed", { status: "cancelled", reason: cancelReason });
25151
+ push2("run.status_changed", { status: "cancelled", reason: cancelReason });
24826
25152
  }
24827
25153
  for (const event of events) context.eventStore.appendEvent(event);
24828
25154
  const nextState = foldStoredKxmRun(context, run);
@@ -24854,15 +25180,15 @@ function assertKxmConfigError(error) {
24854
25180
  // plugins/kxm/src/runtime-supervisor.ts
24855
25181
  import { spawn as spawn3 } from "node:child_process";
24856
25182
  import { createHash as createHash16, createHmac, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
24857
- import { chmodSync as chmodSync2, existsSync as existsSync16, lstatSync as lstatSync6, mkdirSync as mkdirSync9, readFileSync as readFileSync13, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "node:fs";
25183
+ import { chmodSync as chmodSync2, existsSync as existsSync17, lstatSync as lstatSync6, mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "node:fs";
24858
25184
  import { createServer } from "node:http";
24859
- import { dirname as dirname11, isAbsolute as isAbsolute8, join as join18 } from "node:path";
25185
+ import { dirname as dirname11, isAbsolute as isAbsolute8, join as join19 } from "node:path";
24860
25186
 
24861
25187
  // plugins/kxm/src/oneshot-evidence.ts
24862
25188
  import { createHash as createHash10, randomUUID as randomUUID3 } from "node:crypto";
24863
- import { lstatSync as lstatSync4, readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
25189
+ import { lstatSync as lstatSync4, readdirSync as readdirSync5, readFileSync as readFileSync6 } from "node:fs";
24864
25190
  import { lstat, mkdir, open, rename } from "node:fs/promises";
24865
- import { join as join8 } from "node:path";
25191
+ import { join as join9 } from "node:path";
24866
25192
  var ONESHOT_EVIDENCE_SCHEMA = "kxm.oneshot-evidence.v2";
24867
25193
  var RETIRED_ONESHOT_EVIDENCE_SCHEMAS = /* @__PURE__ */ new Set(["kxm.oneshot-evidence.v1"]);
24868
25194
  var TEXT_LIMIT = 4 * 1024 * 1024;
@@ -24886,12 +25212,12 @@ function parseOneShotEvidenceRecord(bytes) {
24886
25212
  return parsed;
24887
25213
  }
24888
25214
  function oneShotEvidenceRoot() {
24889
- return join8(kxmUserStateRoot(), "runtime", "oneshot-evidence");
25215
+ return join9(kxmUserStateRoot(), "runtime", "oneshot-evidence");
24890
25216
  }
24891
25217
  function readOneShotObservedChildExit(runId, attemptId, root = oneShotEvidenceRoot()) {
24892
25218
  let names3;
24893
25219
  try {
24894
- names3 = readdirSync4(root);
25220
+ names3 = readdirSync5(root);
24895
25221
  } catch {
24896
25222
  return void 0;
24897
25223
  }
@@ -24900,13 +25226,13 @@ function readOneShotObservedChildExit(runId, attemptId, root = oneShotEvidenceRo
24900
25226
  const capped = names3.slice(0, 4096);
24901
25227
  for (const name of capped) {
24902
25228
  if (!name.startsWith("evd_")) continue;
24903
- const dir = join8(root, name);
25229
+ const dir = join9(root, name);
24904
25230
  try {
24905
25231
  const info = lstatSync4(dir);
24906
25232
  if (!info.isDirectory() || info.isSymbolicLink()) continue;
24907
- const intent = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "intent.json"), "utf8"));
25233
+ const intent = parseOneShotEvidenceRecord(readFileSync6(join9(dir, "intent.json"), "utf8"));
24908
25234
  if (intent.runId !== runId || intent.attemptId !== attemptId) continue;
24909
- const result = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "result.json"), "utf8"));
25235
+ const result = parseOneShotEvidenceRecord(readFileSync6(join9(dir, "result.json"), "utf8"));
24910
25236
  if (result.observedChildExit === true) seenTrue = true;
24911
25237
  else if (result.observedChildExit === false) seenFalse = true;
24912
25238
  } catch {
@@ -24923,7 +25249,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
24923
25249
  throw new Error("oneshot_evidence_root_not_private");
24924
25250
  }
24925
25251
  const id = `evd_${randomUUID3().replaceAll("-", "")}`;
24926
- const dir = join8(root, id);
25252
+ const dir = join9(root, id);
24927
25253
  await mkdir(dir, { mode: 448 });
24928
25254
  const secrets = [...new Set(sensitive.filter((value) => value.length >= 8))].sort((a, b) => b.length - a.length);
24929
25255
  const redact = (value) => {
@@ -24943,7 +25269,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
24943
25269
  const bytes = JSON.stringify(value);
24944
25270
  if (Buffer.byteLength(bytes) > RECORD_LIMIT) throw new Error("oneshot_evidence_record_limit");
24945
25271
  parseOneShotEvidenceRecord(bytes);
24946
- const target = join8(dir, name);
25272
+ const target = join9(dir, name);
24947
25273
  const partial = `${target}.partial`;
24948
25274
  const file = await open(partial, "wx", 384);
24949
25275
  try {
@@ -25009,10 +25335,10 @@ async function beginOneShotEvidence(root, intent, sensitive) {
25009
25335
  }
25010
25336
 
25011
25337
  // plugins/kxm/src/prices.ts
25012
- var import_yaml3 = __toESM(require_dist(), 1);
25338
+ var import_yaml4 = __toESM(require_dist(), 1);
25013
25339
  import { createHash as createHash11 } from "node:crypto";
25014
- import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync3 } from "node:fs";
25015
- import { join as join9 } from "node:path";
25340
+ import { existsSync as existsSync9, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync3 } from "node:fs";
25341
+ import { join as join10 } from "node:path";
25016
25342
 
25017
25343
  // plugins/kxm/src/price-calc.ts
25018
25344
  var PRICES_SCHEMA = "kxm.prices.v1";
@@ -25076,7 +25402,7 @@ function hashPriceCatalog(catalog) {
25076
25402
  return createHash11("sha256").update(JSON.stringify(canonical), "utf8").digest("hex");
25077
25403
  }
25078
25404
  function parsePriceCatalog(text) {
25079
- const parsed = (0, import_yaml3.parse)(text);
25405
+ const parsed = (0, import_yaml4.parse)(text);
25080
25406
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
25081
25407
  throw new Error("price catalog must be an object");
25082
25408
  }
@@ -25164,11 +25490,11 @@ function parsePriceCatalog(text) {
25164
25490
  return catalog;
25165
25491
  }
25166
25492
  function loadPriceCatalog(rootOrPath) {
25167
- const candidatePath = existsSync8(join9(rootOrPath, ".kxm", "prices.yaml")) ? join9(rootOrPath, ".kxm", "prices.yaml") : existsSync8(join9(rootOrPath, "prices.yaml")) ? join9(rootOrPath, "prices.yaml") : existsSync8(rootOrPath) && statSync2(rootOrPath).isFile() ? rootOrPath : void 0;
25168
- if (!candidatePath || !existsSync8(candidatePath)) {
25493
+ const candidatePath = existsSync9(join10(rootOrPath, ".kxm", "prices.yaml")) ? join10(rootOrPath, ".kxm", "prices.yaml") : existsSync9(join10(rootOrPath, "prices.yaml")) ? join10(rootOrPath, "prices.yaml") : existsSync9(rootOrPath) && statSync2(rootOrPath).isFile() ? rootOrPath : void 0;
25494
+ if (!candidatePath || !existsSync9(candidatePath)) {
25169
25495
  return void 0;
25170
25496
  }
25171
- const content = readFileSync6(candidatePath, "utf8");
25497
+ const content = readFileSync7(candidatePath, "utf8");
25172
25498
  return parsePriceCatalog(content);
25173
25499
  }
25174
25500
  function loadPriceCatalogForEstimate(options) {
@@ -25185,40 +25511,40 @@ function loadPriceCatalogForEstimate(options) {
25185
25511
  }
25186
25512
 
25187
25513
  // plugins/kxm/src/engine.ts
25188
- var import_yaml9 = __toESM(require_dist(), 1);
25514
+ var import_yaml10 = __toESM(require_dist(), 1);
25189
25515
  import { createHash as createHash15, randomBytes as randomBytes2, timingSafeEqual } from "node:crypto";
25190
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
25191
- import { join as join15 } from "node:path";
25516
+ import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
25517
+ import { join as join16 } from "node:path";
25192
25518
 
25193
25519
  // plugins/kxm/src/routes.ts
25194
- var import_yaml6 = __toESM(require_dist(), 1);
25195
- import { existsSync as existsSync9, readFileSync as readFileSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync5 } from "node:fs";
25196
- import { join as join10 } from "node:path";
25520
+ var import_yaml7 = __toESM(require_dist(), 1);
25521
+ import { existsSync as existsSync10, readFileSync as readFileSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync6 } from "node:fs";
25522
+ import { join as join11 } from "node:path";
25197
25523
 
25198
25524
  // plugins/kxm/src/role.ts
25199
- var import_yaml5 = __toESM(require_dist(), 1);
25525
+ var import_yaml6 = __toESM(require_dist(), 1);
25200
25526
 
25201
25527
  // plugins/kxm/src/config.ts
25202
- var import_yaml4 = __toESM(require_dist(), 1);
25528
+ var import_yaml5 = __toESM(require_dist(), 1);
25203
25529
 
25204
25530
  // plugins/kxm/src/routes.ts
25205
25531
  var RETIRED_POLICY = ".kxm/producers.yaml";
25206
25532
  var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [] });
25207
25533
  function loadRoutePolicy(root) {
25208
- if (existsSync9(join10(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
25209
- const path = join10(root, ".kxm", "routes.yaml");
25210
- if (!existsSync9(path)) return empty();
25211
- const value = (0, import_yaml6.parse)(readFileSync7(path, "utf8"));
25534
+ if (existsSync10(join11(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
25535
+ const path = join11(root, ".kxm", "routes.yaml");
25536
+ if (!existsSync10(path)) return empty();
25537
+ const value = (0, import_yaml7.parse)(readFileSync8(path, "utf8"));
25212
25538
  if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
25213
25539
  return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), admitted: value.admitted.filter((x) => typeof x === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x) => typeof x === "string") : [] };
25214
25540
  }
25215
25541
  function listRoleBindings(root) {
25216
- const dir = join10(root, ".kxm", "roles");
25542
+ const dir = join11(root, ".kxm", "roles");
25217
25543
  const result = {};
25218
- if (!existsSync9(dir)) return result;
25219
- for (const file of readdirSync5(dir).filter((name) => name.endsWith(".yaml"))) {
25544
+ if (!existsSync10(dir)) return result;
25545
+ for (const file of readdirSync6(dir).filter((name) => name.endsWith(".yaml"))) {
25220
25546
  const role = file.slice(0, -5);
25221
- const value = (0, import_yaml6.parse)(readFileSync7(join10(dir, file), "utf8"));
25547
+ const value = (0, import_yaml7.parse)(readFileSync8(join11(dir, file), "utf8"));
25222
25548
  result[role] = (value.roster ?? []).map((entry) => entry.route).filter((route) => typeof route === "string");
25223
25549
  }
25224
25550
  return result;
@@ -25550,8 +25876,8 @@ function pruneContextPacket(packet, tokenBudget) {
25550
25876
 
25551
25877
  // plugins/kxm/src/dispatch-context.ts
25552
25878
  import { spawnSync as spawnSync5 } from "node:child_process";
25553
- import { readdirSync as readdirSync8 } from "node:fs";
25554
- import { extname as extname3, join as join13 } from "node:path";
25879
+ import { readdirSync as readdirSync9 } from "node:fs";
25880
+ import { extname as extname3, join as join14 } from "node:path";
25555
25881
 
25556
25882
  // plugins/kxm/src/protocol.ts
25557
25883
  var DEFAULT_MESSAGE_TTL_MS = 24 * 60 * 6e4;
@@ -26182,9 +26508,9 @@ function memoryRecordToContextItem(record2, project) {
26182
26508
  }
26183
26509
 
26184
26510
  // plugins/kxm/src/memory.ts
26185
- var import_yaml7 = __toESM(require_dist(), 1);
26186
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
26187
- import { extname as extname2, join as join11, resolve as resolve7 } from "node:path";
26511
+ var import_yaml8 = __toESM(require_dist(), 1);
26512
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, readdirSync as readdirSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "node:fs";
26513
+ import { extname as extname2, join as join12, resolve as resolve7 } from "node:path";
26188
26514
  var MEMORY_SCHEMA = "kxm.memory.v1";
26189
26515
  var VALID_SCOPES = /* @__PURE__ */ new Set(["agent", "project", "run", "operator"]);
26190
26516
  var VALID_AUTHORITIES = /* @__PURE__ */ new Set(["instruction", "evidence", "promoted"]);
@@ -26214,7 +26540,7 @@ function parseFrontmatter(content) {
26214
26540
  }
26215
26541
  function parseMemoryRecord(raw, filename = "memory.md") {
26216
26542
  const { frontmatter, body } = parseFrontmatter(raw);
26217
- const data = (0, import_yaml7.parse)(frontmatter);
26543
+ const data = (0, import_yaml8.parse)(frontmatter);
26218
26544
  if (!data || typeof data !== "object" || Array.isArray(data)) {
26219
26545
  throw new Error(`invalid YAML frontmatter in ${filename}`);
26220
26546
  }
@@ -26283,20 +26609,20 @@ function parseMemoryRecord(raw, filename = "memory.md") {
26283
26609
  }
26284
26610
  function memoryDirectories(repoRoot) {
26285
26611
  const root = resolve7(repoRoot);
26286
- const memoryDir = join11(root, ".kxm", "memory");
26287
- const candidatesDir = join11(memoryDir, "candidates");
26612
+ const memoryDir = join12(root, ".kxm", "memory");
26613
+ const candidatesDir = join12(memoryDir, "candidates");
26288
26614
  return { memoryDir, candidatesDir };
26289
26615
  }
26290
26616
  function loadAuthoredMemory(repoRoot) {
26291
26617
  const { memoryDir } = memoryDirectories(repoRoot);
26292
- if (!existsSync10(memoryDir)) return [];
26618
+ if (!existsSync11(memoryDir)) return [];
26293
26619
  const records = [];
26294
- const entries = readdirSync6(memoryDir, { withFileTypes: true });
26620
+ const entries = readdirSync7(memoryDir, { withFileTypes: true });
26295
26621
  for (const entry of entries) {
26296
26622
  if (entry.isFile() && extname2(entry.name) === ".md") {
26297
- const fullPath = join11(memoryDir, entry.name);
26623
+ const fullPath = join12(memoryDir, entry.name);
26298
26624
  try {
26299
- const text = readFileSync8(fullPath, "utf8");
26625
+ const text = readFileSync9(fullPath, "utf8");
26300
26626
  const record2 = parseMemoryRecord(text, entry.name);
26301
26627
  if (record2.lifecycle === "active") {
26302
26628
  records.push(record2);
@@ -26310,10 +26636,10 @@ function loadAuthoredMemory(repoRoot) {
26310
26636
  }
26311
26637
 
26312
26638
  // plugins/kxm/src/skills.ts
26313
- var import_yaml8 = __toESM(require_dist(), 1);
26639
+ var import_yaml9 = __toESM(require_dist(), 1);
26314
26640
  import { createHash as createHash12 } from "node:crypto";
26315
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as readdirSync7, readFileSync as readFileSync9, renameSync, rmSync, statSync as statSync3, writeFileSync as writeFileSync6 } from "node:fs";
26316
- import { dirname as dirname7, join as join12 } from "node:path";
26641
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, readdirSync as readdirSync8, readFileSync as readFileSync10, renameSync, rmSync, statSync as statSync3, writeFileSync as writeFileSync6 } from "node:fs";
26642
+ import { dirname as dirname7, join as join13 } from "node:path";
26317
26643
  var SKILL_CANDIDATE_SCHEMA = "kxm.skill-candidate.v1";
26318
26644
  var SKILL_EVALUATION_SCHEMA = "kxm.skill-evaluation.v1";
26319
26645
  var SKILL_DECISION_SCHEMA = "kxm.skill-decision.v1";
@@ -26354,7 +26680,7 @@ function parseSkillFrontmatter(content) {
26354
26680
  return { frontmatter: null, body: content };
26355
26681
  }
26356
26682
  try {
26357
- const parsed = (0, import_yaml8.parse)(rawFm);
26683
+ const parsed = (0, import_yaml9.parse)(rawFm);
26358
26684
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
26359
26685
  return { frontmatter: parsed, body: rawBody };
26360
26686
  }
@@ -26419,20 +26745,20 @@ var SkillLifecycle = class {
26419
26745
  writeFileSync6(file, content);
26420
26746
  }
26421
26747
  dir(state) {
26422
- return join12(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
26748
+ return join13(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
26423
26749
  }
26424
26750
  historyFile(id) {
26425
- return join12(this.root, "history", `${id}.jsonl`);
26751
+ return join13(this.root, "history", `${id}.jsonl`);
26426
26752
  }
26427
26753
  paths(state, id) {
26428
- const dir = join12(this.dir(state), id);
26429
- return { dir, metadata: join12(dir, "metadata.json"), skill: join12(dir, "SKILL.md") };
26754
+ const dir = join13(this.dir(state), id);
26755
+ return { dir, metadata: join13(dir, "metadata.json"), skill: join13(dir, "SKILL.md") };
26430
26756
  }
26431
26757
  appendHistory(id, record2) {
26432
26758
  const line = `${JSON.stringify(record2)}
26433
26759
  `;
26434
- if (existsSync11(this.historyFile(id))) {
26435
- const existing = readFileSync9(this.historyFile(id), "utf8");
26760
+ if (existsSync12(this.historyFile(id))) {
26761
+ const existing = readFileSync10(this.historyFile(id), "utf8");
26436
26762
  const lines = existing.split("\n").filter((entry) => entry.trim());
26437
26763
  this.write(this.historyFile(id), [...lines.slice(-499), line.trim()].join("\n") + "\n");
26438
26764
  } else {
@@ -26441,20 +26767,20 @@ var SkillLifecycle = class {
26441
26767
  }
26442
26768
  history(id) {
26443
26769
  const file = this.historyFile(id);
26444
- if (!existsSync11(file)) return [];
26445
- return readFileSync9(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
26770
+ if (!existsSync12(file)) return [];
26771
+ return readFileSync10(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
26446
26772
  }
26447
26773
  readMetadata(state, id) {
26448
26774
  const { metadata } = this.paths(state, id);
26449
- if (!existsSync11(metadata)) {
26775
+ if (!existsSync12(metadata)) {
26450
26776
  throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${state}`);
26451
26777
  }
26452
- return JSON.parse(readFileSync9(metadata, "utf8"));
26778
+ return JSON.parse(readFileSync10(metadata, "utf8"));
26453
26779
  }
26454
26780
  move(from, to, id) {
26455
- const fromDir = join12(this.dir(from), id);
26456
- const toDir = join12(this.dir(to), id);
26457
- if (!existsSync11(fromDir)) {
26781
+ const fromDir = join13(this.dir(from), id);
26782
+ const toDir = join13(this.dir(to), id);
26783
+ if (!existsSync12(fromDir)) {
26458
26784
  throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${from}`);
26459
26785
  }
26460
26786
  if (this.dryRun) {
@@ -26462,7 +26788,7 @@ var SkillLifecycle = class {
26462
26788
  return;
26463
26789
  }
26464
26790
  mkdirSync5(this.dir(to), { recursive: true });
26465
- if (existsSync11(toDir)) rmSync(toDir, { recursive: true, force: true });
26791
+ if (existsSync12(toDir)) rmSync(toDir, { recursive: true, force: true });
26466
26792
  renameSync(fromDir, toDir);
26467
26793
  }
26468
26794
  /** Submit a new skill candidate. Content is redacted of secret material at
@@ -26505,7 +26831,7 @@ var SkillLifecycle = class {
26505
26831
  const contentSha256 = skillContentSha256(content);
26506
26832
  const id = skillIdFor(name, contentSha256);
26507
26833
  const { metadata, skill } = this.paths("candidate", id);
26508
- if (existsSync11(metadata)) {
26834
+ if (existsSync12(metadata)) {
26509
26835
  throw new SkillLifecycleError(
26510
26836
  "skill_candidate_exists",
26511
26837
  `identical candidate ${id} already exists; changed behavior requires changed content`
@@ -26614,11 +26940,11 @@ var SkillLifecycle = class {
26614
26940
  };
26615
26941
  const candidatePaths = this.paths("candidate", candidateId);
26616
26942
  const promotedPaths = this.paths("promoted", candidateId);
26617
- const skillContent = readFileSync9(candidatePaths.skill, "utf8");
26618
- const metadataContent = readFileSync9(candidatePaths.metadata, "utf8");
26943
+ const skillContent = readFileSync10(candidatePaths.skill, "utf8");
26944
+ const metadataContent = readFileSync10(candidatePaths.metadata, "utf8");
26619
26945
  this.write(promotedPaths.skill, skillContent);
26620
26946
  this.write(promotedPaths.metadata, metadataContent);
26621
- const patchPath = join12(this.root, "patches", `${candidateId}.patch`);
26947
+ const patchPath = join13(this.root, "patches", `${candidateId}.patch`);
26622
26948
  const relSkillPath = `.kxm/skills/promoted/${candidateId}/SKILL.md`;
26623
26949
  const relMetaPath = `.kxm/skills/promoted/${candidateId}/metadata.json`;
26624
26950
  const patch = `${createUnifiedPatch(relSkillPath, skillContent)}${createUnifiedPatch(relMetaPath, metadataContent)}`;
@@ -26646,7 +26972,7 @@ var SkillLifecycle = class {
26646
26972
  verify(state, id) {
26647
26973
  const metadata = this.readMetadata(state, id);
26648
26974
  const { skill } = this.paths(state, id);
26649
- const content = readFileSync9(skill, "utf8");
26975
+ const content = readFileSync10(skill, "utf8");
26650
26976
  if (skillContentSha256(content) !== metadata.contentSha256) {
26651
26977
  throw new SkillLifecycleError(
26652
26978
  "skill_integrity_violation",
@@ -26664,7 +26990,7 @@ var SkillLifecycle = class {
26664
26990
  }
26665
26991
  list(state) {
26666
26992
  const dir = this.dir(state);
26667
- if (!existsSync11(dir)) return [];
26993
+ if (!existsSync12(dir)) return [];
26668
26994
  const ids = readdirSorted(dir);
26669
26995
  return ids.map((id) => {
26670
26996
  try {
@@ -26677,7 +27003,7 @@ var SkillLifecycle = class {
26677
27003
  read(state, id) {
26678
27004
  const metadata = this.readMetadata(state, id);
26679
27005
  const { skill } = this.paths(state, id);
26680
- return { metadata, content: readFileSync9(skill, "utf8") };
27006
+ return { metadata, content: readFileSync10(skill, "utf8") };
26681
27007
  }
26682
27008
  };
26683
27009
  function boundedList(value, field) {
@@ -26692,7 +27018,7 @@ function boundedList(value, field) {
26692
27018
  return [...new Set(refs)];
26693
27019
  }
26694
27020
  function readdirSorted(dir) {
26695
- return readdirSync7(dir).filter((entry) => statSync3(join12(dir, entry)).isDirectory()).sort();
27021
+ return readdirSync8(dir).filter((entry) => statSync3(join13(dir, entry)).isDirectory()).sort();
26696
27022
  }
26697
27023
 
26698
27024
  // plugins/kxm/src/dispatch-context.ts
@@ -26733,18 +27059,18 @@ function contextRoleForAgent(agentId) {
26733
27059
  return agentId;
26734
27060
  }
26735
27061
  function dispatchContextPresent(projectRoot) {
26736
- return hasTopLevelMarkdown(join13(projectRoot, ".kxm", "memory")) || hasAnyEntry(join13(projectRoot, ".kxm", "skills", "promoted"));
27062
+ return hasTopLevelMarkdown(join14(projectRoot, ".kxm", "memory")) || hasAnyEntry(join14(projectRoot, ".kxm", "skills", "promoted"));
26737
27063
  }
26738
27064
  function hasTopLevelMarkdown(dir) {
26739
27065
  try {
26740
- return readdirSync8(dir, { withFileTypes: true }).some((entry) => entry.isFile() && extname3(entry.name) === ".md");
27066
+ return readdirSync9(dir, { withFileTypes: true }).some((entry) => entry.isFile() && extname3(entry.name) === ".md");
26741
27067
  } catch {
26742
27068
  return false;
26743
27069
  }
26744
27070
  }
26745
27071
  function hasAnyEntry(dir) {
26746
27072
  try {
26747
- return readdirSync8(dir).length > 0;
27073
+ return readdirSync9(dir).length > 0;
26748
27074
  } catch {
26749
27075
  return false;
26750
27076
  }
@@ -26809,7 +27135,7 @@ function loadDispatchContextSources(input) {
26809
27135
  }
26810
27136
  const promoted = [];
26811
27137
  try {
26812
- const lifecycle = new SkillLifecycle(join13(projectRoot, ".kxm", "skills"));
27138
+ const lifecycle = new SkillLifecycle(join14(projectRoot, ".kxm", "skills"));
26813
27139
  for (const metadata of lifecycle.list("promoted")) {
26814
27140
  try {
26815
27141
  promoted.push(lifecycle.verify("promoted", metadata.id));
@@ -26892,7 +27218,7 @@ function assembleDispatchContext(sources, input) {
26892
27218
  }
26893
27219
 
26894
27220
  // plugins/kxm/src/engine-artifacts.ts
26895
- import { join as join14 } from "node:path";
27221
+ import { join as join15 } from "node:path";
26896
27222
 
26897
27223
  // plugins/kxm/src/artifacts-exist.ts
26898
27224
  import { lstatSync as lstatSync5, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
@@ -26939,14 +27265,14 @@ function verifyArtifactExists(rootInput, pathInput) {
26939
27265
  // plugins/kxm/src/engine-artifacts.ts
26940
27266
  var kxmArtifactsGateSeams = {};
26941
27267
  function evaluateArtifactsGate(context, definition) {
26942
- const root = join14(context.projectRoot, ".kxm", "assets");
27268
+ const root = join15(context.projectRoot, ".kxm", "assets");
26943
27269
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
26944
27270
  const startTime = process.hrtime.bigint();
26945
27271
  let checkedCount = 0;
26946
27272
  let failedCount = 0;
26947
27273
  for (const [index, path] of definition.paths.entries()) {
26948
27274
  checkedCount += 1;
26949
- const result = verifyArtifactExists(root, join14(root, path));
27275
+ const result = verifyArtifactExists(root, join15(root, path));
26950
27276
  if (!result.ok) failedCount += 1;
26951
27277
  kxmArtifactsGateSeams.afterPathChecked?.({ path, index, checkedCount, failedCount });
26952
27278
  }
@@ -28091,7 +28417,7 @@ function pinKxmCompiledPlan(context, bundle, runId, options) {
28091
28417
  if (String(bundle.project.value.id) !== run.projectId) {
28092
28418
  throw runtimeError("run_owner_mismatch", runId, "bundle project does not match the run");
28093
28419
  }
28094
- const workflow = bundle.workflows.get(run.workflowId);
28420
+ const workflow = lookupKxmResource(bundle.workflows.values(), run.workflowId, "workflow");
28095
28421
  if (!workflow) throw runtimeError("run_workflow_unknown", run.workflowId, `workflow ${run.workflowId} does not exist in this project`);
28096
28422
  const revisions = kxmPolicyRevisions(bundle, options);
28097
28423
  if (revisions.configRevision !== run.configRevision || revisions.executorPolicyRevision !== run.executorPolicyRevision || revisions.toolPolicyRevision !== run.toolPolicyRevision || revisions.memoryRevision !== run.memoryRevision) {
@@ -28824,9 +29150,9 @@ function readYamlFile(file) {
28824
29150
  return readModelDocument(file);
28825
29151
  }
28826
29152
  function readModelDocument(file) {
28827
- if (!existsSync12(file)) return void 0;
29153
+ if (!existsSync13(file)) return void 0;
28828
29154
  try {
28829
- const parsed = (0, import_yaml9.parse)(readFileSync10(file, "utf8"));
29155
+ const parsed = (0, import_yaml10.parse)(readFileSync11(file, "utf8"));
28830
29156
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
28831
29157
  return parsed;
28832
29158
  } catch {
@@ -28857,7 +29183,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28857
29183
  }
28858
29184
  };
28859
29185
  }
28860
- const agent = readYamlFile(join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`));
29186
+ const agentFile = findYamlBasename(join16(projectRoot, ".kxm", "agents"), agentId, "agent") ?? agentId;
29187
+ const agent = readYamlFile(join16(projectRoot, ".kxm", "agents", `${agentFile}.yaml`));
28861
29188
  const role = typeof agent?.role === "string" ? agent.role : "";
28862
29189
  if (!role) {
28863
29190
  return {
@@ -28868,7 +29195,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28868
29195
  }
28869
29196
  };
28870
29197
  }
28871
- const roleDoc = readYamlFile(join15(projectRoot, ".kxm", "roles", `${role}.yaml`));
29198
+ const roleDoc = readYamlFile(join16(projectRoot, ".kxm", "roles", `${role}.yaml`));
28872
29199
  const roster = Array.isArray(roleDoc?.roster) ? roleDoc.roster : void 0;
28873
29200
  if (!roster) {
28874
29201
  return {
@@ -28884,7 +29211,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28884
29211
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
28885
29212
  const record2 = entry;
28886
29213
  if (typeof record2.route !== "string" || record2.route.length === 0) continue;
28887
- const modelPath = join15(projectRoot, ".kxm", "models", `${record2.route}.yaml`);
29214
+ const routeFile = findYamlBasename(join16(projectRoot, ".kxm", "models"), record2.route, "route") ?? record2.route;
29215
+ const modelPath = join16(projectRoot, ".kxm", "models", `${routeFile}.yaml`);
28888
29216
  const doc = readModelDocument(modelPath);
28889
29217
  if (!doc) {
28890
29218
  return {
@@ -28947,7 +29275,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28947
29275
  model: selector.slice(slash + 1),
28948
29276
  selector,
28949
29277
  harness,
28950
- routeId: record2.route,
29278
+ routeId: routeFile,
28951
29279
  role,
28952
29280
  permissions,
28953
29281
  ...typeof record2.effort === "string" ? { effort: record2.effort } : {}
@@ -28989,7 +29317,7 @@ function settleExitedExecutingAttempt(context, run, executing) {
28989
29317
  let sequence = context.eventStore.nextSequence(run.runId);
28990
29318
  let mono = kxmMonotonicNs();
28991
29319
  const events = [];
28992
- const push = (eventType, payload) => {
29320
+ const push2 = (eventType, payload) => {
28993
29321
  events.push({
28994
29322
  ...kxmEventBase(context, run, now, mono),
28995
29323
  eventId: newKxmEventId(),
@@ -28999,18 +29327,18 @@ function settleExitedExecutingAttempt(context, run, executing) {
28999
29327
  });
29000
29328
  mono = kxmIncrementMonotonicNs(mono);
29001
29329
  };
29002
- push("attempt.status_changed", { attemptId: executing.attemptId, status: "settling" });
29003
- push("assignment.result_recorded", {
29330
+ push2("attempt.status_changed", { attemptId: executing.attemptId, status: "settling" });
29331
+ push2("assignment.result_recorded", {
29004
29332
  assignmentId: executing.assignmentId,
29005
29333
  resultClass: "producer_rejected",
29006
29334
  status: "result_recorded",
29007
29335
  producerError: "executing_unrecorded",
29008
29336
  reason: "executing_unrecorded"
29009
29337
  });
29010
- push("attempt.status_changed", { attemptId: executing.attemptId, status: "terminal" });
29011
- push("assignment.terminal", { assignmentId: executing.assignmentId, outcome: "failed", status: "terminal" });
29012
- push("step.status_changed", { stepId: executing.stepId, status: "cancelled", previousStatus: "running" });
29013
- push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
29338
+ push2("attempt.status_changed", { attemptId: executing.attemptId, status: "terminal" });
29339
+ push2("assignment.terminal", { assignmentId: executing.assignmentId, outcome: "failed", status: "terminal" });
29340
+ push2("step.status_changed", { stepId: executing.stepId, status: "cancelled", previousStatus: "running" });
29341
+ push2("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
29014
29342
  for (const event of events) context.eventStore.appendEvent(event);
29015
29343
  context.eventStore.settleCapability(executing.attemptId, "settled");
29016
29344
  const next = foldStoredKxmRun(context, run);
@@ -29191,7 +29519,7 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
29191
29519
  let sequence = context.eventStore.nextSequence(runId);
29192
29520
  let mono = kxmMonotonicNs();
29193
29521
  const events = [];
29194
- const push = (eventType, payload) => {
29522
+ const push2 = (eventType, payload) => {
29195
29523
  events.push({
29196
29524
  ...kxmEventBase(context, run, now, mono),
29197
29525
  eventId: newKxmEventId(),
@@ -29201,8 +29529,8 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
29201
29529
  });
29202
29530
  mono = kxmIncrementMonotonicNs(mono);
29203
29531
  };
29204
- push("step.entered", { stepId, stepAttempt, status: "pending" });
29205
- push("step.status_changed", { stepId, status: "preparing", previousStatus: "pending" });
29532
+ push2("step.entered", { stepId, stepAttempt, status: "pending" });
29533
+ push2("step.status_changed", { stepId, status: "preparing", previousStatus: "pending" });
29206
29534
  for (const event of events) context.eventStore.appendEvent(event);
29207
29535
  const entered = foldStoredKxmRun(context, run);
29208
29536
  persistKxmRunState(context, runId, entered, events[events.length - 1].sequence);
@@ -29303,7 +29631,7 @@ function birthMember(context, input) {
29303
29631
  let sequence = context.eventStore.nextSequence(run.runId);
29304
29632
  let mono = kxmMonotonicNs();
29305
29633
  const events = [];
29306
- const push = (eventType, payload) => {
29634
+ const push2 = (eventType, payload) => {
29307
29635
  events.push({
29308
29636
  ...kxmEventBase(context, run, now, mono),
29309
29637
  eventId: newKxmEventId(),
@@ -29313,18 +29641,18 @@ function birthMember(context, input) {
29313
29641
  });
29314
29642
  mono = kxmIncrementMonotonicNs(mono);
29315
29643
  };
29316
- push("assignment.created", { assignmentId, stepId: input.stepId, stepAttempt: input.stepAttempt, agentId, status: "created" });
29317
- push("assignment.accepted", { assignmentId, status: "accepted" });
29318
- push("attempt.created", { attemptId, assignmentId, status: "created" });
29319
- push("assignment.dispatched", {
29644
+ push2("assignment.created", { assignmentId, stepId: input.stepId, stepAttempt: input.stepAttempt, agentId, status: "created" });
29645
+ push2("assignment.accepted", { assignmentId, status: "accepted" });
29646
+ push2("attempt.created", { attemptId, assignmentId, status: "created" });
29647
+ push2("assignment.dispatched", {
29320
29648
  assignmentId,
29321
29649
  capabilityHash: minted.hash,
29322
29650
  status: "dispatched",
29323
29651
  ...resolvedRoute ? { model: { provider: resolvedRoute.provider, model: resolvedRoute.model } } : {}
29324
29652
  });
29325
- push("attempt.status_changed", { attemptId, status: "starting" });
29653
+ push2("attempt.status_changed", { attemptId, status: "starting" });
29326
29654
  if (input.enterRunning) {
29327
- push("step.status_changed", { stepId: input.stepId, status: "running", previousStatus: "preparing" });
29655
+ push2("step.status_changed", { stepId: input.stepId, status: "running", previousStatus: "preparing" });
29328
29656
  }
29329
29657
  for (const event of events) context.eventStore.appendEvent(event);
29330
29658
  context.eventStore.insertCapability({
@@ -29780,7 +30108,7 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29780
30108
  let sequence = context.eventStore.nextSequence(run.runId);
29781
30109
  let mono = kxmMonotonicNs();
29782
30110
  const events = [];
29783
- const push = (eventType, payload) => {
30111
+ const push2 = (eventType, payload) => {
29784
30112
  events.push({
29785
30113
  ...kxmEventBase(context, run, now, mono),
29786
30114
  eventId: newKxmEventId(),
@@ -29790,17 +30118,17 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29790
30118
  });
29791
30119
  mono = kxmIncrementMonotonicNs(mono);
29792
30120
  };
29793
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "settling" });
30121
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "settling" });
29794
30122
  if (cancelling) {
29795
- push("routing.attempt.recorded", { routing: producerRoutingRecord(
30123
+ push2("routing.attempt.recorded", { routing: producerRoutingRecord(
29796
30124
  context,
29797
30125
  dispatch,
29798
30126
  result ?? { outcome: "cancelled", costBasis: "unknown", costUsd: null },
29799
30127
  now
29800
30128
  ) });
29801
- push("assignment.result_recorded", { assignmentId: dispatch.assignmentId, resultClass: "cancelled", status: "result_recorded" });
29802
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29803
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "cancelled", status: "terminal" });
30129
+ push2("assignment.result_recorded", { assignmentId: dispatch.assignmentId, resultClass: "cancelled", status: "result_recorded" });
30130
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
30131
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "cancelled", status: "terminal" });
29804
30132
  } else if (produceError) {
29805
30133
  const envelope2 = loadKxmRunPlanEnvelope(context.eventStore, run);
29806
30134
  const rawHash = result?.behavioralSha256 ?? behavioralConfigHash({
@@ -29834,22 +30162,22 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29834
30162
  finalOutcome: "failed",
29835
30163
  providerMetadata: engineRoutingMetadata(dispatch)
29836
30164
  };
29837
- push("routing.attempt.recorded", { routing: parseRoutingRecordV2(routingRecord) });
29838
- push("assignment.result_recorded", {
30165
+ push2("routing.attempt.recorded", { routing: parseRoutingRecordV2(routingRecord) });
30166
+ push2("assignment.result_recorded", {
29839
30167
  assignmentId: dispatch.assignmentId,
29840
30168
  resultClass: "producer_rejected",
29841
30169
  status: "result_recorded",
29842
30170
  ...produceErrorCode !== void 0 ? { producerError: produceErrorCode } : {}
29843
30171
  });
29844
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29845
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
30172
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
30173
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
29846
30174
  } else {
29847
30175
  if (!result) {
29848
30176
  throw runtimeError("settle_missing_cost_basis", run.runId, `attempt settlement rejected: missing required costBasis for attempt ${dispatch.attemptId}`);
29849
30177
  }
29850
30178
  const outcome = typeof result.outcome === "string" ? result.outcome : void 0;
29851
30179
  const known = outcome !== void 0 && dispatch.step.outcomes.includes(outcome);
29852
- push("routing.attempt.recorded", {
30180
+ push2("routing.attempt.recorded", {
29853
30181
  routing: producerRoutingRecord(
29854
30182
  context,
29855
30183
  dispatch,
@@ -29859,22 +30187,22 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29859
30187
  )
29860
30188
  });
29861
30189
  if (!known) {
29862
- push("assignment.result_recorded", {
30190
+ push2("assignment.result_recorded", {
29863
30191
  assignmentId: dispatch.assignmentId,
29864
30192
  resultClass: "outcome_unknown",
29865
30193
  status: "result_recorded"
29866
30194
  });
29867
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29868
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
30195
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
30196
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
29869
30197
  } else {
29870
- push("assignment.result_recorded", {
30198
+ push2("assignment.result_recorded", {
29871
30199
  assignmentId: dispatch.assignmentId,
29872
30200
  outcome,
29873
30201
  resultClass: "outcome",
29874
30202
  status: "result_recorded"
29875
30203
  });
29876
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29877
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome, status: "terminal" });
30204
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
30205
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome, status: "terminal" });
29878
30206
  }
29879
30207
  }
29880
30208
  context.eventStore.settleCapability(dispatch.attemptId, "settled");
@@ -29894,7 +30222,7 @@ function joinPanel(context, panel) {
29894
30222
  let sequence = context.eventStore.nextSequence(run.runId);
29895
30223
  let mono = kxmMonotonicNs();
29896
30224
  const events = [];
29897
- const push = (eventType, payload) => {
30225
+ const push2 = (eventType, payload) => {
29898
30226
  events.push({
29899
30227
  ...kxmEventBase(context, run, now, mono),
29900
30228
  eventId: newKxmEventId(),
@@ -29905,8 +30233,8 @@ function joinPanel(context, panel) {
29905
30233
  mono = kxmIncrementMonotonicNs(mono);
29906
30234
  };
29907
30235
  const failRun = (reason) => {
29908
- push("step.status_changed", { stepId: panel.stepId, status: "failed", previousStatus: "running" });
29909
- push("run.status_changed", { status: "failed", reason, stepId: panel.stepId });
30236
+ push2("step.status_changed", { stepId: panel.stepId, status: "failed", previousStatus: "running" });
30237
+ push2("run.status_changed", { status: "failed", reason, stepId: panel.stepId });
29910
30238
  for (const event of events) context.eventStore.appendEvent(event);
29911
30239
  const next2 = foldStoredKxmRun(context, run);
29912
30240
  persistKxmRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -29914,8 +30242,8 @@ function joinPanel(context, panel) {
29914
30242
  return { state: next2 };
29915
30243
  };
29916
30244
  const cancelRun = () => {
29917
- push("step.status_changed", { stepId: panel.stepId, status: "cancelled", previousStatus: "running" });
29918
- push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
30245
+ push2("step.status_changed", { stepId: panel.stepId, status: "cancelled", previousStatus: "running" });
30246
+ push2("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
29919
30247
  for (const event of events) context.eventStore.appendEvent(event);
29920
30248
  const next2 = foldStoredKxmRun(context, run);
29921
30249
  persistKxmRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -29947,12 +30275,12 @@ function joinPanel(context, panel) {
29947
30275
  const outcome = joined.outcome;
29948
30276
  const selected = panel.step.transitions[outcome];
29949
30277
  if (!selected) return failRun("outcome_unknown");
29950
- push("step.outcome_recorded", { stepId: panel.stepId, stepAttempt: panel.stepAttempt, outcome });
30278
+ push2("step.outcome_recorded", { stepId: panel.stepId, stepAttempt: panel.stepAttempt, outcome });
29951
30279
  const stepStatus = outcome === "passed" ? "passed" : outcome === "cancelled" ? "cancelled" : "failed";
29952
- push("step.status_changed", { stepId: panel.stepId, status: stepStatus, previousStatus: "running" });
30280
+ push2("step.status_changed", { stepId: panel.stepId, status: stepStatus, previousStatus: "running" });
29953
30281
  const budget = transitionBudgetFailure(panel.plan, state, panel.stepId, outcome);
29954
30282
  if (budget) {
29955
- push("run.status_changed", { status: "failed", reason: budget, stepId: panel.stepId, outcome });
30283
+ push2("run.status_changed", { status: "failed", reason: budget, stepId: panel.stepId, outcome });
29956
30284
  for (const event of events) context.eventStore.appendEvent(event);
29957
30285
  const next2 = foldStoredKxmRun(context, run);
29958
30286
  persistKxmRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -29960,10 +30288,10 @@ function joinPanel(context, panel) {
29960
30288
  return { state: next2 };
29961
30289
  }
29962
30290
  if (selected.to === "step") {
29963
- push("step.transitioned", { fromStepId: panel.stepId, toStepId: selected.target, outcome });
30291
+ push2("step.transitioned", { fromStepId: panel.stepId, toStepId: selected.target, outcome });
29964
30292
  } else {
29965
- push("step.transitioned", { fromStepId: panel.stepId, status: selected.terminalStatus, outcome });
29966
- push("run.status_changed", { status: selected.terminalStatus });
30293
+ push2("step.transitioned", { fromStepId: panel.stepId, status: selected.terminalStatus, outcome });
30294
+ push2("run.status_changed", { status: selected.terminalStatus });
29967
30295
  }
29968
30296
  for (const event of events) context.eventStore.appendEvent(event);
29969
30297
  const next = foldStoredKxmRun(context, run);
@@ -30567,7 +30895,7 @@ function recoverKxmRun(context, runId, request) {
30567
30895
  let sequence = context.eventStore.nextSequence(runId);
30568
30896
  let mono = kxmMonotonicNs();
30569
30897
  const events = [];
30570
- const push = (eventType, payload) => {
30898
+ const push2 = (eventType, payload) => {
30571
30899
  events.push({
30572
30900
  ...kxmEventBase(context, run, now, mono, request.commandId),
30573
30901
  eventId: newKxmEventId(),
@@ -30578,7 +30906,7 @@ function recoverKxmRun(context, runId, request) {
30578
30906
  mono = kxmIncrementMonotonicNs(mono);
30579
30907
  };
30580
30908
  if (state.status === "running" && state.currentStep?.effectState === "blocked_uncertain") {
30581
- push("run.status_changed", {
30909
+ push2("run.status_changed", {
30582
30910
  status: "blocked_uncertain",
30583
30911
  previousStatus: "running",
30584
30912
  reason: request.reason ?? "uncertain gate effect"
@@ -30598,7 +30926,7 @@ function recoverKxmRun(context, runId, request) {
30598
30926
  }
30599
30927
  }
30600
30928
  if (request.action === "retry" || request.action === "unblock") {
30601
- push("run.status_changed", {
30929
+ push2("run.status_changed", {
30602
30930
  status: "running",
30603
30931
  previousStatus: "blocked_uncertain",
30604
30932
  reason: request.reason ?? "operator_retry"
@@ -30610,7 +30938,7 @@ function recoverKxmRun(context, runId, request) {
30610
30938
  return { state: nextState, unblocked: true };
30611
30939
  }
30612
30940
  if (request.action === "fail") {
30613
- push("run.status_changed", {
30941
+ push2("run.status_changed", {
30614
30942
  status: "failed",
30615
30943
  previousStatus: "blocked_uncertain",
30616
30944
  reason: request.reason ?? "operator_fail"
@@ -30622,16 +30950,16 @@ function recoverKxmRun(context, runId, request) {
30622
30950
  return { state: nextState, unblocked: true };
30623
30951
  }
30624
30952
  if (request.action === "cancel") {
30625
- push("run.cancel_requested", {
30953
+ push2("run.cancel_requested", {
30626
30954
  actor: { kind: "runtime", id: context.homeRuntimeId },
30627
30955
  reason: request.reason ?? "operator_cancel"
30628
30956
  });
30629
- push("run.status_changed", {
30957
+ push2("run.status_changed", {
30630
30958
  status: "cancelling",
30631
30959
  previousStatus: "blocked_uncertain",
30632
30960
  reason: request.reason ?? "operator_cancel"
30633
30961
  });
30634
- push("run.status_changed", {
30962
+ push2("run.status_changed", {
30635
30963
  status: "cancelled",
30636
30964
  previousStatus: "cancelling",
30637
30965
  reason: request.reason ?? "operator_cancel"
@@ -31138,9 +31466,9 @@ var RuntimeHubClient = class {
31138
31466
  };
31139
31467
 
31140
31468
  // plugins/kxm/src/hub-binding.ts
31141
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
31469
+ import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync12, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
31142
31470
  import { homedir as homedir2 } from "node:os";
31143
- import { dirname as dirname8, isAbsolute as isAbsolute6, join as join16, resolve as resolve9 } from "node:path";
31471
+ import { dirname as dirname8, isAbsolute as isAbsolute6, join as join17, resolve as resolve9 } from "node:path";
31144
31472
  var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
31145
31473
  var HubBindingError = class extends Error {
31146
31474
  constructor(message) {
@@ -31156,16 +31484,16 @@ function resolveUserStateRoot(env) {
31156
31484
  }
31157
31485
  if (process.platform === "win32") {
31158
31486
  const localAppData = env.LOCALAPPDATA?.trim();
31159
- const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join16(homedir2(), "AppData", "Local");
31487
+ const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join17(homedir2(), "AppData", "Local");
31160
31488
  return resolve9(base2, "KXM");
31161
31489
  }
31162
31490
  if (process.platform === "darwin") return resolve9(homedir2(), "Library", "Application Support", "KXM");
31163
31491
  const xdgState = env.XDG_STATE_HOME?.trim();
31164
- const base = xdgState && isAbsolute6(xdgState) ? xdgState : join16(homedir2(), ".local", "state");
31492
+ const base = xdgState && isAbsolute6(xdgState) ? xdgState : join17(homedir2(), ".local", "state");
31165
31493
  return resolve9(base, "kxm");
31166
31494
  }
31167
31495
  function hubBindingFile(env = process.env) {
31168
- return join16(resolveUserStateRoot(env), "hub-binding.json");
31496
+ return join17(resolveUserStateRoot(env), "hub-binding.json");
31169
31497
  }
31170
31498
  function validateHubUrl(raw) {
31171
31499
  let parsed;
@@ -31185,10 +31513,10 @@ function isIsoTimestamp(value) {
31185
31513
  }
31186
31514
  function readHubBinding(env = process.env) {
31187
31515
  const file = hubBindingFile(env);
31188
- if (!existsSync13(file)) return void 0;
31516
+ if (!existsSync14(file)) return void 0;
31189
31517
  let parsed;
31190
31518
  try {
31191
- parsed = JSON.parse(readFileSync11(file, "utf8"));
31519
+ parsed = JSON.parse(readFileSync12(file, "utf8"));
31192
31520
  } catch {
31193
31521
  throw new HubBindingError(`malformed hub binding at ${file}`);
31194
31522
  }
@@ -31210,9 +31538,9 @@ function readHubBinding(env = process.env) {
31210
31538
  }
31211
31539
 
31212
31540
  // plugins/kxm/src/hub-env.ts
31213
- import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync12, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
31541
+ import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync13, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
31214
31542
  import { homedir as homedir3 } from "node:os";
31215
- import { dirname as dirname9, isAbsolute as isAbsolute7, join as join17, resolve as resolve10 } from "node:path";
31543
+ import { dirname as dirname9, isAbsolute as isAbsolute7, join as join18, resolve as resolve10 } from "node:path";
31216
31544
  var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
31217
31545
  var HubEnvError = class extends Error {
31218
31546
  constructor(message) {
@@ -31228,23 +31556,23 @@ function resolveUserStateRoot2(env) {
31228
31556
  }
31229
31557
  if (process.platform === "win32") {
31230
31558
  const localAppData = env.LOCALAPPDATA?.trim();
31231
- const base2 = localAppData && isAbsolute7(localAppData) ? localAppData : join17(homedir3(), "AppData", "Local");
31559
+ const base2 = localAppData && isAbsolute7(localAppData) ? localAppData : join18(homedir3(), "AppData", "Local");
31232
31560
  return resolve10(base2, "KXM");
31233
31561
  }
31234
31562
  if (process.platform === "darwin") return resolve10(homedir3(), "Library", "Application Support", "KXM");
31235
31563
  const xdgState = env.XDG_STATE_HOME?.trim();
31236
- const base = xdgState && isAbsolute7(xdgState) ? xdgState : join17(homedir3(), ".local", "state");
31564
+ const base = xdgState && isAbsolute7(xdgState) ? xdgState : join18(homedir3(), ".local", "state");
31237
31565
  return resolve10(base, "kxm");
31238
31566
  }
31239
31567
  function hubEnvFile(env = process.env) {
31240
- return join17(resolveUserStateRoot2(env), "hub-env.json");
31568
+ return join18(resolveUserStateRoot2(env), "hub-env.json");
31241
31569
  }
31242
31570
  function readHubEnvRecord(env = process.env) {
31243
31571
  const file = hubEnvFile(env);
31244
- if (!existsSync14(file)) return void 0;
31572
+ if (!existsSync15(file)) return void 0;
31245
31573
  let parsed;
31246
31574
  try {
31247
- parsed = JSON.parse(readFileSync12(file, "utf8"));
31575
+ parsed = JSON.parse(readFileSync13(file, "utf8"));
31248
31576
  } catch (error) {
31249
31577
  throw new HubEnvError(`hub env file is malformed at ${file}: ${error instanceof Error ? error.message : String(error)}`);
31250
31578
  }
@@ -31284,7 +31612,7 @@ function resolveClientHubAuthToken(env, project) {
31284
31612
  }
31285
31613
 
31286
31614
  // plugins/kxm/src/logger.ts
31287
- import { appendFileSync, existsSync as existsSync15, mkdirSync as mkdirSync8, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
31615
+ import { appendFileSync, existsSync as existsSync16, mkdirSync as mkdirSync8, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
31288
31616
  import { dirname as dirname10 } from "node:path";
31289
31617
  var LOG_LEVEL_PRIORITY = {
31290
31618
  debug: 10,
@@ -31322,7 +31650,7 @@ function redactLogValue(val, key) {
31322
31650
  function rotateLogFiles(filePath, maxFiles) {
31323
31651
  for (let i = maxFiles; i >= 1; i--) {
31324
31652
  const current = `${filePath}.${i}`;
31325
- if (existsSync15(current)) {
31653
+ if (existsSync16(current)) {
31326
31654
  if (i >= maxFiles) {
31327
31655
  try {
31328
31656
  unlinkSync2(current);
@@ -31336,7 +31664,7 @@ function rotateLogFiles(filePath, maxFiles) {
31336
31664
  }
31337
31665
  }
31338
31666
  }
31339
- if (existsSync15(filePath)) {
31667
+ if (existsSync16(filePath)) {
31340
31668
  try {
31341
31669
  renameSync4(filePath, `${filePath}.1`);
31342
31670
  } catch {
@@ -31353,7 +31681,7 @@ function createLogger(options) {
31353
31681
  const shouldStdout = options.stdout ?? !isDaemon;
31354
31682
  const correlationDefaults = options.correlation ?? {};
31355
31683
  let currentSize = 0;
31356
- if (filePath && existsSync15(filePath)) {
31684
+ if (filePath && existsSync16(filePath)) {
31357
31685
  try {
31358
31686
  currentSize = statSync5(filePath).size;
31359
31687
  } catch {
@@ -31434,7 +31762,7 @@ function createLogger(options) {
31434
31762
 
31435
31763
  // plugins/kxm/src/runtime-supervisor.ts
31436
31764
  function kxmSupervisorTokenFile(paths) {
31437
- return join18(paths.runtimeDir, "supervisor.token");
31765
+ return join19(paths.runtimeDir, "supervisor.token");
31438
31766
  }
31439
31767
  function publishKxmSupervisorToken(paths, token) {
31440
31768
  const file = kxmSupervisorTokenFile(paths);
@@ -31462,7 +31790,7 @@ function readKxmSupervisorToken(paths) {
31462
31790
  if (stat.isSymbolicLink() || !stat.isFile()) {
31463
31791
  throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
31464
31792
  }
31465
- const token = readFileSync13(file, "utf8").trim();
31793
+ const token = readFileSync14(file, "utf8").trim();
31466
31794
  return token.length >= 32 ? token : void 0;
31467
31795
  }
31468
31796
  function processAlive(pid) {
@@ -31476,11 +31804,11 @@ function processAlive(pid) {
31476
31804
  var HEARTBEAT_STALE_MS = 15e3;
31477
31805
  var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
31478
31806
  function supervisorErrorFile(paths) {
31479
- return join18(paths.runtimeDir, "supervisor.error");
31807
+ return join19(paths.runtimeDir, "supervisor.error");
31480
31808
  }
31481
31809
  function clearSupervisorError(paths) {
31482
31810
  const file = supervisorErrorFile(paths);
31483
- if (existsSync16(file)) rmSync4(file, { force: true });
31811
+ if (existsSync17(file)) rmSync4(file, { force: true });
31484
31812
  }
31485
31813
  function recordSupervisorError(paths, message) {
31486
31814
  try {
@@ -31497,7 +31825,7 @@ function readRecentSupervisorError(paths) {
31497
31825
  const ageMs = Date.now() - stat.mtimeMs;
31498
31826
  if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
31499
31827
  try {
31500
- return readFileSync13(file, "utf8").trim();
31828
+ return readFileSync14(file, "utf8").trim();
31501
31829
  } catch {
31502
31830
  return void 0;
31503
31831
  }
@@ -31536,7 +31864,7 @@ function supervisorStatusOf(record2) {
31536
31864
  };
31537
31865
  }
31538
31866
  function kxmSupervisorStatus(paths, options = {}) {
31539
- if (!existsSync16(paths.registryDb)) return { running: false };
31867
+ if (!existsSync17(paths.registryDb)) return { running: false };
31540
31868
  if (options.readOnly) {
31541
31869
  const database = openReadOnlyDatabase(paths.registryDb);
31542
31870
  try {
@@ -31602,7 +31930,7 @@ async function ensureKxmSupervisor(options = {}) {
31602
31930
  throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
31603
31931
  }
31604
31932
  clearSupervisorError(paths);
31605
- const scriptPath = join18(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
31933
+ const scriptPath = join19(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
31606
31934
  const spawnImpl = options.spawnImpl ?? ((script, env) => {
31607
31935
  const child = spawn3(process.execPath, [script], {
31608
31936
  detached: true,
@@ -31825,7 +32153,7 @@ function syncFailureText(error) {
31825
32153
  return `${code ? `${code}: ` : ""}${message}`.replace(/(kxm_[A-Za-z0-9_]+|[A-Za-z0-9._-]{40,})/g, "[redacted]").slice(0, 300);
31826
32154
  }
31827
32155
  function runtimeSupervisorLogFile(paths) {
31828
- return join18(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
32156
+ return join19(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
31829
32157
  }
31830
32158
  async function startKxmRuntimeSupervisor(options = {}) {
31831
32159
  const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
@@ -31950,8 +32278,8 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
31950
32278
  openRunIds = unsettledRunIds(existing2);
31951
32279
  } else {
31952
32280
  const registration = registry.projectByRoot(projectRoot);
31953
- const eventsPath = join18(paths.projectsDir, registration?.projectKey ?? projectRuntimeKey(projectRoot), "run-events.db");
31954
- if (registration && existsSync16(eventsPath)) {
32281
+ const eventsPath = join19(paths.projectsDir, registration?.projectKey ?? projectRuntimeKey(projectRoot), "run-events.db");
32282
+ if (registration && existsSync17(eventsPath)) {
31955
32283
  const store = new KxmRunEventStore(eventsPath);
31956
32284
  try {
31957
32285
  openRunIds = store.runsForProject(registration.projectId, 1e4).filter((run) => !SETTLED_RUN_STATUS.has(run.status)).map((run) => run.runId);
@@ -32467,7 +32795,7 @@ function handoffSuffix(handoff) {
32467
32795
 
32468
32796
  // plugins/kxm/src/pi-producer.ts
32469
32797
  import { spawn as spawn4 } from "node:child_process";
32470
- import { join as join19 } from "node:path";
32798
+ import { join as join20 } from "node:path";
32471
32799
  import { StringDecoder } from "node:string_decoder";
32472
32800
  function formatPiSessionKey(params) {
32473
32801
  if (params.agentId === "coordinator") {
@@ -32841,7 +33169,7 @@ function createKxmPiProducer(options = {}) {
32841
33169
  const args = ["--mode", "rpc", "--name", displayName];
32842
33170
  if (options.sessionDir) {
32843
33171
  const safeDirName = key.replace(/[^a-zA-Z0-9_-]/g, "_");
32844
- args.push("--session-dir", join19(options.sessionDir, request.runId, safeDirName));
33172
+ args.push("--session-dir", join20(options.sessionDir, request.runId, safeDirName));
32845
33173
  }
32846
33174
  if (model) {
32847
33175
  args.push("--model", model);
@@ -32970,8 +33298,8 @@ function createKxmPiProducer(options = {}) {
32970
33298
 
32971
33299
  // plugins/kxm/src/improve.ts
32972
33300
  import { createHash as createHash17 } from "node:crypto";
32973
- import { existsSync as existsSync17, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "node:fs";
32974
- import { join as join20, relative as relative5, resolve as resolve11 } from "node:path";
33301
+ import { existsSync as existsSync18, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "node:fs";
33302
+ import { join as join21, relative as relative5, resolve as resolve11 } from "node:path";
32975
33303
  var CANDIDATE_SCHEMA = "kxm.candidate.v1";
32976
33304
  var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
32977
33305
  var IMPROVEMENT_REPORT_V1_SCHEMA = "kxm.improvement-report.v1";
@@ -33228,7 +33556,7 @@ function groupRoutingRecords(records, options = {}) {
33228
33556
  }
33229
33557
  function buildImprovementReport(records, options = {}) {
33230
33558
  const projectRoot = options.projectRoot ? resolve11(options.projectRoot) : process.cwd();
33231
- const candidatesDir = options.candidatesDir ? resolve11(options.candidatesDir) : join20(projectRoot, ".kxm", "candidates");
33559
+ const candidatesDir = options.candidatesDir ? resolve11(options.candidatesDir) : join21(projectRoot, ".kxm", "candidates");
33232
33560
  const promotionPolicy = options.promotionPolicy ?? "manual_pr";
33233
33561
  const groups = groupRoutingRecords(records, options);
33234
33562
  const candidates = [];
@@ -33242,7 +33570,7 @@ function buildImprovementReport(records, options = {}) {
33242
33570
  group.workflowId
33243
33571
  );
33244
33572
  const diffFileName = `${group.candidateId}.diff`;
33245
- const diffFilePath = join20(candidatesDir, diffFileName);
33573
+ const diffFilePath = join21(candidatesDir, diffFileName);
33246
33574
  const relDiffPath = relative5(projectRoot, diffFilePath).replace(/\\/g, "/");
33247
33575
  const candidate = {
33248
33576
  schema: CANDIDATE_SCHEMA,
@@ -33264,11 +33592,11 @@ function buildImprovementReport(records, options = {}) {
33264
33592
  createdAt: nowIso()
33265
33593
  };
33266
33594
  if (!options.dryRun) {
33267
- if (!existsSync17(candidatesDir)) {
33595
+ if (!existsSync18(candidatesDir)) {
33268
33596
  mkdirSync10(candidatesDir, { recursive: true });
33269
33597
  }
33270
33598
  writeFileSync10(diffFilePath, diff, "utf8");
33271
- const jsonFilePath = join20(candidatesDir, `${group.candidateId}.json`);
33599
+ const jsonFilePath = join21(candidatesDir, `${group.candidateId}.json`);
33272
33600
  writeFileSync10(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
33273
33601
  }
33274
33602
  candidates.push(candidate);
@@ -33297,7 +33625,7 @@ function buildImprovementReport(records, options = {}) {
33297
33625
  }
33298
33626
  function writeImprovementReport(improvementsDir, report, dryRun = false) {
33299
33627
  const stamp = report.createdAt.replace(/[:.]/g, "-");
33300
- const path = join20(improvementsDir, `${stamp}.json`);
33628
+ const path = join21(improvementsDir, `${stamp}.json`);
33301
33629
  if (!dryRun) {
33302
33630
  mkdirSync10(improvementsDir, { recursive: true });
33303
33631
  writeFileSync10(path, `${JSON.stringify(report, null, 2)}
@@ -33958,9 +34286,9 @@ Instructions for Operator:
33958
34286
  };
33959
34287
 
33960
34288
  // plugins/kxm/src/modes.ts
33961
- var import_yaml10 = __toESM(require_dist(), 1);
33962
- import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
33963
- import { join as join21 } from "node:path";
34289
+ var import_yaml11 = __toESM(require_dist(), 1);
34290
+ import { existsSync as existsSync19, readFileSync as readFileSync16 } from "node:fs";
34291
+ import { join as join22 } from "node:path";
33964
34292
  var DEFAULT_MODES_CONFIG = Object.freeze({
33965
34293
  schema: "kxm.modes.v1",
33966
34294
  majorModes: {
@@ -34023,13 +34351,13 @@ function loadModesConfig(projectRoot) {
34023
34351
  if (!projectRoot) {
34024
34352
  return DEFAULT_MODES_CONFIG;
34025
34353
  }
34026
- const modesPath = join21(projectRoot, ".kxm", "modes.yaml");
34027
- if (!existsSync18(modesPath)) {
34354
+ const modesPath = join22(projectRoot, ".kxm", "modes.yaml");
34355
+ if (!existsSync19(modesPath)) {
34028
34356
  return DEFAULT_MODES_CONFIG;
34029
34357
  }
34030
34358
  try {
34031
- const raw = readFileSync15(modesPath, "utf8");
34032
- const parsed = (0, import_yaml10.parse)(raw);
34359
+ const raw = readFileSync16(modesPath, "utf8");
34360
+ const parsed = (0, import_yaml11.parse)(raw);
34033
34361
  if (parsed && parsed.schema === "kxm.modes.v1" && parsed.majorModes) {
34034
34362
  return {
34035
34363
  schema: "kxm.modes.v1",
@@ -34114,11 +34442,11 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
34114
34442
  estimatedTokens: estimateTokens(baseSystemPromptChars)
34115
34443
  });
34116
34444
  for (const relPath of resolved.contextFiles) {
34117
- const fullPath = join21(projectRoot, relPath);
34445
+ const fullPath = join22(projectRoot, relPath);
34118
34446
  let chars = 0;
34119
- if (existsSync18(fullPath)) {
34447
+ if (existsSync19(fullPath)) {
34120
34448
  try {
34121
- chars = readFileSync15(fullPath, "utf8").length;
34449
+ chars = readFileSync16(fullPath, "utf8").length;
34122
34450
  } catch {
34123
34451
  chars = 0;
34124
34452
  }
@@ -34250,9 +34578,9 @@ ${divider}
34250
34578
 
34251
34579
  // plugins/kxm/src/ssh-remote.ts
34252
34580
  import { spawnSync as spawnSync6 } from "node:child_process";
34253
- import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync16, readdirSync as readdirSync9, rmSync as rmSync5, statSync as statSync6 } from "node:fs";
34581
+ import { existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync17, readdirSync as readdirSync10, rmSync as rmSync5, statSync as statSync6 } from "node:fs";
34254
34582
  import { homedir as homedir4 } from "node:os";
34255
- import { join as join22, resolve as resolve12 } from "node:path";
34583
+ import { join as join23, resolve as resolve12 } from "node:path";
34256
34584
  var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
34257
34585
  var MAX_SSH_OUTPUT_LINES = 2e3;
34258
34586
  var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
@@ -34278,12 +34606,12 @@ function truncateSshOutput(raw) {
34278
34606
  return { text, truncated };
34279
34607
  }
34280
34608
  function parseSshConfig(configPath) {
34281
- const targetPath = configPath ?? join22(homedir4(), ".ssh", "config");
34282
- if (!existsSync19(targetPath)) {
34609
+ const targetPath = configPath ?? join23(homedir4(), ".ssh", "config");
34610
+ if (!existsSync20(targetPath)) {
34283
34611
  return [];
34284
34612
  }
34285
34613
  try {
34286
- const content = readFileSync16(targetPath, "utf-8");
34614
+ const content = readFileSync17(targetPath, "utf-8");
34287
34615
  const lines = content.split("\n");
34288
34616
  const hosts = [];
34289
34617
  let currentHosts = [];
@@ -34361,14 +34689,14 @@ function resolveSshHostG(host, execFn = spawnSync6) {
34361
34689
  }
34362
34690
  function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
34363
34691
  const resolved = resolve12(socketDir);
34364
- if (!existsSync19(resolved)) {
34692
+ if (!existsSync20(resolved)) {
34365
34693
  mkdirSync11(resolved, { recursive: true, mode: 448 });
34366
34694
  }
34367
34695
  return resolved;
34368
34696
  }
34369
34697
  function buildSshArgs(options) {
34370
34698
  const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
34371
- const controlPath = join22(socketDir, "%C");
34699
+ const controlPath = join23(socketDir, "%C");
34372
34700
  const persist2 = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
34373
34701
  const args = [
34374
34702
  "-o",
@@ -34393,7 +34721,7 @@ function buildSshArgs(options) {
34393
34721
  }
34394
34722
  function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync6) {
34395
34723
  const resolvedDir = ensureSocketDir(socketDir);
34396
- const controlPath = join22(resolvedDir, "%C");
34724
+ const controlPath = join23(resolvedDir, "%C");
34397
34725
  try {
34398
34726
  const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
34399
34727
  encoding: "utf-8"
@@ -34405,7 +34733,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
34405
34733
  }
34406
34734
  function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync6) {
34407
34735
  const resolvedDir = ensureSocketDir(socketDir);
34408
- const controlPath = join22(resolvedDir, "%C");
34736
+ const controlPath = join23(resolvedDir, "%C");
34409
34737
  try {
34410
34738
  const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
34411
34739
  encoding: "utf-8"
@@ -34419,9 +34747,9 @@ function pruneSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
34419
34747
  const resolvedDir = ensureSocketDir(socketDir);
34420
34748
  let removed = 0;
34421
34749
  try {
34422
- const entries = readdirSync9(resolvedDir);
34750
+ const entries = readdirSync10(resolvedDir);
34423
34751
  for (const entry of entries) {
34424
- const fullPath = join22(resolvedDir, entry);
34752
+ const fullPath = join23(resolvedDir, entry);
34425
34753
  try {
34426
34754
  const stat = statSync6(fullPath);
34427
34755
  if (stat.isSocket()) {