@kontextmind/kxm 0.7.144 → 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
@@ -14781,9 +14781,9 @@ var require_dist = __commonJS({
14781
14781
  // plugins/kxm/src/runtime-supervisor.ts
14782
14782
  import { spawn as spawn3 } from "node:child_process";
14783
14783
  import { createHash as createHash15, createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
14784
- 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";
14784
+ 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";
14785
14785
  import { createServer } from "node:http";
14786
- import { dirname as dirname11, isAbsolute as isAbsolute8, join as join18 } from "node:path";
14786
+ import { dirname as dirname11, isAbsolute as isAbsolute8, join as join19 } from "node:path";
14787
14787
 
14788
14788
  // plugins/kxm/src/repo-root.ts
14789
14789
  import { existsSync } from "node:fs";
@@ -14813,8 +14813,8 @@ function findKxmRepoRoot(fromUrl = import.meta.url) {
14813
14813
  var import__ = __toESM(require__(), 1);
14814
14814
  import { spawnSync as spawnSync2 } from "node:child_process";
14815
14815
  import { createHash as createHash3 } from "node:crypto";
14816
- import { existsSync as existsSync3, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
14817
- import { basename, dirname as dirname2, extname, isAbsolute, join as join2, relative, resolve, sep } from "node:path";
14816
+ import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync2, readdirSync as readdirSync2, realpathSync } from "node:fs";
14817
+ import { basename, dirname as dirname2, extname, isAbsolute, join as join3, relative, resolve, sep } from "node:path";
14818
14818
 
14819
14819
  // plugins/kxm/src/restricted-yaml.mjs
14820
14820
  var import_yaml = __toESM(require_dist(), 1);
@@ -14966,6 +14966,7 @@ var MODES = Object.freeze(["headless", "interactive", "either"]);
14966
14966
  var MODEL_KEYS = Object.freeze([
14967
14967
  "schema",
14968
14968
  "id",
14969
+ "aliases",
14969
14970
  "harness",
14970
14971
  "model",
14971
14972
  "vendor",
@@ -15166,6 +15167,9 @@ function validateModelShape(document, id, label, issues) {
15166
15167
  if (document.id !== void 0 && document.id !== id) {
15167
15168
  issues.push(issue2("schema", "identity_mismatch", label, `declared id ${String(document.id)} does not match ${id}`));
15168
15169
  }
15170
+ if (document.aliases !== void 0 && !identifierList(document.aliases)) {
15171
+ issues.push(issue2("schema", "schema_pattern", label, "aliases must be unique identifiers"));
15172
+ }
15169
15173
  if (document.harness !== void 0 && !identifier(document.harness)) {
15170
15174
  issues.push(issue2("schema", "schema_pattern", label, "harness must be an identifier"));
15171
15175
  }
@@ -15428,9 +15432,9 @@ function validateRoleSemantics(role, id, label, models, options, issues) {
15428
15432
  }
15429
15433
  if (id === role.purpose && CRITIC_PURPOSES.includes(role.purpose)) {
15430
15434
  const admitted = role.roster.map((entry) => models.get(entry.route)).filter((model) => model && admittedRoute(model));
15431
- if (admitted.length !== 1) {
15432
- issues.push(issue2("semantic", "critic_route_count", label, "required critic purpose files must list exactly one admitted route"));
15433
- } else if (admitted[0].permissions.length !== 1 || admitted[0].permissions[0] !== "read-only" || role.permission !== "read-only") {
15435
+ if (admitted.length < 1) {
15436
+ issues.push(issue2("semantic", "critic_route_count", label, "required critic purpose files must list at least one admitted route"));
15437
+ } else if (role.permission !== "read-only" || admitted.some((model) => model.permissions.length !== 1 || model.permissions[0] !== "read-only")) {
15434
15438
  issues.push(issue2("semantic", "permission_escalation", label, "critic purpose files must be read-only"));
15435
15439
  }
15436
15440
  }
@@ -15462,7 +15466,7 @@ function validateCriticVendors(roles, models, options, issues) {
15462
15466
  const role = roles.get(purpose);
15463
15467
  if (!role || role.purpose !== purpose) continue;
15464
15468
  const admitted = (role.roster ?? []).map((entry) => models.get(entry.route)).filter((model) => model && admittedRoute(model));
15465
- if (admitted.length === 1) critics.push({ purpose, vendor: canonicalVendor(admitted[0].vendor, aliases) });
15469
+ if (admitted.length >= 1) critics.push({ purpose, vendor: canonicalVendor(admitted[0].vendor, aliases) });
15466
15470
  }
15467
15471
  if (critics.length === 2 && critics[0].vendor === critics[1].vendor) {
15468
15472
  issues.push(issue2("semantic", "critic_vendor_collision", "roles/reviewer-arch", "required critics must have independent vendors"));
@@ -15525,8 +15529,272 @@ function validatePolicyDraft(input, options) {
15525
15529
  return { ok: true, data };
15526
15530
  }
15527
15531
 
15528
- // plugins/kxm/src/template.ts
15532
+ // plugins/kxm/src/workforce-names.mjs
15529
15533
  var import_yaml2 = __toESM(require_dist(), 1);
15534
+ import { existsSync as existsSync2, readdirSync, readFileSync } from "node:fs";
15535
+ import { join as join2 } from "node:path";
15536
+ var ROSTER_EFFORTS = /* @__PURE__ */ new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
15537
+ var ROLE_IDS = Object.freeze([
15538
+ "writer",
15539
+ "planner",
15540
+ "reviewer-arch",
15541
+ "reviewer-cli",
15542
+ "experiment"
15543
+ ]);
15544
+ var ROUTE_RENAMES = Object.freeze([
15545
+ ["grok-native", "grok-grok-4-7"],
15546
+ ["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
15547
+ ["gemini-agy", "agy-gemini-3-8-flash-high"],
15548
+ ["fable-claude", "claude-fable"],
15549
+ ["sol-codex", "codex-gpt-5-6-sol"],
15550
+ ["grok-default", "grok-grok-4-6"],
15551
+ ["fable-default", "claude-fable"]
15552
+ ]);
15553
+ var AGENT_RENAMES = Object.freeze([
15554
+ ["coordinator", "planner"],
15555
+ ["implementer", "writer"],
15556
+ ["critic-arch", "reviewer-arch"],
15557
+ ["critic-cli", "reviewer-cli"]
15558
+ ]);
15559
+ var WORKFLOW_RENAMES = Object.freeze([
15560
+ ["implement-only", "writer-only"],
15561
+ ["review-arch-only", "reviewer-arch-only"],
15562
+ ["review-cli-only", "reviewer-cli-only"]
15563
+ ]);
15564
+ var STEP_RENAMES = Object.freeze([
15565
+ ["implement", "writer"],
15566
+ ["critic-arch", "reviewer-arch"],
15567
+ ["review-arch", "reviewer-arch"],
15568
+ ["critic-cli", "reviewer-cli"],
15569
+ ["review-cli", "reviewer-cli"]
15570
+ ]);
15571
+ var RENAMES = Object.freeze({
15572
+ route: ROUTE_RENAMES,
15573
+ agent: AGENT_RENAMES,
15574
+ workflow: WORKFLOW_RENAMES,
15575
+ step: STEP_RENAMES
15576
+ });
15577
+ var RESERVED_WORKFLOW_IDS = /* @__PURE__ */ new Set(["default", "land"]);
15578
+ var warned = /* @__PURE__ */ new Set();
15579
+ function noteDeprecatedId(kind, from, to) {
15580
+ const key = `${kind}\0${from}\0${to}`;
15581
+ if (warned.has(key)) return;
15582
+ warned.add(key);
15583
+ if (process.env.KXM_QUIET_ALIASES === "1") return;
15584
+ console.warn(`kxm: deprecated ${kind} id '${from}' resolves to '${to}'`);
15585
+ }
15586
+ function resolveRenamedId(requested, knownIds, pairs) {
15587
+ if (typeof requested !== "string" || knownIds.has(requested)) return requested;
15588
+ for (const [oldId, newId2] of pairs) {
15589
+ if (requested === oldId && knownIds.has(newId2)) return newId2;
15590
+ if (requested === newId2 && knownIds.has(oldId)) return oldId;
15591
+ }
15592
+ return requested;
15593
+ }
15594
+ function canonicalRouteId(harness, model) {
15595
+ if (typeof harness !== "string" || typeof model !== "string" || !harness || !model) return void 0;
15596
+ const parts = model.split("/").filter((part) => part.length > 0);
15597
+ if (parts.length === 0) return void 0;
15598
+ const slug = parts[parts.length - 1].replaceAll(".", "-").toLowerCase();
15599
+ const provider = parts.length > 1 ? parts[0].replaceAll(".", "-").toLowerCase() : void 0;
15600
+ const id = provider ? `${harness}-${slug}-${provider}` : `${harness}-${slug}`;
15601
+ return /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(id) && id.length <= 64 ? id : void 0;
15602
+ }
15603
+ function aliasList(value) {
15604
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
15605
+ }
15606
+ function lookupById(records, requested, kind) {
15607
+ const list = [...records].filter((record2) => typeof record2?.id === "string" && record2.id.length > 0);
15608
+ const known = new Set(list.map((record2) => record2.id));
15609
+ const direct = list.find((record2) => record2.id === requested);
15610
+ if (direct) return { record: direct, viaAlias: false };
15611
+ for (const record2 of list) {
15612
+ if (aliasList(record2.aliases).includes(requested)) {
15613
+ noteDeprecatedId(kind, requested, record2.id);
15614
+ return { record: record2, viaAlias: true };
15615
+ }
15616
+ }
15617
+ const renamed = resolveRenamedId(requested, known, RENAMES[kind] ?? []);
15618
+ if (renamed !== requested) {
15619
+ const record2 = list.find((item) => item.id === renamed);
15620
+ if (record2) {
15621
+ noteDeprecatedId(kind, requested, renamed);
15622
+ return { record: record2, viaAlias: true };
15623
+ }
15624
+ }
15625
+ return void 0;
15626
+ }
15627
+ function findYamlBasename(directory, requested, kind) {
15628
+ if (typeof requested !== "string" || !requested) return void 0;
15629
+ if (existsSync2(join2(directory, `${requested}.yaml`))) return requested;
15630
+ if (!existsSync2(directory)) return void 0;
15631
+ const found = [];
15632
+ for (const name of readdirSync(directory)) {
15633
+ if (!name.endsWith(".yaml") || name === "inventory.yaml") continue;
15634
+ const id = name.slice(0, -5);
15635
+ let doc;
15636
+ try {
15637
+ doc = import_yaml2.default.parse(readFileSync(join2(directory, name), "utf8"));
15638
+ } catch {
15639
+ continue;
15640
+ }
15641
+ const aliases = doc && typeof doc === "object" ? aliasList(doc.aliases) : [];
15642
+ found.push({ id, aliases });
15643
+ }
15644
+ const hit = lookupById(found, requested, kind);
15645
+ return hit?.record.id;
15646
+ }
15647
+ function readYamlDir(directory, skipInventory) {
15648
+ if (!existsSync2(directory)) return [];
15649
+ const docs = [];
15650
+ for (const name of readdirSync(directory)) {
15651
+ if (!name.endsWith(".yaml")) continue;
15652
+ const id = name.slice(0, -5);
15653
+ if (skipInventory && id === "inventory") continue;
15654
+ let doc;
15655
+ try {
15656
+ doc = import_yaml2.default.parse(readFileSync(join2(directory, name), "utf8"));
15657
+ } catch (error) {
15658
+ docs.push({ id, file: `${directory}/${name}`, error: error instanceof Error ? error.message : "invalid YAML" });
15659
+ continue;
15660
+ }
15661
+ if (!doc || typeof doc !== "object" || Array.isArray(doc)) {
15662
+ docs.push({ id, file: `${directory}/${name}`, error: "root must be a mapping" });
15663
+ continue;
15664
+ }
15665
+ docs.push({ id, file: name, doc });
15666
+ }
15667
+ return docs;
15668
+ }
15669
+ function push(bucket, severity, code, file, message) {
15670
+ bucket.push({ severity, code, file, message });
15671
+ }
15672
+ function selectorsFor(doc) {
15673
+ const model = typeof doc.model === "string" ? doc.model : "";
15674
+ const vendor = typeof doc.vendor === "string" ? doc.vendor : "";
15675
+ const harness = typeof doc.harness === "string" ? doc.harness : "";
15676
+ return [model, vendor && model ? `${vendor}/${model}` : "", harness && model ? `${harness}/${model}` : ""].filter(Boolean);
15677
+ }
15678
+ function lintWorkforce(root) {
15679
+ const errors = [];
15680
+ const warnings = [];
15681
+ const models = readYamlDir(join2(root, ".kxm", "models"), true).filter((entry) => !entry.error);
15682
+ for (const entry of readYamlDir(join2(root, ".kxm", "models"), true)) {
15683
+ if (entry.error) push(errors, "error", "invalid_yaml", `.kxm/models/${entry.id}.yaml`, entry.error);
15684
+ }
15685
+ const roles = readYamlDir(join2(root, ".kxm", "roles"), false).filter((entry) => !entry.error);
15686
+ const agents = readYamlDir(join2(root, ".kxm", "agents"), false).filter((entry) => !entry.error);
15687
+ const workflows = readYamlDir(join2(root, ".kxm", "workflows"), false).filter((entry) => !entry.error);
15688
+ let admitted = [];
15689
+ const routesFile = join2(root, ".kxm", "routes.yaml");
15690
+ if (existsSync2(routesFile)) {
15691
+ try {
15692
+ const policy = import_yaml2.default.parse(readFileSync(routesFile, "utf8"));
15693
+ admitted = Array.isArray(policy?.admitted) ? policy.admitted.filter((item) => typeof item === "string") : [];
15694
+ } catch (error) {
15695
+ push(errors, "error", "invalid_yaml", ".kxm/routes.yaml", error instanceof Error ? error.message : "invalid YAML");
15696
+ }
15697
+ }
15698
+ const modelRecords = models.map((entry) => ({ id: entry.id, aliases: aliasList(entry.doc.aliases), entry }));
15699
+ const used = /* @__PURE__ */ new Set();
15700
+ for (const role of roles) {
15701
+ const purpose = role.doc.purpose;
15702
+ if (typeof purpose === "string" && role.id !== purpose) {
15703
+ push(errors, "error", "role_id_convention", `.kxm/roles/${role.id}.yaml`, `role id '${role.id}' must equal purpose '${purpose}'`);
15704
+ }
15705
+ const roster = Array.isArray(role.doc.roster) ? role.doc.roster : [];
15706
+ for (const item of roster) {
15707
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
15708
+ const route = item.route;
15709
+ const effort = item.effort;
15710
+ const routeLabel = typeof route === "string" && route ? route : "(missing route)";
15711
+ if (typeof effort !== "string" || !ROSTER_EFFORTS.has(effort)) {
15712
+ const detail = typeof effort === "string" ? `effort '${effort}' is not one of off, minimal, low, medium, high, xhigh, max` : "has no effort";
15713
+ push(errors, "error", "roster_effort_required", `.kxm/roles/${role.id}.yaml`, `roster route '${routeLabel}' ${detail}`);
15714
+ }
15715
+ if (typeof route !== "string" || !route) continue;
15716
+ const found = lookupById(modelRecords, route, "route");
15717
+ if (!found) {
15718
+ push(errors, "error", "route_unknown", `.kxm/roles/${role.id}.yaml`, `roster route '${route}' does not match a model file`);
15719
+ continue;
15720
+ }
15721
+ used.add(found.record.id);
15722
+ if (found.viaAlias) {
15723
+ push(warnings, "warning", "deprecated_id", `.kxm/roles/${role.id}.yaml`, `roster route '${route}' is a deprecated alias of '${found.record.id}'`);
15724
+ }
15725
+ }
15726
+ }
15727
+ const covered = /* @__PURE__ */ new Set();
15728
+ for (const model of models) {
15729
+ const doc = model.doc;
15730
+ if (typeof doc.id === "string" && doc.id !== model.id) {
15731
+ push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `declared id '${doc.id}' does not match the filename`);
15732
+ }
15733
+ const expected = canonicalRouteId(doc.harness, doc.model);
15734
+ if (!expected || model.id !== expected) {
15735
+ push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
15736
+ }
15737
+ if (!used.has(model.id)) {
15738
+ push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
15739
+ }
15740
+ const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
15741
+ if (!selectorHit) {
15742
+ push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
15743
+ } else {
15744
+ covered.add(selectorHit);
15745
+ }
15746
+ }
15747
+ for (const selector of admitted) {
15748
+ if (!covered.has(selector)) {
15749
+ push(warnings, "warning", "admitted_unrouted", ".kxm/routes.yaml", `admitted model '${selector}' is not used by any route`);
15750
+ }
15751
+ }
15752
+ const agentRecords = agents.map((entry) => ({ id: entry.id, aliases: aliasList(entry.doc.aliases), entry }));
15753
+ for (const agent of agents) {
15754
+ const role = agent.doc.role;
15755
+ if (typeof role !== "string" || agent.id !== role) {
15756
+ push(errors, "error", "agent_id_convention", `.kxm/agents/${agent.id}.yaml`, `agent id '${agent.id}' must equal its role '${role ?? ""}'`);
15757
+ }
15758
+ }
15759
+ for (const workflow of workflows) {
15760
+ if (!RESERVED_WORKFLOW_IDS.has(workflow.id) && !ROLE_IDS.some((role) => workflow.id === `${role}-only`)) {
15761
+ push(errors, "error", "workflow_id_convention", `.kxm/workflows/${workflow.id}.yaml`, `workflow id '${workflow.id}' must be default, land, or <role>-only`);
15762
+ }
15763
+ const steps = Array.isArray(workflow.doc.steps) ? workflow.doc.steps : [];
15764
+ const realIds = new Set(steps.map((step) => step && typeof step.id === "string" ? step.id : "").filter(Boolean));
15765
+ for (const step of steps) {
15766
+ if (!step || typeof step !== "object" || typeof step.id !== "string") continue;
15767
+ if (step.kind === "agent" || step.kind === "moa") {
15768
+ const agentName = typeof step.agent === "string" ? step.agent : "";
15769
+ const found = agentName ? lookupById(agentRecords, agentName, "agent") : void 0;
15770
+ if (!found) {
15771
+ push(errors, "error", "agent_unknown", `.kxm/workflows/${workflow.id}.yaml`, `step '${step.id}' references unknown agent '${agentName}'`);
15772
+ } else if (found.viaAlias) {
15773
+ push(warnings, "warning", "deprecated_id", `.kxm/workflows/${workflow.id}.yaml`, `step '${step.id}' agent '${agentName}' is a deprecated alias of '${found.record.id}'`);
15774
+ }
15775
+ const role = found?.record.entry.doc.role;
15776
+ if (typeof role === "string" && step.id !== role) {
15777
+ push(errors, "error", "step_id_convention", `.kxm/workflows/${workflow.id}.yaml`, `agent step '${step.id}' must use the role id '${role}'`);
15778
+ }
15779
+ } else if (step.kind === "gate") {
15780
+ const gate = typeof step.gate === "string" ? step.gate : "";
15781
+ const allowed = step.id === "verify" || step.id === gate || step.id.startsWith(`${workflow.id}-`);
15782
+ if (!allowed) {
15783
+ 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>`);
15784
+ }
15785
+ }
15786
+ for (const alias of aliasList(step.aliases)) {
15787
+ if (realIds.has(alias) && alias !== step.id) {
15788
+ push(errors, "error", "step_id_convention", `.kxm/workflows/${workflow.id}.yaml`, `step alias '${alias}' collides with another step id`);
15789
+ }
15790
+ }
15791
+ }
15792
+ }
15793
+ return { errors, warnings };
15794
+ }
15795
+
15796
+ // plugins/kxm/src/template.ts
15797
+ var import_yaml3 = __toESM(require_dist(), 1);
15530
15798
  import { createHash as createHash2 } from "node:crypto";
15531
15799
  var KXM_TEMPLATE_ID = "builtin-minimal";
15532
15800
  var KXM_TEMPLATE_PROVENANCE_PATH = ".kxm/template-provenance.yaml";
@@ -15663,33 +15931,60 @@ function coreTemplate(projectId, projectName, variant) {
15663
15931
  ]);
15664
15932
  if (variant === "v4-registry") {
15665
15933
  const coordinator = files.get(".kxm/agents/coordinator.yaml");
15666
- if (coordinator) files.set(".kxm/agents/coordinator.yaml", { ...coordinator, role: "planner" });
15934
+ if (coordinator) {
15935
+ files.delete(".kxm/agents/coordinator.yaml");
15936
+ files.set(".kxm/agents/planner.yaml", { ...coordinator, role: "planner", aliases: ["coordinator"] });
15937
+ }
15667
15938
  const implementer = files.get(".kxm/agents/implementer.yaml");
15668
- if (implementer) files.set(".kxm/agents/implementer.yaml", { ...implementer, role: "writer" });
15939
+ if (implementer) {
15940
+ files.delete(".kxm/agents/implementer.yaml");
15941
+ files.set(".kxm/agents/writer.yaml", { ...implementer, role: "writer", aliases: ["implementer"] });
15942
+ }
15669
15943
  const workflow = files.get(".kxm/workflows/default.yaml");
15670
15944
  if (workflow) {
15671
15945
  const limits = { ...workflow.limits };
15672
15946
  delete limits.maxAgentTimeMs;
15673
- files.set(".kxm/workflows/default.yaml", { ...workflow, limits });
15947
+ const steps = workflow.steps.map((step) => {
15948
+ if (step.id === "plan") {
15949
+ const on = { ...step.on, passed: "writer" };
15950
+ return { ...step, agent: "planner", on };
15951
+ }
15952
+ if (step.id === "implement") {
15953
+ const assignments = { ...step.assignments, allowedAgents: ["writer"] };
15954
+ return { ...step, id: "writer", aliases: ["implement"], agent: "writer", assignments };
15955
+ }
15956
+ if (step.id === "verify") {
15957
+ const on = { ...step.on };
15958
+ const failure = on["implementation-failure"];
15959
+ if (failure && typeof failure === "object" && !Array.isArray(failure)) {
15960
+ on["implementation-failure"] = { ...failure, target: "writer" };
15961
+ }
15962
+ return { ...step, on };
15963
+ }
15964
+ return step;
15965
+ });
15966
+ files.set(".kxm/workflows/default.yaml", { ...workflow, coordinator: "planner", limits, steps });
15674
15967
  }
15675
15968
  files.set(".kxm/routes.yaml", {
15676
15969
  schema: "kxm.routes.v2",
15677
- updatedAt: "2026-09-23T00:00:00.000Z",
15970
+ updatedAt: "2026-09-27T00:00:00.000Z",
15678
15971
  admitted: ["anthropic/fable", "xai/grok-4.6"],
15679
15972
  disabled: []
15680
15973
  });
15681
- files.set(".kxm/models/grok-default.yaml", {
15974
+ files.set(".kxm/models/grok-grok-4-6.yaml", {
15682
15975
  schema: "kxm.model.v2",
15683
- id: "grok-default",
15976
+ id: "grok-grok-4-6",
15977
+ aliases: ["grok-default"],
15684
15978
  harness: "grok",
15685
15979
  model: "grok-4.6",
15686
15980
  vendor: "xai",
15687
15981
  status: "admitted",
15688
15982
  permissions: ["edit"]
15689
15983
  });
15690
- files.set(".kxm/models/fable-default.yaml", {
15984
+ files.set(".kxm/models/claude-fable.yaml", {
15691
15985
  schema: "kxm.model.v2",
15692
- id: "fable-default",
15986
+ id: "claude-fable",
15987
+ aliases: ["fable-default"],
15693
15988
  harness: "claude",
15694
15989
  model: "fable",
15695
15990
  vendor: "anthropic",
@@ -15702,7 +15997,7 @@ function coreTemplate(projectId, projectName, variant) {
15702
15997
  purpose: "writer",
15703
15998
  permission: "edit",
15704
15999
  description: "Primary implementation agent.",
15705
- roster: [{ route: "grok-default" }]
16000
+ roster: [{ route: "grok-grok-4-6", effort: "medium" }]
15706
16001
  });
15707
16002
  files.set(".kxm/roles/planner.yaml", {
15708
16003
  schema: "kxm.role.v2",
@@ -15710,7 +16005,7 @@ function coreTemplate(projectId, projectName, variant) {
15710
16005
  purpose: "planner",
15711
16006
  permission: "read-only",
15712
16007
  description: "Plans the change before implementation.",
15713
- roster: [{ route: "fable-default" }]
16008
+ roster: [{ route: "claude-fable", effort: "medium" }]
15714
16009
  });
15715
16010
  files.set(".kxm/gates.yaml", {
15716
16011
  schema: "kxm.gate-registry.v1",
@@ -15731,7 +16026,7 @@ function renderKxmTemplate(projectId, projectName, variant = CURRENT_KXM_TEMPLAT
15731
16026
  const values = coreTemplate(projectId, projectName, variant);
15732
16027
  const coreFiles = /* @__PURE__ */ new Map();
15733
16028
  const records = [...values.entries()].map(([path, value]) => {
15734
- const bytes = Buffer.from((0, import_yaml2.stringify)(value, { lineWidth: 0 }), "utf8");
16029
+ const bytes = Buffer.from((0, import_yaml3.stringify)(value, { lineWidth: 0 }), "utf8");
15735
16030
  coreFiles.set(path, bytes);
15736
16031
  return {
15737
16032
  path,
@@ -15751,7 +16046,7 @@ function renderKxmTemplate(projectId, projectName, variant = CURRENT_KXM_TEMPLAT
15751
16046
  const fileEntries = [...coreFiles.entries()];
15752
16047
  fileEntries.push([
15753
16048
  KXM_TEMPLATE_PROVENANCE_PATH,
15754
- Buffer.from((0, import_yaml2.stringify)(provenance, { lineWidth: 0 }), "utf8")
16049
+ Buffer.from((0, import_yaml3.stringify)(provenance, { lineWidth: 0 }), "utf8")
15755
16050
  ]);
15756
16051
  fileEntries.sort(([left], [right]) => compareCodeUnits3(left, right));
15757
16052
  const files = new Map(fileEntries);
@@ -15776,7 +16071,7 @@ function resolveKxmTemplateBaseline(value) {
15776
16071
 
15777
16072
  // plugins/kxm/src/harness.ts
15778
16073
  import { spawnSync } from "node:child_process";
15779
- import { existsSync as existsSync2 } from "node:fs";
16074
+ import { existsSync as existsSync3 } from "node:fs";
15780
16075
  import { win32 as win32Path } from "node:path";
15781
16076
 
15782
16077
  // plugins/kxm/src/oneshot-process.ts
@@ -16415,7 +16710,7 @@ function findWinNpmInnerExe(cliId, options = {}) {
16415
16710
  if ((options.platform ?? process.platform) !== "win32") return void 0;
16416
16711
  const segments = WIN_NPM_INNER_EXE[cliId];
16417
16712
  if (!segments) return void 0;
16418
- const exists = options.existsSync ?? existsSync2;
16713
+ const exists = options.existsSync ?? existsSync3;
16419
16714
  const pathEnv = options.pathEnv ?? process.env.PATH ?? "";
16420
16715
  for (const dir of pathEnv.split(";").filter(Boolean)) {
16421
16716
  if (!exists(win32Path.join(dir, `${cliId}.cmd`))) continue;
@@ -16943,7 +17238,7 @@ var KxmConfigError = class extends Error {
16943
17238
  }
16944
17239
  };
16945
17240
  function defaultKxmSchemaDir() {
16946
- return join2(findKxmRepoRoot(import.meta.url), "schemas");
17241
+ return join3(findKxmRepoRoot(import.meta.url), "schemas");
16947
17242
  }
16948
17243
  var DEFAULT_SCHEMA_DIR = defaultKxmSchemaDir();
16949
17244
  var RESOURCE_SCHEMA = Object.freeze({
@@ -16992,7 +17287,7 @@ function parseRestrictedYaml2(input, label = "<yaml>", limits = KXM_YAML_LIMITS)
16992
17287
  }
16993
17288
  }
16994
17289
  function readJsonObject(file) {
16995
- const parsed = JSON.parse(readFileSync(file, "utf8"));
17290
+ const parsed = JSON.parse(readFileSync2(file, "utf8"));
16996
17291
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${file} is not a JSON object`);
16997
17292
  return parsed;
16998
17293
  }
@@ -17012,10 +17307,10 @@ var KxmSchemaRegistry = class {
17012
17307
  constructor(schemasDir = DEFAULT_SCHEMA_DIR) {
17013
17308
  this.schemasDir = resolve(schemasDir);
17014
17309
  this.ajv = new import__.Ajv2020({ allErrors: true, strict: true, strictRequired: false });
17015
- const common = readJsonObject(join2(this.schemasDir, "common.schema.json"));
17310
+ const common = readJsonObject(join3(this.schemasDir, "common.schema.json"));
17016
17311
  this.ajv.addSchema(common);
17017
17312
  for (const definition of Object.values(RESOURCE_SCHEMA)) {
17018
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, definition.file)));
17313
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, definition.file)));
17019
17314
  }
17020
17315
  const localBindingsFile = "local-repository-bindings.schema.json";
17021
17316
  const templateProvenanceFile = "template-provenance.schema.json";
@@ -17026,15 +17321,15 @@ var KxmSchemaRegistry = class {
17026
17321
  const coordinatorFile = "coordinator.schema.json";
17027
17322
  const intakeMessageFile = "intake-message.schema.json";
17028
17323
  const syncEventFile = "sync-event.schema.json";
17029
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, localBindingsFile)));
17030
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, templateProvenanceFile)));
17031
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, initOperationFile)));
17032
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, permissionDiffFile)));
17033
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, runEventFile)));
17034
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, driveReceiptFile)));
17035
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, coordinatorFile)));
17036
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, intakeMessageFile)));
17037
- this.ajv.addSchema(readJsonObject(join2(this.schemasDir, syncEventFile)));
17324
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, localBindingsFile)));
17325
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, templateProvenanceFile)));
17326
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, initOperationFile)));
17327
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, permissionDiffFile)));
17328
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, runEventFile)));
17329
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, driveReceiptFile)));
17330
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, coordinatorFile)));
17331
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, intakeMessageFile)));
17332
+ this.ajv.addSchema(readJsonObject(join3(this.schemasDir, syncEventFile)));
17038
17333
  for (const [kind, definition] of Object.entries(RESOURCE_SCHEMA)) {
17039
17334
  const validator = this.ajv.getSchema(`https://schemas.kxm.dev/${definition.file}`);
17040
17335
  if (!validator) throw new Error(`schema did not compile: ${definition.file}`);
@@ -17190,15 +17485,15 @@ function containedHostPath(root, candidate) {
17190
17485
  function portableBindingIssue(root, pathHint, repositoryId) {
17191
17486
  let current = root;
17192
17487
  for (const segment of pathHint === "." ? [] : pathHint.split("/")) {
17193
- current = join2(current, segment);
17194
- if (!existsSync3(current)) break;
17488
+ current = join3(current, segment);
17489
+ if (!existsSync4(current)) break;
17195
17490
  const stat = lstatSync(current);
17196
17491
  if (stat.isSymbolicLink()) {
17197
17492
  return issue3("path", "repository_binding_path_link", ".kxm/project.yaml", `portable pathHint for ${repositoryId} traverses a symbolic link or junction`);
17198
17493
  }
17199
17494
  }
17200
17495
  const binding = resolve(root, ...pathHint.split("/"));
17201
- if (existsSync3(binding)) {
17496
+ if (existsSync4(binding)) {
17202
17497
  const realRoot = canonicalHostPath(root);
17203
17498
  const realBinding = canonicalHostPath(binding);
17204
17499
  if (!containedHostPath(realRoot, realBinding)) {
@@ -17249,7 +17544,7 @@ function readResource(registry, root, file, logicalPath, kind, id, containmentRo
17249
17544
  parent = dirname2(parent);
17250
17545
  }
17251
17546
  if (!stat.isFile()) fail2("path", "resource_not_file", label, "configuration resource must be a regular file");
17252
- return { kind, ...id === void 0 ? {} : { id }, file, logicalPath, value: resourceValue(registry, readFileSync(file), label, kind) };
17547
+ return { kind, ...id === void 0 ? {} : { id }, file, logicalPath, value: resourceValue(registry, readFileSync2(file), label, kind) };
17253
17548
  }
17254
17549
  function resourceValue(registry, input, label, kind) {
17255
17550
  const value = parseRestrictedYaml2(input, label);
@@ -17258,14 +17553,14 @@ function resourceValue(registry, input, label, kind) {
17258
17553
  return value;
17259
17554
  }
17260
17555
  function readTemplateProvenance(registry, root) {
17261
- const file = join2(root, ".kxm", "template-provenance.yaml");
17262
- if (!existsSync3(file)) return void 0;
17556
+ const file = join3(root, ".kxm", "template-provenance.yaml");
17557
+ if (!existsSync4(file)) return void 0;
17263
17558
  const label = ".kxm/template-provenance.yaml";
17264
17559
  const stat = lstatSync(file);
17265
17560
  if (stat.isSymbolicLink() || !stat.isFile()) {
17266
17561
  fail2("path", "resource_not_file", label, "template provenance must be a regular file, not a link or directory");
17267
17562
  }
17268
- const configRoot = join2(root, ".kxm");
17563
+ const configRoot = join3(root, ".kxm");
17269
17564
  let parent = dirname2(file);
17270
17565
  while (parent !== root) {
17271
17566
  const parentStat = lstatSync(parent);
@@ -17275,7 +17570,7 @@ function readTemplateProvenance(registry, root) {
17275
17570
  if (parent === configRoot) break;
17276
17571
  parent = dirname2(parent);
17277
17572
  }
17278
- const value = parseRestrictedYaml2(readFileSync(file), label);
17573
+ const value = parseRestrictedYaml2(readFileSync2(file), label);
17279
17574
  const issues = registry.validateTemplateProvenance(value, label);
17280
17575
  if (issues.length > 0) throw new KxmConfigError(issues);
17281
17576
  if (!resolveKxmTemplateBaseline(value)) {
@@ -17306,37 +17601,37 @@ function readTemplateProvenance(registry, root) {
17306
17601
  }
17307
17602
  function listNamedResources(registry, root, directory, logicalDirectory, kind, replacedId, collected) {
17308
17603
  const resources = /* @__PURE__ */ new Map();
17309
- if (!existsSync3(directory)) return resources;
17604
+ if (!existsSync4(directory)) return resources;
17310
17605
  const stat = lstatSync(directory);
17311
17606
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
17312
17607
  fail2("path", "resource_directory_invalid", displayPath(root, directory), "resource directory must be a regular directory");
17313
17608
  }
17314
17609
  const issues = [];
17315
- const entries = readdirSync(directory, { withFileTypes: true }).sort((left, right) => compareCodeUnits4(left.name, right.name));
17610
+ const entries = readdirSync2(directory, { withFileTypes: true }).sort((left, right) => compareCodeUnits4(left.name, right.name));
17316
17611
  for (const entry of entries) {
17317
17612
  if (entry.isDirectory()) {
17318
- issues.push(issue3("path", "nested_resource_directory", displayPath(root, join2(directory, entry.name)), "nested resource directories are not allowed"));
17613
+ issues.push(issue3("path", "nested_resource_directory", displayPath(root, join3(directory, entry.name)), "nested resource directories are not allowed"));
17319
17614
  continue;
17320
17615
  }
17321
17616
  if (!entry.name.toLowerCase().endsWith(".yaml") && !entry.name.toLowerCase().endsWith(".yml")) continue;
17322
17617
  if (!entry.isFile() || extname(entry.name) !== ".yaml") {
17323
- issues.push(issue3("path", "resource_filename_invalid", displayPath(root, join2(directory, entry.name)), "resource must be a regular file with the exact .yaml extension"));
17618
+ issues.push(issue3("path", "resource_filename_invalid", displayPath(root, join3(directory, entry.name)), "resource must be a regular file with the exact .yaml extension"));
17324
17619
  continue;
17325
17620
  }
17326
17621
  const id = basename(entry.name, ".yaml");
17327
17622
  if (kind === "model" && id === "inventory") continue;
17328
17623
  if (id === replacedId) continue;
17329
17624
  if (!resourceIdentifier(id)) {
17330
- issues.push(issue3("path", "resource_id_invalid", displayPath(root, join2(directory, entry.name)), `filename-derived identity ${id} is invalid or platform-reserved`));
17625
+ issues.push(issue3("path", "resource_id_invalid", displayPath(root, join3(directory, entry.name)), `filename-derived identity ${id} is invalid or platform-reserved`));
17331
17626
  continue;
17332
17627
  }
17333
17628
  const collision = [...resources.keys()].find((candidate) => candidate.toLocaleLowerCase("en-US") === id.toLocaleLowerCase("en-US"));
17334
17629
  if (collision) {
17335
- issues.push(issue3("path", "resource_id_collision", displayPath(root, join2(directory, entry.name)), `${id} case-folds to existing ${collision}`));
17630
+ issues.push(issue3("path", "resource_id_collision", displayPath(root, join3(directory, entry.name)), `${id} case-folds to existing ${collision}`));
17336
17631
  continue;
17337
17632
  }
17338
17633
  try {
17339
- const resource = readResource(registry, root, join2(directory, entry.name), `${logicalDirectory}/${id}.yaml`, kind, id);
17634
+ const resource = readResource(registry, root, join3(directory, entry.name), `${logicalDirectory}/${id}.yaml`, kind, id);
17340
17635
  resources.set(id, resource);
17341
17636
  } catch (error) {
17342
17637
  if (error instanceof KxmConfigError) issues.push(...error.issues);
@@ -17365,6 +17660,14 @@ function numberValue(value, fallback) {
17365
17660
  function names(value) {
17366
17661
  return Array.isArray(value) ? value.filter((candidate) => typeof candidate === "string") : [];
17367
17662
  }
17663
+ function lookupKxmResource(resources, requested, kind) {
17664
+ const records = [...resources].map((resource) => ({
17665
+ id: resource.id,
17666
+ aliases: names(resource.value.aliases),
17667
+ resource
17668
+ }));
17669
+ return lookupById(records, requested, kind)?.record.resource;
17670
+ }
17368
17671
  function mapResource(resource, map, issues) {
17369
17672
  const id = resource.id;
17370
17673
  if (!id) return;
@@ -17555,14 +17858,31 @@ function transition(value) {
17555
17858
  function validateWorkflow(workflow, agents, models, repositories, gates, issues) {
17556
17859
  const file = workflow.logicalPath;
17557
17860
  const coordinator = stringValue(workflow.value.coordinator) ?? "coordinator";
17558
- if (!agents.has(coordinator)) issues.push(issue3("reference", "coordinator_unknown", file, `coordinator ${coordinator} does not exist`));
17861
+ if (!lookupKxmResource(agents.values(), coordinator, "agent")) issues.push(issue3("reference", "coordinator_unknown", file, `coordinator ${coordinator} does not exist`));
17559
17862
  const steps = valuesOf(workflow.value, "steps").map((candidate) => objectValue(candidate)).filter((candidate) => Boolean(candidate));
17560
17863
  const stepIndex = /* @__PURE__ */ new Map();
17864
+ const primarySteps = /* @__PURE__ */ new Set();
17561
17865
  for (const [index, step] of steps.entries()) {
17562
17866
  const id = stringValue(step.id);
17563
17867
  if (!id) continue;
17564
17868
  if (stepIndex.has(id)) issues.push(issue3("semantic", "step_id_duplicate", file, `step ${id} is duplicated`));
17565
- else stepIndex.set(id, index);
17869
+ else {
17870
+ stepIndex.set(id, index);
17871
+ primarySteps.add(id);
17872
+ }
17873
+ }
17874
+ for (const [index, step] of steps.entries()) {
17875
+ const id = stringValue(step.id);
17876
+ if (!id) continue;
17877
+ const aliases = new Set(names(step.aliases));
17878
+ for (const [oldId, newId2] of STEP_RENAMES) {
17879
+ if (id === newId2) aliases.add(oldId);
17880
+ if (id === oldId) aliases.add(newId2);
17881
+ }
17882
+ for (const alias of aliases) {
17883
+ if (alias === id || primarySteps.has(alias) || stepIndex.has(alias)) continue;
17884
+ stepIndex.set(alias, index);
17885
+ }
17566
17886
  }
17567
17887
  for (const field of ["reproOracle", "planHash"]) {
17568
17888
  const oracle = objectValue(workflow.value[field]);
@@ -17591,7 +17911,7 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17591
17911
  const kind = stringValue(step.kind);
17592
17912
  validateToolPolicy(workflow, objectValue(step.tools), `${stepId}.tools`, issues);
17593
17913
  const primaryAgentId = stringValue(step.agent);
17594
- if ((kind === "agent" || kind === "moa") && primaryAgentId && !agents.has(primaryAgentId)) {
17914
+ if ((kind === "agent" || kind === "moa") && primaryAgentId && !lookupKxmResource(agents.values(), primaryAgentId, "agent")) {
17595
17915
  issues.push(issue3("reference", "agent_unknown", file, `${stepId} references unknown agent ${primaryAgentId}`));
17596
17916
  }
17597
17917
  const gate = stringValue(step.gate);
@@ -17618,7 +17938,7 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17618
17938
  const declaredAgents = assignment ? names(assignment.allowedAgents) : [];
17619
17939
  const allowedAgents = declaredAgents.length > 0 ? declaredAgents : primaryAgentId ? [primaryAgentId] : [];
17620
17940
  for (const agentId of allowedAgents) {
17621
- const agent = agents.get(agentId);
17941
+ const agent = lookupKxmResource(agents.values(), agentId, "agent");
17622
17942
  if (!agent) issues.push(issue3("reference", "assignment_agent_unknown", file, `${stepId} allows unknown agent ${agentId}`));
17623
17943
  else {
17624
17944
  validateAgentScope(agent, step, repositories, file, stepId, issues);
@@ -17649,8 +17969,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17649
17969
  const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
17650
17970
  if (maxWriteRepositories > writable) issues.push(issue3("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
17651
17971
  }
17652
- const join19 = objectValue(step.join);
17653
- const minimumPassed = join19 && typeof join19.minimumPassed === "number" ? join19.minimumPassed : void 0;
17972
+ const join20 = objectValue(step.join);
17973
+ const minimumPassed = join20 && typeof join20.minimumPassed === "number" ? join20.minimumPassed : void 0;
17654
17974
  if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue3("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
17655
17975
  const distinctBy = names(assignment?.distinctBy);
17656
17976
  if (distinctBy.length > 0) {
@@ -17675,7 +17995,7 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17675
17995
  const producerMinimum = numberValue(policy.minimumProducers, 1);
17676
17996
  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`));
17677
17997
  for (const agentId of eligible) {
17678
- if (!agents.has(agentId)) issues.push(issue3("reference", "producer_agent_unknown", file, `${stepId}.${String(key)} references unknown producer ${agentId}`));
17998
+ if (!lookupKxmResource(agents.values(), agentId, "agent")) issues.push(issue3("reference", "producer_agent_unknown", file, `${stepId}.${String(key)} references unknown producer ${agentId}`));
17679
17999
  if (allowedAgents.length > 0 && !allowedAgents.includes(agentId)) issues.push(issue3("semantic", "producer_agent_ineligible", file, `${stepId}.${String(key)} producer ${agentId} is outside allowedAgents`));
17680
18000
  }
17681
18001
  const degradation = objectValue(policy.degradation);
@@ -17696,6 +18016,10 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17696
18016
  if (parsed.terminalStatus === "completed") completedTerminalSources.add(index);
17697
18017
  continue;
17698
18018
  }
18019
+ if (parsed.target && parsed.target !== "$terminal" && !primarySteps.has(parsed.target) && stepIndex.has(parsed.target)) {
18020
+ const canonical = stringValue(steps[stepIndex.get(parsed.target) ?? -1]?.id);
18021
+ if (canonical) noteDeprecatedId("step", parsed.target, canonical);
18022
+ }
17699
18023
  const targetIndex = parsed.target === void 0 ? void 0 : stepIndex.get(parsed.target);
17700
18024
  if (targetIndex === void 0) {
17701
18025
  issues.push(issue3("reference", "transition_target_unknown", file, `${stepId}.${outcome} references unknown target ${String(parsed.target)}`));
@@ -17850,12 +18174,12 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
17850
18174
  }
17851
18175
  validateModelReferences(models, issues);
17852
18176
  const defaultWorkflow = stringValue(project.value.defaultWorkflow) ?? "default";
17853
- if (!workflows.has(defaultWorkflow)) issues.push(issue3("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
18177
+ if (!lookupKxmResource(workflows.values(), defaultWorkflow, "workflow")) issues.push(issue3("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
17854
18178
  for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
17855
- if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roster.yaml"))) {
18179
+ if (projectRoot && existsSync4(join3(projectRoot, ".kxm", "roster.yaml"))) {
17856
18180
  issues.push(issue3("semantic", "retired_roster_file", ".kxm/roster.yaml", "create the role and model files and delete roster.yaml"));
17857
18181
  }
17858
- if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roles"))) {
18182
+ if (projectRoot && existsSync4(join3(projectRoot, ".kxm", "roles"))) {
17859
18183
  issues.push(...developerRolePolicyIssues(projectRoot));
17860
18184
  }
17861
18185
  if (projectRoot) {
@@ -17870,11 +18194,12 @@ function rosterModelIssues(projectRoot, roles) {
17870
18194
  for (const entry of valuesOf(role.value, "roster")) {
17871
18195
  const route = stringValue(objectValue(entry)?.route);
17872
18196
  if (!route) continue;
17873
- const logical = `.kxm/models/${route}.yaml`;
17874
- const file = join2(projectRoot, ".kxm", "models", `${route}.yaml`);
18197
+ const resolved = findYamlBasename(join3(projectRoot, ".kxm", "models"), route, "route") ?? route;
18198
+ const logical = `.kxm/models/${resolved}.yaml`;
18199
+ const file = join3(projectRoot, ".kxm", "models", `${resolved}.yaml`);
17875
18200
  let harness;
17876
18201
  try {
17877
- if (existsSync3(file)) harness = stringValue(parseRestrictedYaml2(readFileSync(file, "utf8"), logical).harness);
18202
+ if (existsSync4(file)) harness = stringValue(parseRestrictedYaml2(readFileSync2(file, "utf8"), logical).harness);
17878
18203
  } catch {
17879
18204
  harness = void 0;
17880
18205
  }
@@ -17900,7 +18225,7 @@ function originHashIssues(projectRoot, models) {
17900
18225
  }
17901
18226
  let actual;
17902
18227
  try {
17903
- actual = createHash3("sha256").update(readFileSync(file, "utf8"), "utf8").digest("hex");
18228
+ actual = createHash3("sha256").update(readFileSync2(file, "utf8"), "utf8").digest("hex");
17904
18229
  } catch (error) {
17905
18230
  const code = error.code;
17906
18231
  if (code === "ENOENT" || code === "EACCES" || code === "EPERM" || code === "EISDIR") {
@@ -17916,7 +18241,7 @@ function originHashIssues(projectRoot, models) {
17916
18241
  return issues;
17917
18242
  }
17918
18243
  function developerCeilings() {
17919
- const script = join2(findKxmRepoRoot(import.meta.url), "scripts", "harness-run.mjs");
18244
+ const script = join3(findKxmRepoRoot(import.meta.url), "scripts", "harness-run.mjs");
17920
18245
  let loaded;
17921
18246
  try {
17922
18247
  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}))`], {
@@ -17943,20 +18268,21 @@ function developerCeilings() {
17943
18268
  }
17944
18269
  function developerRolePolicyIssues(projectRoot) {
17945
18270
  if (resolve(projectRoot) !== findKxmRepoRoot(import.meta.url)) return [];
17946
- const rolesDir = join2(projectRoot, ".kxm", "roles");
17947
- const modelsDir = join2(projectRoot, ".kxm", "models");
18271
+ const lintIssues = lintWorkforce(projectRoot).errors.map((entry) => issue3("semantic", entry.code, entry.file, entry.message));
18272
+ const rolesDir = join3(projectRoot, ".kxm", "roles");
18273
+ const modelsDir = join3(projectRoot, ".kxm", "models");
17948
18274
  const roles = {};
17949
18275
  const models = {};
17950
18276
  const evidence = {};
17951
18277
  const parseIssues = [];
17952
18278
  const readMap = (dir, into, skipInventory) => {
17953
- if (!existsSync3(dir)) return;
17954
- for (const name of readdirSync(dir)) {
18279
+ if (!existsSync4(dir)) return;
18280
+ for (const name of readdirSync2(dir)) {
17955
18281
  if (!name.endsWith(".yaml")) continue;
17956
18282
  const id = basename(name, ".yaml");
17957
18283
  if (skipInventory && id === "inventory") continue;
17958
18284
  try {
17959
- const value = parseRestrictedYaml2(readFileSync(join2(dir, name), "utf8"), `${dir}/${name}`);
18285
+ const value = parseRestrictedYaml2(readFileSync2(join3(dir, name), "utf8"), `${dir}/${name}`);
17960
18286
  into[id] = value;
17961
18287
  } catch (error) {
17962
18288
  if (error instanceof KxmConfigError) {
@@ -17973,12 +18299,12 @@ function developerRolePolicyIssues(projectRoot) {
17973
18299
  const origin = objectValue(model.origin);
17974
18300
  const source = origin ? stringValue(origin.source) : void 0;
17975
18301
  if (!source || evidence[source] !== void 0) continue;
17976
- const evidenceFile = isAbsolute(source) ? source : join2(projectRoot, source);
17977
- if (existsSync3(evidenceFile)) evidence[source] = readFileSync(evidenceFile, "utf8");
18302
+ const evidenceFile = isAbsolute(source) ? source : join3(projectRoot, source);
18303
+ if (existsSync4(evidenceFile)) evidence[source] = readFileSync2(evidenceFile, "utf8");
17978
18304
  }
17979
18305
  const ceilings = developerCeilings();
17980
18306
  if (!ceilings.ok) {
17981
- return [...parseIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/models", `developer ceilings could not be loaded: ${ceilings.detail}`)];
18307
+ return [...parseIssues, ...lintIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/models", `developer ceilings could not be loaded: ${ceilings.detail}`)];
17982
18308
  }
17983
18309
  const result = validatePolicyDraft({ models, roles, evidence }, {
17984
18310
  ceilings: ceilings.ROUTES,
@@ -17987,8 +18313,8 @@ function developerRolePolicyIssues(projectRoot) {
17987
18313
  piNativeVendorProviders: ceilings.PI_NATIVE_VENDOR_PROVIDERS,
17988
18314
  vendorAliases: { "x-ai": "xai", moonshotai: "moonshot", "google-ai": "google", qwen: "alibaba" }
17989
18315
  });
17990
- if (result.ok) return parseIssues;
17991
- return [...parseIssues, ...result.issues.map((entry) => issue3(entry.phase, entry.code, entry.file, entry.message))];
18316
+ if (result.ok) return [...parseIssues, ...lintIssues];
18317
+ return [...parseIssues, ...lintIssues, ...result.issues.map((entry) => issue3(entry.phase, entry.code, entry.file, entry.message))];
17992
18318
  }
17993
18319
  function kxmCanonicalJson(value) {
17994
18320
  if (value === null || typeof value !== "object") return JSON.stringify(value);
@@ -18013,7 +18339,7 @@ function gitEnvironment() {
18013
18339
  }
18014
18340
  function discoverGitRoot(start = process.cwd()) {
18015
18341
  let current = resolve(start);
18016
- if (existsSync3(current) && !lstatSync(current).isDirectory()) current = dirname2(current);
18342
+ if (existsSync4(current) && !lstatSync(current).isDirectory()) current = dirname2(current);
18017
18343
  const result = spawnSync2("git", ["-C", current, "rev-parse", "--show-toplevel"], {
18018
18344
  encoding: "utf8",
18019
18345
  env: gitEnvironment(),
@@ -18022,7 +18348,7 @@ function discoverGitRoot(start = process.cwd()) {
18022
18348
  });
18023
18349
  if (result.status !== 0 || result.error || !result.stdout.trim()) return void 0;
18024
18350
  const root = resolve(result.stdout.trim());
18025
- return existsSync3(root) && lstatSync(root).isDirectory() ? root : void 0;
18351
+ return existsSync4(root) && lstatSync(root).isDirectory() ? root : void 0;
18026
18352
  }
18027
18353
  function assertNoRegisteredGates(options) {
18028
18354
  if ("registeredGates" in options) {
@@ -18047,7 +18373,7 @@ function loadProjectBundle(projectRoot, options, candidate) {
18047
18373
  )));
18048
18374
  }
18049
18375
  const registry = new KxmSchemaRegistry(options.schemasDir);
18050
- const project = readResource(registry, root, join2(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
18376
+ const project = readResource(registry, root, join3(root, ".kxm", "project.yaml"), ".kxm/project.yaml", "project");
18051
18377
  const earlyIssues = [];
18052
18378
  validatePortablePaths(project, earlyIssues);
18053
18379
  const templateProvenance = readTemplateProvenance(registry, root);
@@ -18066,30 +18392,30 @@ function loadProjectBundle(projectRoot, options, candidate) {
18066
18392
  }
18067
18393
  }
18068
18394
  if (earlyIssues.length > 0) throw new KxmConfigError(earlyIssues);
18069
- const agents = listNamedResources(registry, root, join2(root, ".kxm", "agents"), ".kxm/agents", "agent");
18395
+ const agents = listNamedResources(registry, root, join3(root, ".kxm", "agents"), ".kxm/agents", "agent");
18070
18396
  const modelIssues = [];
18071
- const models = listNamedResources(registry, root, join2(root, ".kxm", "models"), ".kxm/models", "model", void 0, modelIssues);
18072
- const roles = listNamedResources(registry, root, join2(root, ".kxm", "roles"), ".kxm/roles", "role", writerRole === void 0 ? void 0 : "writer");
18397
+ const models = listNamedResources(registry, root, join3(root, ".kxm", "models"), ".kxm/models", "model", void 0, modelIssues);
18398
+ const roles = listNamedResources(registry, root, join3(root, ".kxm", "roles"), ".kxm/roles", "role", writerRole === void 0 ? void 0 : "writer");
18073
18399
  if (writerRole !== void 0) {
18074
18400
  const logicalPath = ".kxm/roles/writer.yaml";
18075
- roles.set("writer", { kind: "role", id: "writer", file: join2(root, logicalPath), logicalPath, value: resourceValue(registry, writerRole, logicalPath, "role") });
18401
+ roles.set("writer", { kind: "role", id: "writer", file: join3(root, logicalPath), logicalPath, value: resourceValue(registry, writerRole, logicalPath, "role") });
18076
18402
  }
18077
- const workflows = listNamedResources(registry, root, join2(root, ".kxm", "workflows"), ".kxm/workflows", "workflow", workflowCandidate?.id);
18403
+ const workflows = listNamedResources(registry, root, join3(root, ".kxm", "workflows"), ".kxm/workflows", "workflow", workflowCandidate?.id);
18078
18404
  if (workflowCandidate) {
18079
18405
  const { id, document } = workflowCandidate;
18080
18406
  const logicalPath = `.kxm/workflows/${id}.yaml`;
18081
18407
  if (!resourceIdentifier(id)) fail2("path", "resource_id_invalid", logicalPath, `filename-derived identity ${id} is invalid or platform-reserved`);
18082
18408
  const collision = [...workflows.keys()].find((candidate2) => candidate2.toLocaleLowerCase("en-US") === id.toLocaleLowerCase("en-US"));
18083
18409
  if (collision) fail2("path", "resource_id_collision", logicalPath, `${id} case-folds to existing ${collision}`);
18084
- workflows.set(id, { kind: "workflow", id, file: join2(root, logicalPath), logicalPath, value: resourceValue(registry, document, logicalPath, "workflow") });
18410
+ workflows.set(id, { kind: "workflow", id, file: join3(root, logicalPath), logicalPath, value: resourceValue(registry, document, logicalPath, "workflow") });
18085
18411
  }
18086
- const gatePath = join2(root, ".kxm", "gates.yaml");
18087
- const gateRegistry = existsSync3(gatePath) ? readResource(registry, root, gatePath, ".kxm/gates.yaml", "gate-registry") : void 0;
18412
+ const gatePath = join3(root, ".kxm", "gates.yaml");
18413
+ const gateRegistry = existsSync4(gatePath) ? readResource(registry, root, gatePath, ".kxm/gates.yaml", "gate-registry") : void 0;
18088
18414
  const environments = [];
18089
18415
  const repositories = /* @__PURE__ */ new Map();
18090
18416
  const loadIssues = [];
18091
- const projectEnvironment = join2(root, ".kxm", "project", "env.yaml");
18092
- if (existsSync3(projectEnvironment)) {
18417
+ const projectEnvironment = join3(root, ".kxm", "project", "env.yaml");
18418
+ if (existsSync4(projectEnvironment)) {
18093
18419
  try {
18094
18420
  environments.push(readResource(registry, root, projectEnvironment, ".kxm/project/env.yaml", "environment"));
18095
18421
  } catch (error) {
@@ -18131,7 +18457,7 @@ function loadProjectBundle(projectRoot, options, candidate) {
18131
18457
  if (required2) loadIssues.push(issue3("discovery", "repository_binding_missing", ".kxm/project.yaml", `required repository ${repositoryId} has no portable pathHint or host-local binding`));
18132
18458
  continue;
18133
18459
  }
18134
- if (!existsSync3(binding)) {
18460
+ if (!existsSync4(binding)) {
18135
18461
  if (required2 || hasLocalBinding) loadIssues.push(issue3("discovery", "repository_binding_unavailable", ".kxm/project.yaml", `${hasLocalBinding ? "explicit" : "required"} repository binding ${repositoryId} is unavailable`));
18136
18462
  continue;
18137
18463
  }
@@ -18163,9 +18489,9 @@ function loadProjectBundle(projectRoot, options, candidate) {
18163
18489
  continue;
18164
18490
  }
18165
18491
  seenBindings.set(foldedBinding, repositoryId);
18166
- const repositoryFile = join2(binding, ".kxm", "repo", "repo.yaml");
18492
+ const repositoryFile = join3(binding, ".kxm", "repo", "repo.yaml");
18167
18493
  let definitionValidated = false;
18168
- if (existsSync3(repositoryFile)) {
18494
+ if (existsSync4(repositoryFile)) {
18169
18495
  try {
18170
18496
  const resource = readResource(registry, root, repositoryFile, `.kxm/repositories/${repositoryId}/repo.yaml`, "repository", repositoryId, binding);
18171
18497
  if (resource.value.repositoryId !== repositoryId) {
@@ -18181,8 +18507,8 @@ function loadProjectBundle(projectRoot, options, candidate) {
18181
18507
  } else if (required2 || hasLocalBinding) {
18182
18508
  loadIssues.push(issue3("discovery", "repository_definition_missing", `.kxm/repositories/${repositoryId}/repo.yaml`, `${hasLocalBinding ? "explicit" : "required"} repository ${repositoryId} has no repo.yaml`));
18183
18509
  }
18184
- const environmentFile = join2(binding, ".kxm", "repo", "env.yaml");
18185
- if (existsSync3(environmentFile)) {
18510
+ const environmentFile = join3(binding, ".kxm", "repo", "env.yaml");
18511
+ if (existsSync4(environmentFile)) {
18186
18512
  if (!definitionValidated) {
18187
18513
  loadIssues.push(issue3("reference", "repository_environment_without_definition", `.kxm/repositories/${repositoryId}/env.yaml`, `repository ${repositoryId} environment requires a validated matching repo.yaml`));
18188
18514
  } else {
@@ -18218,21 +18544,21 @@ var LEGACY_CONFIG_FILES = [".kxm/config/agents.json", ".kxm/config/gates.json"];
18218
18544
  function legacyConfigFilesAt(root) {
18219
18545
  const files = [];
18220
18546
  for (const component of [".kxm", ".kxm/config"]) {
18221
- const absolute = join2(root, ...component.split("/"));
18222
- if (existsSync3(absolute) && lstatSync(absolute).isSymbolicLink()) return [component];
18547
+ const absolute = join3(root, ...component.split("/"));
18548
+ if (existsSync4(absolute) && lstatSync(absolute).isSymbolicLink()) return [component];
18223
18549
  }
18224
18550
  for (const candidate of LEGACY_CONFIG_FILES) {
18225
- if (existsSync3(join2(root, ...candidate.split("/")))) files.push(candidate);
18551
+ if (existsSync4(join3(root, ...candidate.split("/")))) files.push(candidate);
18226
18552
  }
18227
- const workflowsDir = join2(root, ".kxm", "config", "workflows");
18228
- if (existsSync3(workflowsDir)) {
18553
+ const workflowsDir = join3(root, ".kxm", "config", "workflows");
18554
+ if (existsSync4(workflowsDir)) {
18229
18555
  const stat = lstatSync(workflowsDir);
18230
18556
  if (stat.isSymbolicLink()) {
18231
18557
  files.push(".kxm/config/workflows");
18232
18558
  return files;
18233
18559
  }
18234
18560
  if (stat.isDirectory()) {
18235
- 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))) {
18561
+ 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))) {
18236
18562
  files.push(`.kxm/config/workflows/${entry.name}`);
18237
18563
  }
18238
18564
  }
@@ -18243,11 +18569,11 @@ function legacyConfigFilesAt(root) {
18243
18569
  // plugins/kxm/src/runtime-store.ts
18244
18570
  import { spawnSync as spawnSync3 } from "node:child_process";
18245
18571
  import { createHash as createHash6, randomUUID } from "node:crypto";
18246
- import { existsSync as existsSync6, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, realpathSync as realpathSync3, statSync, writeFileSync as writeFileSync2 } from "node:fs";
18572
+ import { existsSync as existsSync7, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, realpathSync as realpathSync3, statSync, writeFileSync as writeFileSync2 } from "node:fs";
18247
18573
  import { dirname as dirname5, isAbsolute as isAbsolute4, resolve as resolve6 } from "node:path";
18248
18574
 
18249
18575
  // plugins/kxm/src/sqlite.ts
18250
- import { existsSync as existsSync4 } from "node:fs";
18576
+ import { existsSync as existsSync5 } from "node:fs";
18251
18577
  import { createRequire } from "node:module";
18252
18578
  import { resolve as resolve2 } from "node:path";
18253
18579
  import { pathToFileURL as pathToFileURL2 } from "node:url";
@@ -18288,7 +18614,7 @@ var DatabaseSync = class {
18288
18614
  }
18289
18615
  };
18290
18616
  function openReadOnlyDatabase(path) {
18291
- if (existsSync4(`${path}-wal`)) return new DatabaseSync(path, { readOnly: true });
18617
+ if (existsSync5(`${path}-wal`)) return new DatabaseSync(path, { readOnly: true });
18292
18618
  const uri = pathToFileURL2(resolve2(path));
18293
18619
  uri.searchParams.set("immutable", "1");
18294
18620
  return new DatabaseSync(uri.href, { readOnly: true });
@@ -18297,11 +18623,11 @@ function openReadOnlyDatabase(path) {
18297
18623
  // plugins/kxm/src/runtime-paths.ts
18298
18624
  import { createHash as createHash4 } from "node:crypto";
18299
18625
  import { realpathSync as realpathSync2 } from "node:fs";
18300
- import { join as join4, resolve as resolve4 } from "node:path";
18626
+ import { join as join5, resolve as resolve4 } from "node:path";
18301
18627
 
18302
18628
  // plugins/kxm/src/bindings.ts
18303
18629
  import { homedir } from "node:os";
18304
- import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, parse, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
18630
+ import { dirname as dirname3, isAbsolute as isAbsolute2, join as join4, parse, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
18305
18631
  var MAX_BINDING_RECORD_BYTES = 256 * 1024;
18306
18632
  var BINDING_LABEL = "Runtime-local repository bindings";
18307
18633
  function bindingIssue(phase, code, message) {
@@ -18321,24 +18647,24 @@ function kxmUserStateRoot(options = {}) {
18321
18647
  }
18322
18648
  if (platform === "win32") {
18323
18649
  const localAppData = env.LOCALAPPDATA?.trim();
18324
- const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join3(home, "AppData", "Local");
18650
+ const base2 = localAppData && isAbsolute2(localAppData) ? localAppData : join4(home, "AppData", "Local");
18325
18651
  return resolve3(base2, "KXM");
18326
18652
  }
18327
18653
  if (platform === "darwin") return resolve3(home, "Library", "Application Support", "KXM");
18328
18654
  const xdgState = env.XDG_STATE_HOME?.trim();
18329
- const base = xdgState && isAbsolute2(xdgState) ? xdgState : join3(home, ".local", "state");
18655
+ const base = xdgState && isAbsolute2(xdgState) ? xdgState : join4(home, ".local", "state");
18330
18656
  return resolve3(base, "kxm");
18331
18657
  }
18332
18658
 
18333
18659
  // plugins/kxm/src/runtime-paths.ts
18334
18660
  function kxmRuntimePaths(options = {}) {
18335
18661
  const stateRoot = options.stateRoot ? resolve4(options.stateRoot) : kxmUserStateRoot({ ...options.env ? { env: options.env } : {}, ...options.homeDir ? { homeDir: options.homeDir } : {} });
18336
- const runtimeDir = join4(stateRoot, "runtime");
18662
+ const runtimeDir = join5(stateRoot, "runtime");
18337
18663
  return {
18338
18664
  stateRoot,
18339
18665
  runtimeDir,
18340
- registryDb: join4(runtimeDir, "registry.db"),
18341
- projectsDir: join4(runtimeDir, "projects")
18666
+ registryDb: join5(runtimeDir, "registry.db"),
18667
+ projectsDir: join5(runtimeDir, "projects")
18342
18668
  };
18343
18669
  }
18344
18670
  function projectRuntimeKey(projectRoot) {
@@ -18687,22 +19013,22 @@ function kxmSyncEventBytes(event) {
18687
19013
  import {
18688
19014
  chmodSync,
18689
19015
  copyFileSync,
18690
- existsSync as existsSync5,
19016
+ existsSync as existsSync6,
18691
19017
  lstatSync as lstatSync2,
18692
19018
  mkdirSync,
18693
- readdirSync as readdirSync2,
18694
- readFileSync as readFileSync2,
19019
+ readdirSync as readdirSync3,
19020
+ readFileSync as readFileSync3,
18695
19021
  unlinkSync,
18696
19022
  writeFileSync
18697
19023
  } from "node:fs";
18698
- 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";
19024
+ 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";
18699
19025
  function databaseError(code, file, message) {
18700
19026
  const issue4 = { phase: "semantic", code, file, message };
18701
19027
  return new KxmConfigError([issue4]);
18702
19028
  }
18703
19029
  function checkedParent(path, description) {
18704
19030
  const parent = dirname4(path);
18705
- if (!existsSync5(parent)) mkdirSync(parent, { recursive: true, mode: 448 });
19031
+ if (!existsSync6(parent)) mkdirSync(parent, { recursive: true, mode: 448 });
18706
19032
  const stat = lstatSync2(parent, { throwIfNoEntry: false });
18707
19033
  if (!stat || stat.isSymbolicLink() || !stat.isDirectory()) {
18708
19034
  throw databaseError("runtime_path_invalid", description, `${description} parent must be a regular directory, not a link`);
@@ -19772,9 +20098,9 @@ var KxmRunEventStore = class {
19772
20098
  }
19773
20099
  readRunPrompts() {
19774
20100
  const sidecar = this.runPromptSidecarPath();
19775
- if (!existsSync6(sidecar)) return {};
20101
+ if (!existsSync7(sidecar)) return {};
19776
20102
  try {
19777
- const parsed = JSON.parse(readFileSync3(sidecar, "utf8"));
20103
+ const parsed = JSON.parse(readFileSync4(sidecar, "utf8"));
19778
20104
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
19779
20105
  return Object.fromEntries(
19780
20106
  Object.entries(parsed).filter((entry) => typeof entry[1] === "string")
@@ -20861,8 +21187,8 @@ function capabilityFromRow(row) {
20861
21187
 
20862
21188
  // plugins/kxm/src/runtime-service.ts
20863
21189
  import { createHash as createHash8 } from "node:crypto";
20864
- import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync4 } from "node:fs";
20865
- import { join as join7 } from "node:path";
21190
+ import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
21191
+ import { join as join8 } from "node:path";
20866
21192
 
20867
21193
  // plugins/kxm/src/engine-fold.ts
20868
21194
  var KXM_RUN_STATE_SCHEMA = "kxm.run-state.v2";
@@ -22223,7 +22549,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
22223
22549
  const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
22224
22550
  const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
22225
22551
  const assignments = compileAssignments(step, id, agent, sink);
22226
- const join19 = compileJoin(step, id, sink);
22552
+ const join20 = compileJoin(step, id, sink);
22227
22553
  const requiredEvidence = compileEvidence(step, id, sink);
22228
22554
  const transitions = compileTransitions(step, id, index, stepIndex, sink);
22229
22555
  const outcomes = Object.keys(transitions).sort(compareCodeUnits5);
@@ -22251,7 +22577,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
22251
22577
  transitions: orderedTransitions,
22252
22578
  requiresPlanHash: requirePlanHash.includes(id),
22253
22579
  assignments,
22254
- join: join19
22580
+ join: join20
22255
22581
  };
22256
22582
  if (kind === "agent" || kind === "moa") {
22257
22583
  if (!agent) return void 0;
@@ -22301,15 +22627,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
22301
22627
  };
22302
22628
  }
22303
22629
  function compileJoin(step, stepId, sink) {
22304
- const join19 = objectValue2(step.join);
22305
- if (!join19) return { strategy: "all" };
22306
- const declared = stringValue2(join19.strategy);
22630
+ const join20 = objectValue2(step.join);
22631
+ if (!join20) return { strategy: "all" };
22632
+ const declared = stringValue2(join20.strategy);
22307
22633
  const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
22308
- const minimumPassed = compileOptionalCount(join19.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
22634
+ const minimumPassed = compileOptionalCount(join20.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
22309
22635
  const compiled = {
22310
22636
  strategy,
22311
22637
  ...minimumPassed !== void 0 ? { minimumPassed } : {},
22312
- ...typeof join19.cancelRemaining === "boolean" ? { cancelRemaining: join19.cancelRemaining } : {}
22638
+ ...typeof join20.cancelRemaining === "boolean" ? { cancelRemaining: join20.cancelRemaining } : {}
22313
22639
  };
22314
22640
  return compiled;
22315
22641
  }
@@ -23728,11 +24054,11 @@ function kxmToolPolicyRevision(bundle) {
23728
24054
  return sha256Of(kxmCanonicalJson({ policies, gateRegistry: bundle.gateRegistry?.value ?? null }));
23729
24055
  }
23730
24056
  function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Set()) {
23731
- if (!existsSync7(dir)) return [];
23732
- const entries = readdirSync3(dir, { withFileTypes: true });
24057
+ if (!existsSync8(dir)) return [];
24058
+ const entries = readdirSync4(dir, { withFileTypes: true });
23733
24059
  const results = [];
23734
24060
  for (const entry of entries) {
23735
- const fullPath = join7(dir, entry.name);
24061
+ const fullPath = join8(dir, entry.name);
23736
24062
  if (entry.isDirectory()) {
23737
24063
  if (ignoreSubdirs.has(entry.name)) continue;
23738
24064
  results.push(...collectMemoryFiles(fullPath, baseDir, ignoreSubdirs));
@@ -23745,19 +24071,19 @@ function collectMemoryFiles(dir, baseDir, ignoreSubdirs = /* @__PURE__ */ new Se
23745
24071
  }
23746
24072
  function computeKxmMemoryRevision(bundle, options = {}) {
23747
24073
  const hash = createHash8("sha256");
23748
- const memoryDir = options.memoryDir ?? join7(bundle.projectRoot, ".kxm", "memory");
24074
+ const memoryDir = options.memoryDir ?? join8(bundle.projectRoot, ".kxm", "memory");
23749
24075
  const memoryFiles = collectMemoryFiles(memoryDir, memoryDir, /* @__PURE__ */ new Set(["candidates"])).sort((left, right) => compareCodeUnits6(left.relPath, right.relPath));
23750
24076
  for (const file of memoryFiles) {
23751
24077
  hash.update(`memory:${file.relPath}\0`, "utf8");
23752
- hash.update(readFileSync4(file.fullPath));
24078
+ hash.update(readFileSync5(file.fullPath));
23753
24079
  hash.update("\0", "utf8");
23754
24080
  }
23755
- const skillsDir = options.skillsDir ?? join7(bundle.projectRoot, ".kxm", "skills");
23756
- const promotedSkillsDir = join7(skillsDir, "promoted");
24081
+ const skillsDir = options.skillsDir ?? join8(bundle.projectRoot, ".kxm", "skills");
24082
+ const promotedSkillsDir = join8(skillsDir, "promoted");
23757
24083
  const skillFiles = collectMemoryFiles(promotedSkillsDir, promotedSkillsDir).sort((left, right) => compareCodeUnits6(left.relPath, right.relPath));
23758
24084
  for (const file of skillFiles) {
23759
24085
  hash.update(`skill:${file.relPath}\0`, "utf8");
23760
- hash.update(readFileSync4(file.fullPath));
24086
+ hash.update(readFileSync5(file.fullPath));
23761
24087
  hash.update("\0", "utf8");
23762
24088
  }
23763
24089
  if (options.promotedState && options.promotedState.length > 0) {
@@ -23835,7 +24161,7 @@ function openKxmRuntimeContext(projectRoot, options) {
23835
24161
  now: options.now ?? (/* @__PURE__ */ new Date()).toISOString(),
23836
24162
  ...options.logger ? { logger: options.logger } : {}
23837
24163
  });
23838
- const eventStore = new KxmRunEventStore(join7(paths.projectsDir, registration.projectKey, "run-events.db"));
24164
+ const eventStore = new KxmRunEventStore(join8(paths.projectsDir, registration.projectKey, "run-events.db"));
23839
24165
  registerKxmRuntimeHandle(eventStore.path);
23840
24166
  return {
23841
24167
  registry,
@@ -23896,7 +24222,7 @@ function acceptKxmRun(context, bundle, request, options = {}) {
23896
24222
  const commandId = request.commandId ?? newKxmCommandId();
23897
24223
  const now = options.now ?? (/* @__PURE__ */ new Date()).toISOString();
23898
24224
  const monotonicNs = options.monotonicNs ?? kxmMonotonicNs();
23899
- const workflow = bundle.workflows.get(request.workflowId);
24225
+ const workflow = lookupKxmResource(bundle.workflows.values(), request.workflowId, "workflow");
23900
24226
  if (!workflow) {
23901
24227
  throw runtimeError("run_workflow_unknown", ".kxm/workflows", `workflow ${request.workflowId} does not exist in this project`);
23902
24228
  }
@@ -24065,7 +24391,7 @@ function cancelKxmRun(context, runId, options = {}) {
24065
24391
  const events = [];
24066
24392
  let sequence = context.eventStore.nextSequence(runId);
24067
24393
  let nextMono = monotonicNs;
24068
- const push = (eventType, payload) => {
24394
+ const push2 = (eventType, payload) => {
24069
24395
  const event = {
24070
24396
  ...kxmEventBase(context, run, now, nextMono, commandId),
24071
24397
  eventId: newKxmEventId(),
@@ -24089,11 +24415,11 @@ function cancelKxmRun(context, runId, options = {}) {
24089
24415
  }
24090
24416
  cancelPayload.budget = options.budget;
24091
24417
  }
24092
- push("run.cancel_requested", cancelPayload);
24418
+ push2("run.cancel_requested", cancelPayload);
24093
24419
  let status = "cancelled";
24094
24420
  if (folded.status === "running" && activeAttempt) {
24095
24421
  status = "cancelling";
24096
- push("run.status_changed", { status: "cancelling", reason: cancelReason });
24422
+ push2("run.status_changed", { status: "cancelling", reason: cancelReason });
24097
24423
  const attemptIds = new Set(kxmFoldPanelAttemptIds(folded.currentStep));
24098
24424
  if (folded.currentStep?.attemptId) attemptIds.add(folded.currentStep.attemptId);
24099
24425
  for (const attemptId of attemptIds) {
@@ -24106,7 +24432,7 @@ function cancelKxmRun(context, runId, options = {}) {
24106
24432
  abortControllers.push(owned.controller);
24107
24433
  }
24108
24434
  } else if (folded.status === "blocked_uncertain") {
24109
- push("run.status_changed", { status: "cancelling", reason: cancelReason });
24435
+ push2("run.status_changed", { status: "cancelling", reason: cancelReason });
24110
24436
  const attemptId = folded.currentStep?.attemptId;
24111
24437
  if (attemptId) {
24112
24438
  const capability = context.eventStore.capabilityByAttempt(attemptId);
@@ -24118,13 +24444,13 @@ function cancelKxmRun(context, runId, options = {}) {
24118
24444
  for (const owned of kxmAttemptControllers(context.eventStore.path, runId)) {
24119
24445
  abortControllers.push(owned.controller);
24120
24446
  }
24121
- push("run.status_changed", { status: "cancelled", reason: cancelReason });
24447
+ push2("run.status_changed", { status: "cancelled", reason: cancelReason });
24122
24448
  status = "cancelled";
24123
24449
  } else if (folded.status === "running" && !activeAttempt) {
24124
- push("run.status_changed", { status: "cancelling", reason: cancelReason });
24125
- push("run.status_changed", { status: "cancelled", reason: cancelReason });
24450
+ push2("run.status_changed", { status: "cancelling", reason: cancelReason });
24451
+ push2("run.status_changed", { status: "cancelled", reason: cancelReason });
24126
24452
  } else {
24127
- push("run.status_changed", { status: "cancelled", reason: cancelReason });
24453
+ push2("run.status_changed", { status: "cancelled", reason: cancelReason });
24128
24454
  }
24129
24455
  for (const event of events) context.eventStore.appendEvent(event);
24130
24456
  const nextState = foldStoredKxmRun(context, run);
@@ -24145,9 +24471,9 @@ function cancelKxmRun(context, runId, options = {}) {
24145
24471
 
24146
24472
  // plugins/kxm/src/oneshot-evidence.ts
24147
24473
  import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
24148
- import { lstatSync as lstatSync4, readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
24474
+ import { lstatSync as lstatSync4, readdirSync as readdirSync5, readFileSync as readFileSync6 } from "node:fs";
24149
24475
  import { lstat, mkdir, open, rename } from "node:fs/promises";
24150
- import { join as join8 } from "node:path";
24476
+ import { join as join9 } from "node:path";
24151
24477
  var ONESHOT_EVIDENCE_SCHEMA = "kxm.oneshot-evidence.v2";
24152
24478
  var RETIRED_ONESHOT_EVIDENCE_SCHEMAS = /* @__PURE__ */ new Set(["kxm.oneshot-evidence.v1"]);
24153
24479
  var TEXT_LIMIT = 4 * 1024 * 1024;
@@ -24171,12 +24497,12 @@ function parseOneShotEvidenceRecord(bytes) {
24171
24497
  return parsed;
24172
24498
  }
24173
24499
  function oneShotEvidenceRoot() {
24174
- return join8(kxmUserStateRoot(), "runtime", "oneshot-evidence");
24500
+ return join9(kxmUserStateRoot(), "runtime", "oneshot-evidence");
24175
24501
  }
24176
24502
  function readOneShotObservedChildExit(runId, attemptId, root = oneShotEvidenceRoot()) {
24177
24503
  let names3;
24178
24504
  try {
24179
- names3 = readdirSync4(root);
24505
+ names3 = readdirSync5(root);
24180
24506
  } catch {
24181
24507
  return void 0;
24182
24508
  }
@@ -24185,13 +24511,13 @@ function readOneShotObservedChildExit(runId, attemptId, root = oneShotEvidenceRo
24185
24511
  const capped = names3.slice(0, 4096);
24186
24512
  for (const name of capped) {
24187
24513
  if (!name.startsWith("evd_")) continue;
24188
- const dir = join8(root, name);
24514
+ const dir = join9(root, name);
24189
24515
  try {
24190
24516
  const info = lstatSync4(dir);
24191
24517
  if (!info.isDirectory() || info.isSymbolicLink()) continue;
24192
- const intent = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "intent.json"), "utf8"));
24518
+ const intent = parseOneShotEvidenceRecord(readFileSync6(join9(dir, "intent.json"), "utf8"));
24193
24519
  if (intent.runId !== runId || intent.attemptId !== attemptId) continue;
24194
- const result = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "result.json"), "utf8"));
24520
+ const result = parseOneShotEvidenceRecord(readFileSync6(join9(dir, "result.json"), "utf8"));
24195
24521
  if (result.observedChildExit === true) seenTrue = true;
24196
24522
  else if (result.observedChildExit === false) seenFalse = true;
24197
24523
  } catch {
@@ -24208,7 +24534,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
24208
24534
  throw new Error("oneshot_evidence_root_not_private");
24209
24535
  }
24210
24536
  const id = `evd_${randomUUID3().replaceAll("-", "")}`;
24211
- const dir = join8(root, id);
24537
+ const dir = join9(root, id);
24212
24538
  await mkdir(dir, { mode: 448 });
24213
24539
  const secrets = [...new Set(sensitive.filter((value) => value.length >= 8))].sort((a, b) => b.length - a.length);
24214
24540
  const redact = (value) => {
@@ -24228,7 +24554,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
24228
24554
  const bytes = JSON.stringify(value);
24229
24555
  if (Buffer.byteLength(bytes) > RECORD_LIMIT) throw new Error("oneshot_evidence_record_limit");
24230
24556
  parseOneShotEvidenceRecord(bytes);
24231
- const target = join8(dir, name);
24557
+ const target = join9(dir, name);
24232
24558
  const partial = `${target}.partial`;
24233
24559
  const file = await open(partial, "wx", 384);
24234
24560
  try {
@@ -24294,10 +24620,10 @@ async function beginOneShotEvidence(root, intent, sensitive) {
24294
24620
  }
24295
24621
 
24296
24622
  // plugins/kxm/src/prices.ts
24297
- var import_yaml3 = __toESM(require_dist(), 1);
24623
+ var import_yaml4 = __toESM(require_dist(), 1);
24298
24624
  import { createHash as createHash10 } from "node:crypto";
24299
- import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync3 } from "node:fs";
24300
- import { join as join9 } from "node:path";
24625
+ import { existsSync as existsSync9, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync3 } from "node:fs";
24626
+ import { join as join10 } from "node:path";
24301
24627
 
24302
24628
  // plugins/kxm/src/price-calc.ts
24303
24629
  var PRICES_SCHEMA = "kxm.prices.v1";
@@ -24361,7 +24687,7 @@ function hashPriceCatalog(catalog) {
24361
24687
  return createHash10("sha256").update(JSON.stringify(canonical), "utf8").digest("hex");
24362
24688
  }
24363
24689
  function parsePriceCatalog(text) {
24364
- const parsed = (0, import_yaml3.parse)(text);
24690
+ const parsed = (0, import_yaml4.parse)(text);
24365
24691
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
24366
24692
  throw new Error("price catalog must be an object");
24367
24693
  }
@@ -24449,49 +24775,49 @@ function parsePriceCatalog(text) {
24449
24775
  return catalog;
24450
24776
  }
24451
24777
  function loadPriceCatalog(rootOrPath) {
24452
- 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;
24453
- if (!candidatePath || !existsSync8(candidatePath)) {
24778
+ 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;
24779
+ if (!candidatePath || !existsSync9(candidatePath)) {
24454
24780
  return void 0;
24455
24781
  }
24456
- const content = readFileSync6(candidatePath, "utf8");
24782
+ const content = readFileSync7(candidatePath, "utf8");
24457
24783
  return parsePriceCatalog(content);
24458
24784
  }
24459
24785
 
24460
24786
  // plugins/kxm/src/engine.ts
24461
- var import_yaml9 = __toESM(require_dist(), 1);
24787
+ var import_yaml10 = __toESM(require_dist(), 1);
24462
24788
  import { createHash as createHash14, randomBytes, timingSafeEqual } from "node:crypto";
24463
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
24464
- import { join as join15 } from "node:path";
24789
+ import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
24790
+ import { join as join16 } from "node:path";
24465
24791
 
24466
24792
  // plugins/kxm/src/routes.ts
24467
- var import_yaml6 = __toESM(require_dist(), 1);
24468
- import { existsSync as existsSync9, readFileSync as readFileSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync5 } from "node:fs";
24469
- import { join as join10 } from "node:path";
24793
+ var import_yaml7 = __toESM(require_dist(), 1);
24794
+ import { existsSync as existsSync10, readFileSync as readFileSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync6 } from "node:fs";
24795
+ import { join as join11 } from "node:path";
24470
24796
 
24471
24797
  // plugins/kxm/src/role.ts
24472
- var import_yaml5 = __toESM(require_dist(), 1);
24798
+ var import_yaml6 = __toESM(require_dist(), 1);
24473
24799
 
24474
24800
  // plugins/kxm/src/config.ts
24475
- var import_yaml4 = __toESM(require_dist(), 1);
24801
+ var import_yaml5 = __toESM(require_dist(), 1);
24476
24802
 
24477
24803
  // plugins/kxm/src/routes.ts
24478
24804
  var RETIRED_POLICY = ".kxm/producers.yaml";
24479
24805
  var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [] });
24480
24806
  function loadRoutePolicy(root) {
24481
- if (existsSync9(join10(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
24482
- const path = join10(root, ".kxm", "routes.yaml");
24483
- if (!existsSync9(path)) return empty();
24484
- const value = (0, import_yaml6.parse)(readFileSync7(path, "utf8"));
24807
+ if (existsSync10(join11(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
24808
+ const path = join11(root, ".kxm", "routes.yaml");
24809
+ if (!existsSync10(path)) return empty();
24810
+ const value = (0, import_yaml7.parse)(readFileSync8(path, "utf8"));
24485
24811
  if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
24486
24812
  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") : [] };
24487
24813
  }
24488
24814
  function listRoleBindings(root) {
24489
- const dir = join10(root, ".kxm", "roles");
24815
+ const dir = join11(root, ".kxm", "roles");
24490
24816
  const result = {};
24491
- if (!existsSync9(dir)) return result;
24492
- for (const file of readdirSync5(dir).filter((name) => name.endsWith(".yaml"))) {
24817
+ if (!existsSync10(dir)) return result;
24818
+ for (const file of readdirSync6(dir).filter((name) => name.endsWith(".yaml"))) {
24493
24819
  const role = file.slice(0, -5);
24494
- const value = (0, import_yaml6.parse)(readFileSync7(join10(dir, file), "utf8"));
24820
+ const value = (0, import_yaml7.parse)(readFileSync8(join11(dir, file), "utf8"));
24495
24821
  result[role] = (value.roster ?? []).map((entry) => entry.route).filter((route) => typeof route === "string");
24496
24822
  }
24497
24823
  return result;
@@ -24823,8 +25149,8 @@ function pruneContextPacket(packet, tokenBudget) {
24823
25149
 
24824
25150
  // plugins/kxm/src/dispatch-context.ts
24825
25151
  import { spawnSync as spawnSync5 } from "node:child_process";
24826
- import { readdirSync as readdirSync8 } from "node:fs";
24827
- import { extname as extname3, join as join13 } from "node:path";
25152
+ import { readdirSync as readdirSync9 } from "node:fs";
25153
+ import { extname as extname3, join as join14 } from "node:path";
24828
25154
 
24829
25155
  // plugins/kxm/src/protocol.ts
24830
25156
  var DEFAULT_MESSAGE_TTL_MS = 24 * 60 * 6e4;
@@ -25452,9 +25778,9 @@ function memoryRecordToContextItem(record2, project) {
25452
25778
  }
25453
25779
 
25454
25780
  // plugins/kxm/src/memory.ts
25455
- var import_yaml7 = __toESM(require_dist(), 1);
25456
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
25457
- import { extname as extname2, join as join11, resolve as resolve7 } from "node:path";
25781
+ var import_yaml8 = __toESM(require_dist(), 1);
25782
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, readdirSync as readdirSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "node:fs";
25783
+ import { extname as extname2, join as join12, resolve as resolve7 } from "node:path";
25458
25784
  var MEMORY_SCHEMA = "kxm.memory.v1";
25459
25785
  var VALID_SCOPES = /* @__PURE__ */ new Set(["agent", "project", "run", "operator"]);
25460
25786
  var VALID_AUTHORITIES = /* @__PURE__ */ new Set(["instruction", "evidence", "promoted"]);
@@ -25484,7 +25810,7 @@ function parseFrontmatter(content) {
25484
25810
  }
25485
25811
  function parseMemoryRecord(raw, filename = "memory.md") {
25486
25812
  const { frontmatter, body } = parseFrontmatter(raw);
25487
- const data = (0, import_yaml7.parse)(frontmatter);
25813
+ const data = (0, import_yaml8.parse)(frontmatter);
25488
25814
  if (!data || typeof data !== "object" || Array.isArray(data)) {
25489
25815
  throw new Error(`invalid YAML frontmatter in ${filename}`);
25490
25816
  }
@@ -25553,20 +25879,20 @@ function parseMemoryRecord(raw, filename = "memory.md") {
25553
25879
  }
25554
25880
  function memoryDirectories(repoRoot) {
25555
25881
  const root = resolve7(repoRoot);
25556
- const memoryDir = join11(root, ".kxm", "memory");
25557
- const candidatesDir = join11(memoryDir, "candidates");
25882
+ const memoryDir = join12(root, ".kxm", "memory");
25883
+ const candidatesDir = join12(memoryDir, "candidates");
25558
25884
  return { memoryDir, candidatesDir };
25559
25885
  }
25560
25886
  function loadAuthoredMemory(repoRoot) {
25561
25887
  const { memoryDir } = memoryDirectories(repoRoot);
25562
- if (!existsSync10(memoryDir)) return [];
25888
+ if (!existsSync11(memoryDir)) return [];
25563
25889
  const records = [];
25564
- const entries = readdirSync6(memoryDir, { withFileTypes: true });
25890
+ const entries = readdirSync7(memoryDir, { withFileTypes: true });
25565
25891
  for (const entry of entries) {
25566
25892
  if (entry.isFile() && extname2(entry.name) === ".md") {
25567
- const fullPath = join11(memoryDir, entry.name);
25893
+ const fullPath = join12(memoryDir, entry.name);
25568
25894
  try {
25569
- const text = readFileSync8(fullPath, "utf8");
25895
+ const text = readFileSync9(fullPath, "utf8");
25570
25896
  const record2 = parseMemoryRecord(text, entry.name);
25571
25897
  if (record2.lifecycle === "active") {
25572
25898
  records.push(record2);
@@ -25580,10 +25906,10 @@ function loadAuthoredMemory(repoRoot) {
25580
25906
  }
25581
25907
 
25582
25908
  // plugins/kxm/src/skills.ts
25583
- var import_yaml8 = __toESM(require_dist(), 1);
25909
+ var import_yaml9 = __toESM(require_dist(), 1);
25584
25910
  import { createHash as createHash11 } from "node:crypto";
25585
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as readdirSync7, readFileSync as readFileSync9, renameSync, rmSync, statSync as statSync3, writeFileSync as writeFileSync6 } from "node:fs";
25586
- import { dirname as dirname7, join as join12 } from "node:path";
25911
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, readdirSync as readdirSync8, readFileSync as readFileSync10, renameSync, rmSync, statSync as statSync3, writeFileSync as writeFileSync6 } from "node:fs";
25912
+ import { dirname as dirname7, join as join13 } from "node:path";
25587
25913
  var SKILL_CANDIDATE_SCHEMA = "kxm.skill-candidate.v1";
25588
25914
  var SKILL_EVALUATION_SCHEMA = "kxm.skill-evaluation.v1";
25589
25915
  var SKILL_DECISION_SCHEMA = "kxm.skill-decision.v1";
@@ -25624,7 +25950,7 @@ function parseSkillFrontmatter(content) {
25624
25950
  return { frontmatter: null, body: content };
25625
25951
  }
25626
25952
  try {
25627
- const parsed = (0, import_yaml8.parse)(rawFm);
25953
+ const parsed = (0, import_yaml9.parse)(rawFm);
25628
25954
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
25629
25955
  return { frontmatter: parsed, body: rawBody };
25630
25956
  }
@@ -25689,20 +26015,20 @@ var SkillLifecycle = class {
25689
26015
  writeFileSync6(file, content);
25690
26016
  }
25691
26017
  dir(state) {
25692
- return join12(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
26018
+ return join13(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
25693
26019
  }
25694
26020
  historyFile(id) {
25695
- return join12(this.root, "history", `${id}.jsonl`);
26021
+ return join13(this.root, "history", `${id}.jsonl`);
25696
26022
  }
25697
26023
  paths(state, id) {
25698
- const dir = join12(this.dir(state), id);
25699
- return { dir, metadata: join12(dir, "metadata.json"), skill: join12(dir, "SKILL.md") };
26024
+ const dir = join13(this.dir(state), id);
26025
+ return { dir, metadata: join13(dir, "metadata.json"), skill: join13(dir, "SKILL.md") };
25700
26026
  }
25701
26027
  appendHistory(id, record2) {
25702
26028
  const line = `${JSON.stringify(record2)}
25703
26029
  `;
25704
- if (existsSync11(this.historyFile(id))) {
25705
- const existing = readFileSync9(this.historyFile(id), "utf8");
26030
+ if (existsSync12(this.historyFile(id))) {
26031
+ const existing = readFileSync10(this.historyFile(id), "utf8");
25706
26032
  const lines = existing.split("\n").filter((entry) => entry.trim());
25707
26033
  this.write(this.historyFile(id), [...lines.slice(-499), line.trim()].join("\n") + "\n");
25708
26034
  } else {
@@ -25711,20 +26037,20 @@ var SkillLifecycle = class {
25711
26037
  }
25712
26038
  history(id) {
25713
26039
  const file = this.historyFile(id);
25714
- if (!existsSync11(file)) return [];
25715
- return readFileSync9(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
26040
+ if (!existsSync12(file)) return [];
26041
+ return readFileSync10(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
25716
26042
  }
25717
26043
  readMetadata(state, id) {
25718
26044
  const { metadata } = this.paths(state, id);
25719
- if (!existsSync11(metadata)) {
26045
+ if (!existsSync12(metadata)) {
25720
26046
  throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${state}`);
25721
26047
  }
25722
- return JSON.parse(readFileSync9(metadata, "utf8"));
26048
+ return JSON.parse(readFileSync10(metadata, "utf8"));
25723
26049
  }
25724
26050
  move(from, to, id) {
25725
- const fromDir = join12(this.dir(from), id);
25726
- const toDir = join12(this.dir(to), id);
25727
- if (!existsSync11(fromDir)) {
26051
+ const fromDir = join13(this.dir(from), id);
26052
+ const toDir = join13(this.dir(to), id);
26053
+ if (!existsSync12(fromDir)) {
25728
26054
  throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${from}`);
25729
26055
  }
25730
26056
  if (this.dryRun) {
@@ -25732,7 +26058,7 @@ var SkillLifecycle = class {
25732
26058
  return;
25733
26059
  }
25734
26060
  mkdirSync5(this.dir(to), { recursive: true });
25735
- if (existsSync11(toDir)) rmSync(toDir, { recursive: true, force: true });
26061
+ if (existsSync12(toDir)) rmSync(toDir, { recursive: true, force: true });
25736
26062
  renameSync(fromDir, toDir);
25737
26063
  }
25738
26064
  /** Submit a new skill candidate. Content is redacted of secret material at
@@ -25775,7 +26101,7 @@ var SkillLifecycle = class {
25775
26101
  const contentSha256 = skillContentSha256(content);
25776
26102
  const id = skillIdFor(name, contentSha256);
25777
26103
  const { metadata, skill } = this.paths("candidate", id);
25778
- if (existsSync11(metadata)) {
26104
+ if (existsSync12(metadata)) {
25779
26105
  throw new SkillLifecycleError(
25780
26106
  "skill_candidate_exists",
25781
26107
  `identical candidate ${id} already exists; changed behavior requires changed content`
@@ -25884,11 +26210,11 @@ var SkillLifecycle = class {
25884
26210
  };
25885
26211
  const candidatePaths = this.paths("candidate", candidateId);
25886
26212
  const promotedPaths = this.paths("promoted", candidateId);
25887
- const skillContent = readFileSync9(candidatePaths.skill, "utf8");
25888
- const metadataContent = readFileSync9(candidatePaths.metadata, "utf8");
26213
+ const skillContent = readFileSync10(candidatePaths.skill, "utf8");
26214
+ const metadataContent = readFileSync10(candidatePaths.metadata, "utf8");
25889
26215
  this.write(promotedPaths.skill, skillContent);
25890
26216
  this.write(promotedPaths.metadata, metadataContent);
25891
- const patchPath = join12(this.root, "patches", `${candidateId}.patch`);
26217
+ const patchPath = join13(this.root, "patches", `${candidateId}.patch`);
25892
26218
  const relSkillPath = `.kxm/skills/promoted/${candidateId}/SKILL.md`;
25893
26219
  const relMetaPath = `.kxm/skills/promoted/${candidateId}/metadata.json`;
25894
26220
  const patch = `${createUnifiedPatch(relSkillPath, skillContent)}${createUnifiedPatch(relMetaPath, metadataContent)}`;
@@ -25916,7 +26242,7 @@ var SkillLifecycle = class {
25916
26242
  verify(state, id) {
25917
26243
  const metadata = this.readMetadata(state, id);
25918
26244
  const { skill } = this.paths(state, id);
25919
- const content = readFileSync9(skill, "utf8");
26245
+ const content = readFileSync10(skill, "utf8");
25920
26246
  if (skillContentSha256(content) !== metadata.contentSha256) {
25921
26247
  throw new SkillLifecycleError(
25922
26248
  "skill_integrity_violation",
@@ -25934,7 +26260,7 @@ var SkillLifecycle = class {
25934
26260
  }
25935
26261
  list(state) {
25936
26262
  const dir = this.dir(state);
25937
- if (!existsSync11(dir)) return [];
26263
+ if (!existsSync12(dir)) return [];
25938
26264
  const ids = readdirSorted(dir);
25939
26265
  return ids.map((id) => {
25940
26266
  try {
@@ -25947,7 +26273,7 @@ var SkillLifecycle = class {
25947
26273
  read(state, id) {
25948
26274
  const metadata = this.readMetadata(state, id);
25949
26275
  const { skill } = this.paths(state, id);
25950
- return { metadata, content: readFileSync9(skill, "utf8") };
26276
+ return { metadata, content: readFileSync10(skill, "utf8") };
25951
26277
  }
25952
26278
  };
25953
26279
  function boundedList(value, field) {
@@ -25962,7 +26288,7 @@ function boundedList(value, field) {
25962
26288
  return [...new Set(refs)];
25963
26289
  }
25964
26290
  function readdirSorted(dir) {
25965
- return readdirSync7(dir).filter((entry) => statSync3(join12(dir, entry)).isDirectory()).sort();
26291
+ return readdirSync8(dir).filter((entry) => statSync3(join13(dir, entry)).isDirectory()).sort();
25966
26292
  }
25967
26293
 
25968
26294
  // plugins/kxm/src/dispatch-context.ts
@@ -26003,18 +26329,18 @@ function contextRoleForAgent(agentId) {
26003
26329
  return agentId;
26004
26330
  }
26005
26331
  function dispatchContextPresent(projectRoot) {
26006
- return hasTopLevelMarkdown(join13(projectRoot, ".kxm", "memory")) || hasAnyEntry(join13(projectRoot, ".kxm", "skills", "promoted"));
26332
+ return hasTopLevelMarkdown(join14(projectRoot, ".kxm", "memory")) || hasAnyEntry(join14(projectRoot, ".kxm", "skills", "promoted"));
26007
26333
  }
26008
26334
  function hasTopLevelMarkdown(dir) {
26009
26335
  try {
26010
- return readdirSync8(dir, { withFileTypes: true }).some((entry) => entry.isFile() && extname3(entry.name) === ".md");
26336
+ return readdirSync9(dir, { withFileTypes: true }).some((entry) => entry.isFile() && extname3(entry.name) === ".md");
26011
26337
  } catch {
26012
26338
  return false;
26013
26339
  }
26014
26340
  }
26015
26341
  function hasAnyEntry(dir) {
26016
26342
  try {
26017
- return readdirSync8(dir).length > 0;
26343
+ return readdirSync9(dir).length > 0;
26018
26344
  } catch {
26019
26345
  return false;
26020
26346
  }
@@ -26079,7 +26405,7 @@ function loadDispatchContextSources(input) {
26079
26405
  }
26080
26406
  const promoted = [];
26081
26407
  try {
26082
- const lifecycle = new SkillLifecycle(join13(projectRoot, ".kxm", "skills"));
26408
+ const lifecycle = new SkillLifecycle(join14(projectRoot, ".kxm", "skills"));
26083
26409
  for (const metadata of lifecycle.list("promoted")) {
26084
26410
  try {
26085
26411
  promoted.push(lifecycle.verify("promoted", metadata.id));
@@ -26162,7 +26488,7 @@ function assembleDispatchContext(sources, input) {
26162
26488
  }
26163
26489
 
26164
26490
  // plugins/kxm/src/engine-artifacts.ts
26165
- import { join as join14 } from "node:path";
26491
+ import { join as join15 } from "node:path";
26166
26492
 
26167
26493
  // plugins/kxm/src/artifacts-exist.ts
26168
26494
  import { lstatSync as lstatSync5, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
@@ -26209,14 +26535,14 @@ function verifyArtifactExists(rootInput, pathInput) {
26209
26535
  // plugins/kxm/src/engine-artifacts.ts
26210
26536
  var kxmArtifactsGateSeams = {};
26211
26537
  function evaluateArtifactsGate(context, definition) {
26212
- const root = join14(context.projectRoot, ".kxm", "assets");
26538
+ const root = join15(context.projectRoot, ".kxm", "assets");
26213
26539
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
26214
26540
  const startTime = process.hrtime.bigint();
26215
26541
  let checkedCount = 0;
26216
26542
  let failedCount = 0;
26217
26543
  for (const [index, path] of definition.paths.entries()) {
26218
26544
  checkedCount += 1;
26219
- const result = verifyArtifactExists(root, join14(root, path));
26545
+ const result = verifyArtifactExists(root, join15(root, path));
26220
26546
  if (!result.ok) failedCount += 1;
26221
26547
  kxmArtifactsGateSeams.afterPathChecked?.({ path, index, checkedCount, failedCount });
26222
26548
  }
@@ -27343,7 +27669,7 @@ function pinKxmCompiledPlan(context, bundle, runId, options) {
27343
27669
  if (String(bundle.project.value.id) !== run.projectId) {
27344
27670
  throw runtimeError("run_owner_mismatch", runId, "bundle project does not match the run");
27345
27671
  }
27346
- const workflow = bundle.workflows.get(run.workflowId);
27672
+ const workflow = lookupKxmResource(bundle.workflows.values(), run.workflowId, "workflow");
27347
27673
  if (!workflow) throw runtimeError("run_workflow_unknown", run.workflowId, `workflow ${run.workflowId} does not exist in this project`);
27348
27674
  const revisions = kxmPolicyRevisions(bundle, options);
27349
27675
  if (revisions.configRevision !== run.configRevision || revisions.executorPolicyRevision !== run.executorPolicyRevision || revisions.toolPolicyRevision !== run.toolPolicyRevision || revisions.memoryRevision !== run.memoryRevision) {
@@ -28076,9 +28402,9 @@ function readYamlFile(file) {
28076
28402
  return readModelDocument(file);
28077
28403
  }
28078
28404
  function readModelDocument(file) {
28079
- if (!existsSync12(file)) return void 0;
28405
+ if (!existsSync13(file)) return void 0;
28080
28406
  try {
28081
- const parsed = (0, import_yaml9.parse)(readFileSync10(file, "utf8"));
28407
+ const parsed = (0, import_yaml10.parse)(readFileSync11(file, "utf8"));
28082
28408
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
28083
28409
  return parsed;
28084
28410
  } catch {
@@ -28109,7 +28435,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28109
28435
  }
28110
28436
  };
28111
28437
  }
28112
- const agent = readYamlFile(join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`));
28438
+ const agentFile = findYamlBasename(join16(projectRoot, ".kxm", "agents"), agentId, "agent") ?? agentId;
28439
+ const agent = readYamlFile(join16(projectRoot, ".kxm", "agents", `${agentFile}.yaml`));
28113
28440
  const role = typeof agent?.role === "string" ? agent.role : "";
28114
28441
  if (!role) {
28115
28442
  return {
@@ -28120,7 +28447,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28120
28447
  }
28121
28448
  };
28122
28449
  }
28123
- const roleDoc = readYamlFile(join15(projectRoot, ".kxm", "roles", `${role}.yaml`));
28450
+ const roleDoc = readYamlFile(join16(projectRoot, ".kxm", "roles", `${role}.yaml`));
28124
28451
  const roster = Array.isArray(roleDoc?.roster) ? roleDoc.roster : void 0;
28125
28452
  if (!roster) {
28126
28453
  return {
@@ -28136,7 +28463,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28136
28463
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
28137
28464
  const record2 = entry;
28138
28465
  if (typeof record2.route !== "string" || record2.route.length === 0) continue;
28139
- const modelPath = join15(projectRoot, ".kxm", "models", `${record2.route}.yaml`);
28466
+ const routeFile = findYamlBasename(join16(projectRoot, ".kxm", "models"), record2.route, "route") ?? record2.route;
28467
+ const modelPath = join16(projectRoot, ".kxm", "models", `${routeFile}.yaml`);
28140
28468
  const doc = readModelDocument(modelPath);
28141
28469
  if (!doc) {
28142
28470
  return {
@@ -28199,7 +28527,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
28199
28527
  model: selector.slice(slash + 1),
28200
28528
  selector,
28201
28529
  harness,
28202
- routeId: record2.route,
28530
+ routeId: routeFile,
28203
28531
  role,
28204
28532
  permissions,
28205
28533
  ...typeof record2.effort === "string" ? { effort: record2.effort } : {}
@@ -28241,7 +28569,7 @@ function settleExitedExecutingAttempt(context, run, executing) {
28241
28569
  let sequence = context.eventStore.nextSequence(run.runId);
28242
28570
  let mono = kxmMonotonicNs();
28243
28571
  const events = [];
28244
- const push = (eventType, payload) => {
28572
+ const push2 = (eventType, payload) => {
28245
28573
  events.push({
28246
28574
  ...kxmEventBase(context, run, now, mono),
28247
28575
  eventId: newKxmEventId(),
@@ -28251,18 +28579,18 @@ function settleExitedExecutingAttempt(context, run, executing) {
28251
28579
  });
28252
28580
  mono = kxmIncrementMonotonicNs(mono);
28253
28581
  };
28254
- push("attempt.status_changed", { attemptId: executing.attemptId, status: "settling" });
28255
- push("assignment.result_recorded", {
28582
+ push2("attempt.status_changed", { attemptId: executing.attemptId, status: "settling" });
28583
+ push2("assignment.result_recorded", {
28256
28584
  assignmentId: executing.assignmentId,
28257
28585
  resultClass: "producer_rejected",
28258
28586
  status: "result_recorded",
28259
28587
  producerError: "executing_unrecorded",
28260
28588
  reason: "executing_unrecorded"
28261
28589
  });
28262
- push("attempt.status_changed", { attemptId: executing.attemptId, status: "terminal" });
28263
- push("assignment.terminal", { assignmentId: executing.assignmentId, outcome: "failed", status: "terminal" });
28264
- push("step.status_changed", { stepId: executing.stepId, status: "cancelled", previousStatus: "running" });
28265
- push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
28590
+ push2("attempt.status_changed", { attemptId: executing.attemptId, status: "terminal" });
28591
+ push2("assignment.terminal", { assignmentId: executing.assignmentId, outcome: "failed", status: "terminal" });
28592
+ push2("step.status_changed", { stepId: executing.stepId, status: "cancelled", previousStatus: "running" });
28593
+ push2("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
28266
28594
  for (const event of events) context.eventStore.appendEvent(event);
28267
28595
  context.eventStore.settleCapability(executing.attemptId, "settled");
28268
28596
  const next = foldStoredKxmRun(context, run);
@@ -28443,7 +28771,7 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
28443
28771
  let sequence = context.eventStore.nextSequence(runId);
28444
28772
  let mono = kxmMonotonicNs();
28445
28773
  const events = [];
28446
- const push = (eventType, payload) => {
28774
+ const push2 = (eventType, payload) => {
28447
28775
  events.push({
28448
28776
  ...kxmEventBase(context, run, now, mono),
28449
28777
  eventId: newKxmEventId(),
@@ -28453,8 +28781,8 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
28453
28781
  });
28454
28782
  mono = kxmIncrementMonotonicNs(mono);
28455
28783
  };
28456
- push("step.entered", { stepId, stepAttempt, status: "pending" });
28457
- push("step.status_changed", { stepId, status: "preparing", previousStatus: "pending" });
28784
+ push2("step.entered", { stepId, stepAttempt, status: "pending" });
28785
+ push2("step.status_changed", { stepId, status: "preparing", previousStatus: "pending" });
28458
28786
  for (const event of events) context.eventStore.appendEvent(event);
28459
28787
  const entered = foldStoredKxmRun(context, run);
28460
28788
  persistKxmRunState(context, runId, entered, events[events.length - 1].sequence);
@@ -28555,7 +28883,7 @@ function birthMember(context, input) {
28555
28883
  let sequence = context.eventStore.nextSequence(run.runId);
28556
28884
  let mono = kxmMonotonicNs();
28557
28885
  const events = [];
28558
- const push = (eventType, payload) => {
28886
+ const push2 = (eventType, payload) => {
28559
28887
  events.push({
28560
28888
  ...kxmEventBase(context, run, now, mono),
28561
28889
  eventId: newKxmEventId(),
@@ -28565,18 +28893,18 @@ function birthMember(context, input) {
28565
28893
  });
28566
28894
  mono = kxmIncrementMonotonicNs(mono);
28567
28895
  };
28568
- push("assignment.created", { assignmentId, stepId: input.stepId, stepAttempt: input.stepAttempt, agentId, status: "created" });
28569
- push("assignment.accepted", { assignmentId, status: "accepted" });
28570
- push("attempt.created", { attemptId, assignmentId, status: "created" });
28571
- push("assignment.dispatched", {
28896
+ push2("assignment.created", { assignmentId, stepId: input.stepId, stepAttempt: input.stepAttempt, agentId, status: "created" });
28897
+ push2("assignment.accepted", { assignmentId, status: "accepted" });
28898
+ push2("attempt.created", { attemptId, assignmentId, status: "created" });
28899
+ push2("assignment.dispatched", {
28572
28900
  assignmentId,
28573
28901
  capabilityHash: minted.hash,
28574
28902
  status: "dispatched",
28575
28903
  ...resolvedRoute ? { model: { provider: resolvedRoute.provider, model: resolvedRoute.model } } : {}
28576
28904
  });
28577
- push("attempt.status_changed", { attemptId, status: "starting" });
28905
+ push2("attempt.status_changed", { attemptId, status: "starting" });
28578
28906
  if (input.enterRunning) {
28579
- push("step.status_changed", { stepId: input.stepId, status: "running", previousStatus: "preparing" });
28907
+ push2("step.status_changed", { stepId: input.stepId, status: "running", previousStatus: "preparing" });
28580
28908
  }
28581
28909
  for (const event of events) context.eventStore.appendEvent(event);
28582
28910
  context.eventStore.insertCapability({
@@ -29032,7 +29360,7 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29032
29360
  let sequence = context.eventStore.nextSequence(run.runId);
29033
29361
  let mono = kxmMonotonicNs();
29034
29362
  const events = [];
29035
- const push = (eventType, payload) => {
29363
+ const push2 = (eventType, payload) => {
29036
29364
  events.push({
29037
29365
  ...kxmEventBase(context, run, now, mono),
29038
29366
  eventId: newKxmEventId(),
@@ -29042,17 +29370,17 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29042
29370
  });
29043
29371
  mono = kxmIncrementMonotonicNs(mono);
29044
29372
  };
29045
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "settling" });
29373
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "settling" });
29046
29374
  if (cancelling) {
29047
- push("routing.attempt.recorded", { routing: producerRoutingRecord(
29375
+ push2("routing.attempt.recorded", { routing: producerRoutingRecord(
29048
29376
  context,
29049
29377
  dispatch,
29050
29378
  result ?? { outcome: "cancelled", costBasis: "unknown", costUsd: null },
29051
29379
  now
29052
29380
  ) });
29053
- push("assignment.result_recorded", { assignmentId: dispatch.assignmentId, resultClass: "cancelled", status: "result_recorded" });
29054
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29055
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "cancelled", status: "terminal" });
29381
+ push2("assignment.result_recorded", { assignmentId: dispatch.assignmentId, resultClass: "cancelled", status: "result_recorded" });
29382
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29383
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "cancelled", status: "terminal" });
29056
29384
  } else if (produceError) {
29057
29385
  const envelope2 = loadKxmRunPlanEnvelope(context.eventStore, run);
29058
29386
  const rawHash = result?.behavioralSha256 ?? behavioralConfigHash({
@@ -29086,22 +29414,22 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29086
29414
  finalOutcome: "failed",
29087
29415
  providerMetadata: engineRoutingMetadata(dispatch)
29088
29416
  };
29089
- push("routing.attempt.recorded", { routing: parseRoutingRecordV2(routingRecord) });
29090
- push("assignment.result_recorded", {
29417
+ push2("routing.attempt.recorded", { routing: parseRoutingRecordV2(routingRecord) });
29418
+ push2("assignment.result_recorded", {
29091
29419
  assignmentId: dispatch.assignmentId,
29092
29420
  resultClass: "producer_rejected",
29093
29421
  status: "result_recorded",
29094
29422
  ...produceErrorCode !== void 0 ? { producerError: produceErrorCode } : {}
29095
29423
  });
29096
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29097
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
29424
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29425
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
29098
29426
  } else {
29099
29427
  if (!result) {
29100
29428
  throw runtimeError("settle_missing_cost_basis", run.runId, `attempt settlement rejected: missing required costBasis for attempt ${dispatch.attemptId}`);
29101
29429
  }
29102
29430
  const outcome = typeof result.outcome === "string" ? result.outcome : void 0;
29103
29431
  const known = outcome !== void 0 && dispatch.step.outcomes.includes(outcome);
29104
- push("routing.attempt.recorded", {
29432
+ push2("routing.attempt.recorded", {
29105
29433
  routing: producerRoutingRecord(
29106
29434
  context,
29107
29435
  dispatch,
@@ -29111,22 +29439,22 @@ function settleMember(context, dispatch, result, produceError, produceErrorCode)
29111
29439
  )
29112
29440
  });
29113
29441
  if (!known) {
29114
- push("assignment.result_recorded", {
29442
+ push2("assignment.result_recorded", {
29115
29443
  assignmentId: dispatch.assignmentId,
29116
29444
  resultClass: "outcome_unknown",
29117
29445
  status: "result_recorded"
29118
29446
  });
29119
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29120
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
29447
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29448
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome: "failed", status: "terminal" });
29121
29449
  } else {
29122
- push("assignment.result_recorded", {
29450
+ push2("assignment.result_recorded", {
29123
29451
  assignmentId: dispatch.assignmentId,
29124
29452
  outcome,
29125
29453
  resultClass: "outcome",
29126
29454
  status: "result_recorded"
29127
29455
  });
29128
- push("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29129
- push("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome, status: "terminal" });
29456
+ push2("attempt.status_changed", { attemptId: dispatch.attemptId, status: "terminal" });
29457
+ push2("assignment.terminal", { assignmentId: dispatch.assignmentId, outcome, status: "terminal" });
29130
29458
  }
29131
29459
  }
29132
29460
  context.eventStore.settleCapability(dispatch.attemptId, "settled");
@@ -29146,7 +29474,7 @@ function joinPanel(context, panel) {
29146
29474
  let sequence = context.eventStore.nextSequence(run.runId);
29147
29475
  let mono = kxmMonotonicNs();
29148
29476
  const events = [];
29149
- const push = (eventType, payload) => {
29477
+ const push2 = (eventType, payload) => {
29150
29478
  events.push({
29151
29479
  ...kxmEventBase(context, run, now, mono),
29152
29480
  eventId: newKxmEventId(),
@@ -29157,8 +29485,8 @@ function joinPanel(context, panel) {
29157
29485
  mono = kxmIncrementMonotonicNs(mono);
29158
29486
  };
29159
29487
  const failRun = (reason) => {
29160
- push("step.status_changed", { stepId: panel.stepId, status: "failed", previousStatus: "running" });
29161
- push("run.status_changed", { status: "failed", reason, stepId: panel.stepId });
29488
+ push2("step.status_changed", { stepId: panel.stepId, status: "failed", previousStatus: "running" });
29489
+ push2("run.status_changed", { status: "failed", reason, stepId: panel.stepId });
29162
29490
  for (const event of events) context.eventStore.appendEvent(event);
29163
29491
  const next2 = foldStoredKxmRun(context, run);
29164
29492
  persistKxmRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -29166,8 +29494,8 @@ function joinPanel(context, panel) {
29166
29494
  return { state: next2 };
29167
29495
  };
29168
29496
  const cancelRun = () => {
29169
- push("step.status_changed", { stepId: panel.stepId, status: "cancelled", previousStatus: "running" });
29170
- push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
29497
+ push2("step.status_changed", { stepId: panel.stepId, status: "cancelled", previousStatus: "running" });
29498
+ push2("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
29171
29499
  for (const event of events) context.eventStore.appendEvent(event);
29172
29500
  const next2 = foldStoredKxmRun(context, run);
29173
29501
  persistKxmRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -29199,12 +29527,12 @@ function joinPanel(context, panel) {
29199
29527
  const outcome = joined.outcome;
29200
29528
  const selected = panel.step.transitions[outcome];
29201
29529
  if (!selected) return failRun("outcome_unknown");
29202
- push("step.outcome_recorded", { stepId: panel.stepId, stepAttempt: panel.stepAttempt, outcome });
29530
+ push2("step.outcome_recorded", { stepId: panel.stepId, stepAttempt: panel.stepAttempt, outcome });
29203
29531
  const stepStatus = outcome === "passed" ? "passed" : outcome === "cancelled" ? "cancelled" : "failed";
29204
- push("step.status_changed", { stepId: panel.stepId, status: stepStatus, previousStatus: "running" });
29532
+ push2("step.status_changed", { stepId: panel.stepId, status: stepStatus, previousStatus: "running" });
29205
29533
  const budget = transitionBudgetFailure(panel.plan, state, panel.stepId, outcome);
29206
29534
  if (budget) {
29207
- push("run.status_changed", { status: "failed", reason: budget, stepId: panel.stepId, outcome });
29535
+ push2("run.status_changed", { status: "failed", reason: budget, stepId: panel.stepId, outcome });
29208
29536
  for (const event of events) context.eventStore.appendEvent(event);
29209
29537
  const next2 = foldStoredKxmRun(context, run);
29210
29538
  persistKxmRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -29212,10 +29540,10 @@ function joinPanel(context, panel) {
29212
29540
  return { state: next2 };
29213
29541
  }
29214
29542
  if (selected.to === "step") {
29215
- push("step.transitioned", { fromStepId: panel.stepId, toStepId: selected.target, outcome });
29543
+ push2("step.transitioned", { fromStepId: panel.stepId, toStepId: selected.target, outcome });
29216
29544
  } else {
29217
- push("step.transitioned", { fromStepId: panel.stepId, status: selected.terminalStatus, outcome });
29218
- push("run.status_changed", { status: selected.terminalStatus });
29545
+ push2("step.transitioned", { fromStepId: panel.stepId, status: selected.terminalStatus, outcome });
29546
+ push2("run.status_changed", { status: selected.terminalStatus });
29219
29547
  }
29220
29548
  for (const event of events) context.eventStore.appendEvent(event);
29221
29549
  const next = foldStoredKxmRun(context, run);
@@ -29819,7 +30147,7 @@ function recoverKxmRun(context, runId, request) {
29819
30147
  let sequence = context.eventStore.nextSequence(runId);
29820
30148
  let mono = kxmMonotonicNs();
29821
30149
  const events = [];
29822
- const push = (eventType, payload) => {
30150
+ const push2 = (eventType, payload) => {
29823
30151
  events.push({
29824
30152
  ...kxmEventBase(context, run, now, mono, request.commandId),
29825
30153
  eventId: newKxmEventId(),
@@ -29830,7 +30158,7 @@ function recoverKxmRun(context, runId, request) {
29830
30158
  mono = kxmIncrementMonotonicNs(mono);
29831
30159
  };
29832
30160
  if (state.status === "running" && state.currentStep?.effectState === "blocked_uncertain") {
29833
- push("run.status_changed", {
30161
+ push2("run.status_changed", {
29834
30162
  status: "blocked_uncertain",
29835
30163
  previousStatus: "running",
29836
30164
  reason: request.reason ?? "uncertain gate effect"
@@ -29850,7 +30178,7 @@ function recoverKxmRun(context, runId, request) {
29850
30178
  }
29851
30179
  }
29852
30180
  if (request.action === "retry" || request.action === "unblock") {
29853
- push("run.status_changed", {
30181
+ push2("run.status_changed", {
29854
30182
  status: "running",
29855
30183
  previousStatus: "blocked_uncertain",
29856
30184
  reason: request.reason ?? "operator_retry"
@@ -29862,7 +30190,7 @@ function recoverKxmRun(context, runId, request) {
29862
30190
  return { state: nextState, unblocked: true };
29863
30191
  }
29864
30192
  if (request.action === "fail") {
29865
- push("run.status_changed", {
30193
+ push2("run.status_changed", {
29866
30194
  status: "failed",
29867
30195
  previousStatus: "blocked_uncertain",
29868
30196
  reason: request.reason ?? "operator_fail"
@@ -29874,16 +30202,16 @@ function recoverKxmRun(context, runId, request) {
29874
30202
  return { state: nextState, unblocked: true };
29875
30203
  }
29876
30204
  if (request.action === "cancel") {
29877
- push("run.cancel_requested", {
30205
+ push2("run.cancel_requested", {
29878
30206
  actor: { kind: "runtime", id: context.homeRuntimeId },
29879
30207
  reason: request.reason ?? "operator_cancel"
29880
30208
  });
29881
- push("run.status_changed", {
30209
+ push2("run.status_changed", {
29882
30210
  status: "cancelling",
29883
30211
  previousStatus: "blocked_uncertain",
29884
30212
  reason: request.reason ?? "operator_cancel"
29885
30213
  });
29886
- push("run.status_changed", {
30214
+ push2("run.status_changed", {
29887
30215
  status: "cancelled",
29888
30216
  previousStatus: "cancelling",
29889
30217
  reason: request.reason ?? "operator_cancel"
@@ -30390,9 +30718,9 @@ var RuntimeHubClient = class {
30390
30718
  };
30391
30719
 
30392
30720
  // plugins/kxm/src/hub-binding.ts
30393
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
30721
+ import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync12, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
30394
30722
  import { homedir as homedir2 } from "node:os";
30395
- import { dirname as dirname8, isAbsolute as isAbsolute6, join as join16, resolve as resolve9 } from "node:path";
30723
+ import { dirname as dirname8, isAbsolute as isAbsolute6, join as join17, resolve as resolve9 } from "node:path";
30396
30724
  var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
30397
30725
  var HubBindingError = class extends Error {
30398
30726
  constructor(message) {
@@ -30408,16 +30736,16 @@ function resolveUserStateRoot(env) {
30408
30736
  }
30409
30737
  if (process.platform === "win32") {
30410
30738
  const localAppData = env.LOCALAPPDATA?.trim();
30411
- const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join16(homedir2(), "AppData", "Local");
30739
+ const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join17(homedir2(), "AppData", "Local");
30412
30740
  return resolve9(base2, "KXM");
30413
30741
  }
30414
30742
  if (process.platform === "darwin") return resolve9(homedir2(), "Library", "Application Support", "KXM");
30415
30743
  const xdgState = env.XDG_STATE_HOME?.trim();
30416
- const base = xdgState && isAbsolute6(xdgState) ? xdgState : join16(homedir2(), ".local", "state");
30744
+ const base = xdgState && isAbsolute6(xdgState) ? xdgState : join17(homedir2(), ".local", "state");
30417
30745
  return resolve9(base, "kxm");
30418
30746
  }
30419
30747
  function hubBindingFile(env = process.env) {
30420
- return join16(resolveUserStateRoot(env), "hub-binding.json");
30748
+ return join17(resolveUserStateRoot(env), "hub-binding.json");
30421
30749
  }
30422
30750
  function validateHubUrl(raw) {
30423
30751
  let parsed;
@@ -30437,10 +30765,10 @@ function isIsoTimestamp(value) {
30437
30765
  }
30438
30766
  function readHubBinding(env = process.env) {
30439
30767
  const file = hubBindingFile(env);
30440
- if (!existsSync13(file)) return void 0;
30768
+ if (!existsSync14(file)) return void 0;
30441
30769
  let parsed;
30442
30770
  try {
30443
- parsed = JSON.parse(readFileSync11(file, "utf8"));
30771
+ parsed = JSON.parse(readFileSync12(file, "utf8"));
30444
30772
  } catch {
30445
30773
  throw new HubBindingError(`malformed hub binding at ${file}`);
30446
30774
  }
@@ -30462,9 +30790,9 @@ function readHubBinding(env = process.env) {
30462
30790
  }
30463
30791
 
30464
30792
  // plugins/kxm/src/hub-env.ts
30465
- import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync12, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
30793
+ import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync13, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
30466
30794
  import { homedir as homedir3 } from "node:os";
30467
- import { dirname as dirname9, isAbsolute as isAbsolute7, join as join17, resolve as resolve10 } from "node:path";
30795
+ import { dirname as dirname9, isAbsolute as isAbsolute7, join as join18, resolve as resolve10 } from "node:path";
30468
30796
  var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
30469
30797
  var HubEnvError = class extends Error {
30470
30798
  constructor(message) {
@@ -30480,23 +30808,23 @@ function resolveUserStateRoot2(env) {
30480
30808
  }
30481
30809
  if (process.platform === "win32") {
30482
30810
  const localAppData = env.LOCALAPPDATA?.trim();
30483
- const base2 = localAppData && isAbsolute7(localAppData) ? localAppData : join17(homedir3(), "AppData", "Local");
30811
+ const base2 = localAppData && isAbsolute7(localAppData) ? localAppData : join18(homedir3(), "AppData", "Local");
30484
30812
  return resolve10(base2, "KXM");
30485
30813
  }
30486
30814
  if (process.platform === "darwin") return resolve10(homedir3(), "Library", "Application Support", "KXM");
30487
30815
  const xdgState = env.XDG_STATE_HOME?.trim();
30488
- const base = xdgState && isAbsolute7(xdgState) ? xdgState : join17(homedir3(), ".local", "state");
30816
+ const base = xdgState && isAbsolute7(xdgState) ? xdgState : join18(homedir3(), ".local", "state");
30489
30817
  return resolve10(base, "kxm");
30490
30818
  }
30491
30819
  function hubEnvFile(env = process.env) {
30492
- return join17(resolveUserStateRoot2(env), "hub-env.json");
30820
+ return join18(resolveUserStateRoot2(env), "hub-env.json");
30493
30821
  }
30494
30822
  function readHubEnvRecord(env = process.env) {
30495
30823
  const file = hubEnvFile(env);
30496
- if (!existsSync14(file)) return void 0;
30824
+ if (!existsSync15(file)) return void 0;
30497
30825
  let parsed;
30498
30826
  try {
30499
- parsed = JSON.parse(readFileSync12(file, "utf8"));
30827
+ parsed = JSON.parse(readFileSync13(file, "utf8"));
30500
30828
  } catch (error) {
30501
30829
  throw new HubEnvError(`hub env file is malformed at ${file}: ${error instanceof Error ? error.message : String(error)}`);
30502
30830
  }
@@ -30536,7 +30864,7 @@ function resolveClientHubAuthToken(env, project) {
30536
30864
  }
30537
30865
 
30538
30866
  // plugins/kxm/src/logger.ts
30539
- import { appendFileSync, existsSync as existsSync15, mkdirSync as mkdirSync8, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
30867
+ import { appendFileSync, existsSync as existsSync16, mkdirSync as mkdirSync8, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
30540
30868
  import { dirname as dirname10 } from "node:path";
30541
30869
  var LOG_LEVEL_PRIORITY = {
30542
30870
  debug: 10,
@@ -30574,7 +30902,7 @@ function redactLogValue(val, key) {
30574
30902
  function rotateLogFiles(filePath, maxFiles) {
30575
30903
  for (let i = maxFiles; i >= 1; i--) {
30576
30904
  const current = `${filePath}.${i}`;
30577
- if (existsSync15(current)) {
30905
+ if (existsSync16(current)) {
30578
30906
  if (i >= maxFiles) {
30579
30907
  try {
30580
30908
  unlinkSync2(current);
@@ -30588,7 +30916,7 @@ function rotateLogFiles(filePath, maxFiles) {
30588
30916
  }
30589
30917
  }
30590
30918
  }
30591
- if (existsSync15(filePath)) {
30919
+ if (existsSync16(filePath)) {
30592
30920
  try {
30593
30921
  renameSync4(filePath, `${filePath}.1`);
30594
30922
  } catch {
@@ -30605,7 +30933,7 @@ function createLogger(options) {
30605
30933
  const shouldStdout = options.stdout ?? !isDaemon;
30606
30934
  const correlationDefaults = options.correlation ?? {};
30607
30935
  let currentSize = 0;
30608
- if (filePath && existsSync15(filePath)) {
30936
+ if (filePath && existsSync16(filePath)) {
30609
30937
  try {
30610
30938
  currentSize = statSync5(filePath).size;
30611
30939
  } catch {
@@ -30686,7 +31014,7 @@ function createLogger(options) {
30686
31014
 
30687
31015
  // plugins/kxm/src/runtime-supervisor.ts
30688
31016
  function kxmSupervisorTokenFile(paths) {
30689
- return join18(paths.runtimeDir, "supervisor.token");
31017
+ return join19(paths.runtimeDir, "supervisor.token");
30690
31018
  }
30691
31019
  function publishKxmSupervisorToken(paths, token) {
30692
31020
  const file = kxmSupervisorTokenFile(paths);
@@ -30714,7 +31042,7 @@ function readKxmSupervisorToken(paths) {
30714
31042
  if (stat.isSymbolicLink() || !stat.isFile()) {
30715
31043
  throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
30716
31044
  }
30717
- const token = readFileSync13(file, "utf8").trim();
31045
+ const token = readFileSync14(file, "utf8").trim();
30718
31046
  return token.length >= 32 ? token : void 0;
30719
31047
  }
30720
31048
  function processAlive(pid) {
@@ -30728,11 +31056,11 @@ function processAlive(pid) {
30728
31056
  var HEARTBEAT_STALE_MS = 15e3;
30729
31057
  var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
30730
31058
  function supervisorErrorFile(paths) {
30731
- return join18(paths.runtimeDir, "supervisor.error");
31059
+ return join19(paths.runtimeDir, "supervisor.error");
30732
31060
  }
30733
31061
  function clearSupervisorError(paths) {
30734
31062
  const file = supervisorErrorFile(paths);
30735
- if (existsSync16(file)) rmSync4(file, { force: true });
31063
+ if (existsSync17(file)) rmSync4(file, { force: true });
30736
31064
  }
30737
31065
  function recordSupervisorError(paths, message) {
30738
31066
  try {
@@ -30749,7 +31077,7 @@ function readRecentSupervisorError(paths) {
30749
31077
  const ageMs = Date.now() - stat.mtimeMs;
30750
31078
  if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
30751
31079
  try {
30752
- return readFileSync13(file, "utf8").trim();
31080
+ return readFileSync14(file, "utf8").trim();
30753
31081
  } catch {
30754
31082
  return void 0;
30755
31083
  }
@@ -30788,7 +31116,7 @@ function supervisorStatusOf(record2) {
30788
31116
  };
30789
31117
  }
30790
31118
  function kxmSupervisorStatus(paths, options = {}) {
30791
- if (!existsSync16(paths.registryDb)) return { running: false };
31119
+ if (!existsSync17(paths.registryDb)) return { running: false };
30792
31120
  if (options.readOnly) {
30793
31121
  const database = openReadOnlyDatabase(paths.registryDb);
30794
31122
  try {
@@ -30854,7 +31182,7 @@ async function ensureKxmSupervisor(options = {}) {
30854
31182
  throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
30855
31183
  }
30856
31184
  clearSupervisorError(paths);
30857
- const scriptPath = join18(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
31185
+ const scriptPath = join19(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
30858
31186
  const spawnImpl = options.spawnImpl ?? ((script, env) => {
30859
31187
  const child = spawn3(process.execPath, [script], {
30860
31188
  detached: true,
@@ -31077,7 +31405,7 @@ function syncFailureText(error) {
31077
31405
  return `${code ? `${code}: ` : ""}${message}`.replace(/(kxm_[A-Za-z0-9_]+|[A-Za-z0-9._-]{40,})/g, "[redacted]").slice(0, 300);
31078
31406
  }
31079
31407
  function runtimeSupervisorLogFile(paths) {
31080
- return join18(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
31408
+ return join19(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
31081
31409
  }
31082
31410
  async function startKxmRuntimeSupervisor(options = {}) {
31083
31411
  const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
@@ -31202,8 +31530,8 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
31202
31530
  openRunIds = unsettledRunIds(existing2);
31203
31531
  } else {
31204
31532
  const registration = registry.projectByRoot(projectRoot);
31205
- const eventsPath = join18(paths.projectsDir, registration?.projectKey ?? projectRuntimeKey(projectRoot), "run-events.db");
31206
- if (registration && existsSync16(eventsPath)) {
31533
+ const eventsPath = join19(paths.projectsDir, registration?.projectKey ?? projectRuntimeKey(projectRoot), "run-events.db");
31534
+ if (registration && existsSync17(eventsPath)) {
31207
31535
  const store = new KxmRunEventStore(eventsPath);
31208
31536
  try {
31209
31537
  openRunIds = store.runsForProject(registration.projectId, 1e4).filter((run) => !SETTLED_RUN_STATUS.has(run.status)).map((run) => run.runId);