@kontextmind/kxm 0.7.165 → 0.7.167

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 (41) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/docs/README.md +1 -0
  4. package/docs/architecture/hosted-direction.md +9 -4
  5. package/docs/architecture/inventory.md +1 -0
  6. package/docs/concepts/trust-model.md +1 -1
  7. package/docs/contributing/decisions.md +153 -0
  8. package/docs/contributing/learnings.md +54 -53
  9. package/docs/contributing/operating-rules.md +19 -6
  10. package/docs/glossary.md +2 -2
  11. package/docs/operations/troubleshooting.md +2 -2
  12. package/docs/operations.md +62 -8
  13. package/docs/reference/cli-reference.md +11 -11
  14. package/docs/reference/config-reference.md +36 -11
  15. package/docs/reference/configuration.md +2 -2
  16. package/docs/reference/tools.md +1 -1
  17. package/docs/start/quickstart-claude-code.md +2 -2
  18. package/package.json +1 -1
  19. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  20. package/plugins/kxm/README.md +3 -3
  21. package/plugins/kxm/dist/claude-hook.js +417 -66
  22. package/plugins/kxm/dist/cli.js +1399 -900
  23. package/plugins/kxm/dist/extension.js +399 -64
  24. package/plugins/kxm/dist/mcp-server.js +622 -135
  25. package/plugins/kxm/dist/runtime-supervisor.js +668 -166
  26. package/plugins/kxm/dist/runtime.js +713 -211
  27. package/plugins/kxm/dist/server.js +466 -58
  28. package/plugins/kxm/package.json +1 -1
  29. package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +15 -7
  30. package/plugins/kxm/src/cli/hub.ts +80 -21
  31. package/plugins/kxm/src/cli/types.ts +8 -1
  32. package/plugins/kxm/src/cli.ts +41 -7
  33. package/plugins/kxm/src/config.ts +246 -3
  34. package/plugins/kxm/src/extension.ts +8 -7
  35. package/plugins/kxm/src/hub-autostart.ts +20 -0
  36. package/plugins/kxm/src/hub-env.ts +83 -31
  37. package/plugins/kxm/src/hub-identity.ts +337 -0
  38. package/plugins/kxm/src/mcp-server.ts +17 -15
  39. package/plugins/kxm/src/project-name.ts +6 -47
  40. package/plugins/kxm/src/server.ts +22 -4
  41. package/scripts/kxm-hub.mjs +5 -0
@@ -2986,7 +2986,7 @@ var require_compile = __commonJS({
2986
2986
  const schOrFunc = root.refs[ref];
2987
2987
  if (schOrFunc)
2988
2988
  return schOrFunc;
2989
- let _sch = resolve13.call(this, root, ref);
2989
+ let _sch = resolve15.call(this, root, ref);
2990
2990
  if (_sch === void 0) {
2991
2991
  const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
2992
2992
  const { schemaId } = this.opts;
@@ -3013,7 +3013,7 @@ var require_compile = __commonJS({
3013
3013
  function sameSchemaEnv(s1, s2) {
3014
3014
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3015
3015
  }
3016
- function resolve13(root, ref) {
3016
+ function resolve15(root, ref) {
3017
3017
  let sch;
3018
3018
  while (typeof (sch = this.refs[ref]) == "string")
3019
3019
  ref = sch;
@@ -3838,7 +3838,7 @@ var require_fast_uri = __commonJS({
3838
3838
  }
3839
3839
  return uri;
3840
3840
  }
3841
- function resolve13(baseURI, relativeURI, options) {
3841
+ function resolve15(baseURI, relativeURI, options) {
3842
3842
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3843
3843
  const {
3844
3844
  parsed: baseParsed,
@@ -4200,7 +4200,7 @@ var require_fast_uri = __commonJS({
4200
4200
  var fastUri = {
4201
4201
  SCHEMES,
4202
4202
  normalize,
4203
- resolve: resolve13,
4203
+ resolve: resolve15,
4204
4204
  resolveComponent,
4205
4205
  equal,
4206
4206
  serialize,
@@ -16094,7 +16094,7 @@ function defaultSpawn(command, args, options) {
16094
16094
  if (options.signal?.aborted) {
16095
16095
  return Promise.resolve({ stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") });
16096
16096
  }
16097
- return new Promise((resolve13) => {
16097
+ return new Promise((resolve15) => {
16098
16098
  const stdout = [];
16099
16099
  const stderr = [];
16100
16100
  let outputBytes = 0;
@@ -16125,7 +16125,7 @@ function defaultSpawn(command, args, options) {
16125
16125
  const started = Boolean(child?.pid);
16126
16126
  if (started && !observedChildExit) error ??= new Error("process_exit_unobserved");
16127
16127
  const unverifiedDescendants = stopping || started && !observedChildExit;
16128
- resolve13({
16128
+ resolve15({
16129
16129
  stdout: Buffer.concat(stdout).toString("utf8"),
16130
16130
  stderr: Buffer.concat(stderr).toString("utf8"),
16131
16131
  code,
@@ -18146,8 +18146,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
18146
18146
  const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
18147
18147
  if (maxWriteRepositories > writable) issues.push(issue3("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
18148
18148
  }
18149
- const join25 = objectValue(step.join);
18150
- const minimumPassed = join25 && typeof join25.minimumPassed === "number" ? join25.minimumPassed : void 0;
18149
+ const join27 = objectValue(step.join);
18150
+ const minimumPassed = join27 && typeof join27.minimumPassed === "number" ? join27.minimumPassed : void 0;
18151
18151
  if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue3("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
18152
18152
  const distinctBy = names(assignment?.distinctBy);
18153
18153
  if (distinctBy.length > 0) {
@@ -23218,7 +23218,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
23218
23218
  const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
23219
23219
  const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
23220
23220
  const assignments = compileAssignments(step, id, agent, sink);
23221
- const join25 = compileJoin(step, id, sink);
23221
+ const join27 = compileJoin(step, id, sink);
23222
23222
  const requiredEvidence = compileEvidence(step, id, sink);
23223
23223
  const transitions = compileTransitions(step, id, index, stepIndex, sink);
23224
23224
  const outcomes = Object.keys(transitions).sort(compareCodeUnits5);
@@ -23246,7 +23246,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
23246
23246
  transitions: orderedTransitions,
23247
23247
  requiresPlanHash: requirePlanHash.includes(id),
23248
23248
  assignments,
23249
- join: join25
23249
+ join: join27
23250
23250
  };
23251
23251
  if (kind === "agent" || kind === "moa") {
23252
23252
  if (!agent) return void 0;
@@ -23296,15 +23296,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
23296
23296
  };
23297
23297
  }
23298
23298
  function compileJoin(step, stepId, sink) {
23299
- const join25 = objectValue2(step.join);
23300
- if (!join25) return { strategy: "all" };
23301
- const declared = stringValue2(join25.strategy);
23299
+ const join27 = objectValue2(step.join);
23300
+ if (!join27) return { strategy: "all" };
23301
+ const declared = stringValue2(join27.strategy);
23302
23302
  const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
23303
- const minimumPassed = compileOptionalCount(join25.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
23303
+ const minimumPassed = compileOptionalCount(join27.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
23304
23304
  const compiled = {
23305
23305
  strategy,
23306
23306
  ...minimumPassed !== void 0 ? { minimumPassed } : {},
23307
- ...typeof join25.cancelRemaining === "boolean" ? { cancelRemaining: join25.cancelRemaining } : {}
23307
+ ...typeof join27.cancelRemaining === "boolean" ? { cancelRemaining: join27.cancelRemaining } : {}
23308
23308
  };
23309
23309
  return compiled;
23310
23310
  }
@@ -24657,12 +24657,12 @@ function enqueueKxmScheduledRun(storePath, runId, configRevision, bound, start)
24657
24657
  if (owner.admitted.has(runId) || owner.queue.some((item) => item.runId === runId)) {
24658
24658
  return Promise.reject(runtimeError("run_busy", runId, `run ${runId} is already admitted or queued`));
24659
24659
  }
24660
- return new Promise((resolve13, reject) => {
24660
+ return new Promise((resolve15, reject) => {
24661
24661
  owner.queue.push({
24662
24662
  runId,
24663
24663
  configRevision,
24664
24664
  bound,
24665
- start: (token) => start(token).then(resolve13, reject),
24665
+ start: (token) => start(token).then(resolve15, reject),
24666
24666
  fail: (error) => reject(error)
24667
24667
  });
24668
24668
  pump(storePath, owner);
@@ -25188,9 +25188,9 @@ function assertKxmConfigError(error) {
25188
25188
  // plugins/kxm/src/runtime-supervisor.ts
25189
25189
  import { spawn as spawn3 } from "node:child_process";
25190
25190
  import { createHash as createHash16, createHmac, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
25191
- import { chmodSync as chmodSync2, existsSync as existsSync18, lstatSync as lstatSync6, mkdirSync as mkdirSync9, readFileSync as readFileSync15, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "node:fs";
25191
+ import { chmodSync as chmodSync2, existsSync as existsSync20, lstatSync as lstatSync6, mkdirSync as mkdirSync10, readFileSync as readFileSync17, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
25192
25192
  import { createServer } from "node:http";
25193
- import { dirname as dirname11, isAbsolute as isAbsolute8, join as join20 } from "node:path";
25193
+ import { dirname as dirname13, isAbsolute as isAbsolute8, join as join22 } from "node:path";
25194
25194
 
25195
25195
  // plugins/kxm/src/oneshot-evidence.ts
25196
25196
  import { createHash as createHash10, randomUUID as randomUUID3 } from "node:crypto";
@@ -25521,38 +25521,344 @@ function loadPriceCatalogForEstimate(options) {
25521
25521
  // plugins/kxm/src/engine.ts
25522
25522
  var import_yaml11 = __toESM(require_dist(), 1);
25523
25523
  import { createHash as createHash15, randomBytes as randomBytes2, timingSafeEqual } from "node:crypto";
25524
- import { existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
25525
- import { join as join17 } from "node:path";
25524
+ import { existsSync as existsSync15, readFileSync as readFileSync13 } from "node:fs";
25525
+ import { join as join18 } from "node:path";
25526
25526
 
25527
25527
  // plugins/kxm/src/routes.ts
25528
25528
  var import_yaml7 = __toESM(require_dist(), 1);
25529
- import { existsSync as existsSync10, readFileSync as readFileSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync6 } from "node:fs";
25530
- import { join as join11 } from "node:path";
25529
+ import { existsSync as existsSync11, readFileSync as readFileSync9, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
25530
+ import { join as join12 } from "node:path";
25531
25531
 
25532
25532
  // plugins/kxm/src/role.ts
25533
25533
  var import_yaml6 = __toESM(require_dist(), 1);
25534
25534
 
25535
25535
  // plugins/kxm/src/config.ts
25536
25536
  var import_yaml5 = __toESM(require_dist(), 1);
25537
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
25538
+ import { tmpdir, homedir as homedir2 } from "node:os";
25539
+ import { dirname as dirname6, join as join11, resolve as resolve7 } from "node:path";
25540
+ var KXM_CONFIG_SCHEMA = "kxm.config.v1";
25541
+ var KxmHubConfigError = class extends Error {
25542
+ code = "hub_config_invalid";
25543
+ constructor(message) {
25544
+ super(message);
25545
+ this.name = "KxmHubConfigError";
25546
+ }
25547
+ };
25548
+ var HUB_ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
25549
+ var HUB_OP_REF = /^op:\/\/\S+\/\S+\/\S+$/;
25550
+ var LITERAL_SECRET_KEY = /^(token|secret|password|authToken|auth_token|apiKey|api_key|api_token|bearer|credential|access_token)$/i;
25551
+ function isHubKeyEnvName(value) {
25552
+ return HUB_ENV_NAME.test(value);
25553
+ }
25554
+ function isHubOpReference(value) {
25555
+ return HUB_OP_REF.test(value);
25556
+ }
25557
+ var IMPROVEMENT_PROMOTION_POLICIES = ["manual_pr", "critic_quorum", "auto_threshold"];
25558
+ var DEFAULT_KXM_CONFIG = {
25559
+ schema: KXM_CONFIG_SCHEMA,
25560
+ user: {
25561
+ theme: "dark",
25562
+ preferredCritics: ["reviewer-arch", "reviewer-cli"],
25563
+ tokenBudget: 16e3
25564
+ },
25565
+ defaults: {
25566
+ workflow: "software-engineering/feature-implementation",
25567
+ harness: "pi"
25568
+ },
25569
+ dash: {
25570
+ defaultScreen: "agents",
25571
+ refreshIntervalMs: 1e3,
25572
+ autoOpen: false
25573
+ },
25574
+ sync: {
25575
+ defaultTracker: "none"
25576
+ },
25577
+ hub: {
25578
+ autoStart: "background"
25579
+ },
25580
+ improvement: {
25581
+ promotionPolicy: "manual_pr",
25582
+ telemetryHalfLifeDays: 14,
25583
+ autoThreshold: {
25584
+ minRuns: 10,
25585
+ minPassRate: 0.95,
25586
+ minCostSavings: 0.5
25587
+ }
25588
+ },
25589
+ routing: {
25590
+ shadowExecution: {
25591
+ enabled: false,
25592
+ sampleRate: 0.05,
25593
+ candidateModels: []
25594
+ },
25595
+ circuitBreaker: {
25596
+ mode: "soft_demotion",
25597
+ failureThreshold: 3,
25598
+ windowSeconds: 3600,
25599
+ cooldownSeconds: 1800,
25600
+ penaltyMultiplier: 5
25601
+ }
25602
+ },
25603
+ telemetry: {
25604
+ federated: true,
25605
+ anonymize: true
25606
+ }
25607
+ };
25608
+ function userConfigDirectory(overrideDir) {
25609
+ if (overrideDir) return resolve7(overrideDir);
25610
+ return resolve7(process.env.KXM_USER_CONFIG_DIR?.trim() || join11(homedir2(), ".config", "kxm"));
25611
+ }
25612
+ function repoConfigDirectory(repoRoot) {
25613
+ return resolve7(repoRoot, ".kxm");
25614
+ }
25615
+ function deepMerge(target, source) {
25616
+ const result = { ...target };
25617
+ for (const [key, val] of Object.entries(source)) {
25618
+ if (val && typeof val === "object" && !Array.isArray(val)) {
25619
+ const existing = result[key] && typeof result[key] === "object" && !Array.isArray(result[key]) ? result[key] : {};
25620
+ result[key] = deepMerge(existing, val);
25621
+ } else if (val !== void 0) {
25622
+ result[key] = val;
25623
+ }
25624
+ }
25625
+ return result;
25626
+ }
25627
+ function literalSecretMessage(path) {
25628
+ return `refusing literal hub token at ${path}: store an op:// reference (key.op) or an environment variable name (key.env), never the token`;
25629
+ }
25630
+ function rejectLiteralHubSecrets(value, path) {
25631
+ if (Array.isArray(value)) {
25632
+ value.forEach((item, index) => rejectLiteralHubSecrets(item, `${path}[${index}]`));
25633
+ return;
25634
+ }
25635
+ if (!value || typeof value !== "object") return;
25636
+ for (const [key, child] of Object.entries(value)) {
25637
+ const childPath = `${path}.${key}`;
25638
+ if (typeof child === "string" && (key === "key" || LITERAL_SECRET_KEY.test(key))) {
25639
+ throw new KxmHubConfigError(literalSecretMessage(childPath));
25640
+ }
25641
+ if (child && typeof child === "object") rejectLiteralHubSecrets(child, childPath);
25642
+ }
25643
+ }
25644
+ function parseKeyRef(raw, path) {
25645
+ if (raw === void 0) return void 0;
25646
+ if (typeof raw === "string") throw new KxmHubConfigError(literalSecretMessage(path));
25647
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25648
+ throw new KxmHubConfigError(`${path} must be a key reference with op and/or env, never a token`);
25649
+ }
25650
+ const row = raw;
25651
+ for (const key of Object.keys(row)) {
25652
+ if (key !== "op" && key !== "env") {
25653
+ throw new KxmHubConfigError(literalSecretMessage(`${path}.${key}`));
25654
+ }
25655
+ }
25656
+ const ref = {};
25657
+ if (row.op !== void 0) {
25658
+ if (typeof row.op !== "string" || !isHubOpReference(row.op)) {
25659
+ throw new KxmHubConfigError(`${path}.op must be an op://vault/item/field reference, not a token`);
25660
+ }
25661
+ ref.op = row.op;
25662
+ }
25663
+ if (row.env !== void 0) {
25664
+ if (typeof row.env !== "string" || !isHubKeyEnvName(row.env)) {
25665
+ throw new KxmHubConfigError(`${path}.env must be an environment variable name, not a token`);
25666
+ }
25667
+ ref.env = row.env;
25668
+ }
25669
+ if (!ref.op && !ref.env) throw new KxmHubConfigError(`${path} needs key.op, key.env, or both`);
25670
+ return ref;
25671
+ }
25672
+ function parseEndpoint(raw, path) {
25673
+ if (raw === void 0) return void 0;
25674
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25675
+ throw new KxmHubConfigError(`${path} must be an object with url, project, and key`);
25676
+ }
25677
+ const row = raw;
25678
+ const endpoint = {};
25679
+ if (row.url !== void 0) {
25680
+ if (typeof row.url !== "string" || !isHubUrl(row.url)) {
25681
+ throw new KxmHubConfigError(`${path}.url must be an http or https URL without credentials, query, or fragment`);
25682
+ }
25683
+ endpoint.url = row.url.replace(/\/$/, "");
25684
+ }
25685
+ if (row.project !== void 0) {
25686
+ if (typeof row.project !== "string" || !isHubProjectId(row.project)) {
25687
+ throw new KxmHubConfigError(`${path}.project must be a single-line project id, not a token`);
25688
+ }
25689
+ endpoint.project = row.project.trim();
25690
+ }
25691
+ const key = parseKeyRef(row.key, `${path}.key`);
25692
+ if (key) endpoint.key = key;
25693
+ for (const name of Object.keys(row)) {
25694
+ if (name !== "url" && name !== "project" && name !== "key") {
25695
+ if (typeof row[name] === "string") throw new KxmHubConfigError(literalSecretMessage(`${path}.${name}`));
25696
+ throw new KxmHubConfigError(`${path}.${name} is not a hub endpoint field`);
25697
+ }
25698
+ }
25699
+ return endpoint;
25700
+ }
25701
+ function isHubUrl(raw) {
25702
+ try {
25703
+ const parsed = new URL(raw);
25704
+ return (parsed.protocol === "http:" || parsed.protocol === "https:") && parsed.username === "" && parsed.password === "" && parsed.search === "" && parsed.hash === "" && !raw.includes("?") && !raw.includes("#");
25705
+ } catch {
25706
+ return false;
25707
+ }
25708
+ }
25709
+ function isHubProjectId(raw) {
25710
+ const value = raw.trim();
25711
+ return value.length > 0 && value.length <= 200 && !/[\s\r\n]/.test(value);
25712
+ }
25713
+ function parseProjectMap(raw) {
25714
+ if (raw === void 0) return void 0;
25715
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25716
+ throw new KxmHubConfigError("hub.projects must be a map of project id to key reference, never a token");
25717
+ }
25718
+ const projects = {};
25719
+ for (const [project, value] of Object.entries(raw)) {
25720
+ if (!isHubProjectId(project)) {
25721
+ throw new KxmHubConfigError(`hub.projects key ${JSON.stringify(project)} must be a project id, not a token`);
25722
+ }
25723
+ const ref = parseKeyRef(value, `hub.projects.${project}`);
25724
+ if (!ref) throw new KxmHubConfigError(`hub.projects.${project} needs an op:// reference or an environment variable name`);
25725
+ projects[project.trim()] = ref;
25726
+ }
25727
+ return projects;
25728
+ }
25729
+ function normalizeHubConfig(raw) {
25730
+ const autoStart = raw?.autoStart;
25731
+ const hub = {
25732
+ autoStart: autoStart === "off" || autoStart === "background" ? autoStart : DEFAULT_KXM_CONFIG.hub.autoStart
25733
+ };
25734
+ if (raw === void 0) return hub;
25735
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25736
+ throw new KxmHubConfigError("hub must be an object");
25737
+ }
25738
+ rejectLiteralHubSecrets(raw, "hub");
25739
+ const row = raw;
25740
+ if (row.mode !== void 0) {
25741
+ if (row.mode !== "local" && row.mode !== "cloud") {
25742
+ throw new KxmHubConfigError("hub.mode must be local or cloud");
25743
+ }
25744
+ hub.mode = row.mode;
25745
+ }
25746
+ const local = parseEndpoint(row.local, "hub.local");
25747
+ const cloud = parseEndpoint(row.cloud, "hub.cloud");
25748
+ const projects = parseProjectMap(row.projects);
25749
+ if (local) hub.local = local;
25750
+ if (cloud) hub.cloud = cloud;
25751
+ if (projects && Object.keys(projects).length > 0) hub.projects = projects;
25752
+ return hub;
25753
+ }
25754
+ function findConfigRoot(start) {
25755
+ let dir = resolve7(start);
25756
+ for (; ; ) {
25757
+ if (existsSync10(join11(dir, ".kxm", "project.yaml")) || existsSync10(join11(dir, ".kxm", "config.yaml"))) return dir;
25758
+ const parent = dirname6(dir);
25759
+ if (parent === dir) return resolve7(start);
25760
+ dir = parent;
25761
+ }
25762
+ }
25763
+ function userConfigDirForEnv(env) {
25764
+ const explicit = env.KXM_USER_CONFIG_DIR?.trim();
25765
+ if (explicit) return explicit;
25766
+ if (env === process.env) return void 0;
25767
+ return join11(tmpdir(), "kxm-no-user-config");
25768
+ }
25769
+ function loadHubSettings(start, env = process.env) {
25770
+ const userConfigDir = userConfigDirForEnv(env);
25771
+ return loadKxmConfig(findConfigRoot(start), userConfigDir === void 0 ? {} : { userConfigDir }).hub;
25772
+ }
25773
+ function recordOf(raw) {
25774
+ return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
25775
+ }
25776
+ function finiteNumber(value) {
25777
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
25778
+ }
25779
+ function normalizeImprovementConfig(raw) {
25780
+ const value = recordOf(raw);
25781
+ const threshold = recordOf(value.autoThreshold);
25782
+ const policy = value.promotionPolicy;
25783
+ const halfLife = finiteNumber(value.telemetryHalfLifeDays);
25784
+ const minRuns = finiteNumber(threshold.minRuns);
25785
+ const minPassRate = finiteNumber(threshold.minPassRate);
25786
+ const minCostSavings = finiteNumber(threshold.minCostSavings);
25787
+ return {
25788
+ promotionPolicy: IMPROVEMENT_PROMOTION_POLICIES.includes(policy) ? policy : "manual_pr",
25789
+ telemetryHalfLifeDays: halfLife !== void 0 && halfLife > 0 && halfLife <= 3650 ? halfLife : 14,
25790
+ autoThreshold: {
25791
+ minRuns: minRuns !== void 0 && Number.isInteger(minRuns) && minRuns >= 1 && minRuns <= 1e6 ? minRuns : 10,
25792
+ minPassRate: minPassRate !== void 0 && minPassRate >= 0 && minPassRate <= 1 ? minPassRate : 0.95,
25793
+ minCostSavings: minCostSavings !== void 0 && minCostSavings >= 0 ? minCostSavings : 0.5
25794
+ }
25795
+ };
25796
+ }
25797
+ function loadKxmConfig(repoRoot = process.cwd(), options = {}) {
25798
+ const userDir = userConfigDirectory(options.userConfigDir);
25799
+ const userConfigFile = join11(userDir, "config.yaml");
25800
+ const repoDir = repoConfigDirectory(repoRoot);
25801
+ const repoConfigFile = join11(repoDir, "config.yaml");
25802
+ let userRaw = {};
25803
+ let userLoadedPath;
25804
+ if (existsSync10(userConfigFile)) {
25805
+ try {
25806
+ const text = readFileSync8(userConfigFile, "utf8");
25807
+ userRaw = (0, import_yaml5.parse)(text) ?? {};
25808
+ userLoadedPath = userConfigFile;
25809
+ } catch (error) {
25810
+ throw new Error(`invalid user config YAML at ${userConfigFile}`, { cause: error });
25811
+ }
25812
+ }
25813
+ let repoRaw = {};
25814
+ let repoLoadedPath;
25815
+ if (existsSync10(repoConfigFile)) {
25816
+ try {
25817
+ const text = readFileSync8(repoConfigFile, "utf8");
25818
+ repoRaw = (0, import_yaml5.parse)(text) ?? {};
25819
+ repoLoadedPath = repoConfigFile;
25820
+ } catch (error) {
25821
+ throw new Error(`invalid project config YAML at ${repoConfigFile}`, { cause: error });
25822
+ }
25823
+ }
25824
+ const baseCopy = JSON.parse(JSON.stringify(DEFAULT_KXM_CONFIG));
25825
+ const mergedUser = deepMerge(baseCopy, userRaw);
25826
+ const mergedAll = deepMerge(mergedUser, repoRaw);
25827
+ return {
25828
+ schema: KXM_CONFIG_SCHEMA,
25829
+ user: mergedAll.user ?? {},
25830
+ defaults: mergedAll.defaults ?? {},
25831
+ dash: mergedAll.dash ?? {},
25832
+ sync: mergedAll.sync ?? {},
25833
+ hub: normalizeHubConfig(mergedAll.hub),
25834
+ improvement: normalizeImprovementConfig(mergedAll.improvement),
25835
+ routing: mergedAll.routing ?? DEFAULT_KXM_CONFIG.routing,
25836
+ telemetry: mergedAll.telemetry ?? DEFAULT_KXM_CONFIG.telemetry,
25837
+ loadedFrom: {
25838
+ userConfigPath: userLoadedPath,
25839
+ repoConfigPath: repoLoadedPath
25840
+ }
25841
+ };
25842
+ }
25537
25843
 
25538
25844
  // plugins/kxm/src/routes.ts
25539
25845
  var RETIRED_POLICY = ".kxm/producers.yaml";
25540
25846
  var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [] });
25541
25847
  function loadRoutePolicy(root) {
25542
- if (existsSync10(join11(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
25543
- const path = join11(root, ".kxm", "routes.yaml");
25544
- if (!existsSync10(path)) return empty();
25545
- const value = (0, import_yaml7.parse)(readFileSync8(path, "utf8"));
25848
+ if (existsSync11(join12(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
25849
+ const path = join12(root, ".kxm", "routes.yaml");
25850
+ if (!existsSync11(path)) return empty();
25851
+ const value = (0, import_yaml7.parse)(readFileSync9(path, "utf8"));
25546
25852
  if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
25547
25853
  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") : [] };
25548
25854
  }
25549
25855
  function listRoleBindings(root) {
25550
- const dir = join11(root, ".kxm", "roles");
25856
+ const dir = join12(root, ".kxm", "roles");
25551
25857
  const result = {};
25552
- if (!existsSync10(dir)) return result;
25858
+ if (!existsSync11(dir)) return result;
25553
25859
  for (const file of readdirSync6(dir).filter((name) => name.endsWith(".yaml"))) {
25554
25860
  const role = file.slice(0, -5);
25555
- const value = (0, import_yaml7.parse)(readFileSync8(join11(dir, file), "utf8"));
25861
+ const value = (0, import_yaml7.parse)(readFileSync9(join12(dir, file), "utf8"));
25556
25862
  result[role] = (value.roster ?? []).map((entry) => entry.route).filter((route) => typeof route === "string");
25557
25863
  }
25558
25864
  return result;
@@ -25560,8 +25866,8 @@ function listRoleBindings(root) {
25560
25866
 
25561
25867
  // plugins/kxm/src/route-fallback.ts
25562
25868
  var import_yaml8 = __toESM(require_dist(), 1);
25563
- import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync9 } from "node:fs";
25564
- import { join as join12 } from "node:path";
25869
+ import { existsSync as existsSync12, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "node:fs";
25870
+ import { join as join13 } from "node:path";
25565
25871
 
25566
25872
  // plugins/kxm/src/route-switch.ts
25567
25873
  var WALKABLE_CLASSES = ["rate_limit", "transport", "provider_unavailable", "context_overflow"];
@@ -25761,9 +26067,9 @@ ${lines.join("\n")}`;
25761
26067
  ${block}`;
25762
26068
  }
25763
26069
  function readYaml(file) {
25764
- if (!existsSync11(file)) return void 0;
26070
+ if (!existsSync12(file)) return void 0;
25765
26071
  try {
25766
- const parsed = (0, import_yaml8.parse)(readFileSync9(file, "utf8"));
26072
+ const parsed = (0, import_yaml8.parse)(readFileSync10(file, "utf8"));
25767
26073
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
25768
26074
  return parsed;
25769
26075
  } catch {
@@ -25775,7 +26081,7 @@ function stringList(value) {
25775
26081
  }
25776
26082
  function readSelectors(projectRoot, value) {
25777
26083
  if (!Array.isArray(value)) return [];
25778
- const modelsDir = join12(projectRoot, ".kxm", "models");
26084
+ const modelsDir = join13(projectRoot, ".kxm", "models");
25779
26085
  const selectors = [];
25780
26086
  for (const item of value) {
25781
26087
  if (!item || typeof item !== "object" || Array.isArray(item)) continue;
@@ -25794,9 +26100,9 @@ function readSelectors(projectRoot, value) {
25794
26100
  return selectors;
25795
26101
  }
25796
26102
  function loadChainModel(projectRoot, routeId2, writerIds) {
25797
- const modelsDir = join12(projectRoot, ".kxm", "models");
26103
+ const modelsDir = join13(projectRoot, ".kxm", "models");
25798
26104
  const fileId = findYamlBasename(modelsDir, routeId2, "route") ?? routeId2;
25799
- const doc = readYaml(join12(modelsDir, `${fileId}.yaml`));
26105
+ const doc = readYaml(join13(modelsDir, `${fileId}.yaml`));
25800
26106
  if (!doc || doc.schema !== "kxm.model.v2") return void 0;
25801
26107
  const harness = typeof doc.harness === "string" ? doc.harness : "";
25802
26108
  const model = typeof doc.model === "string" ? doc.model : "";
@@ -25823,7 +26129,7 @@ function loadChainModel(projectRoot, routeId2, writerIds) {
25823
26129
  };
25824
26130
  }
25825
26131
  function canonicalRoster(projectRoot, entries) {
25826
- const modelsDir = join12(projectRoot, ".kxm", "models");
26132
+ const modelsDir = join13(projectRoot, ".kxm", "models");
25827
26133
  return entries.map((entry) => {
25828
26134
  const route = findYamlBasename(modelsDir, entry.route, "route") ?? entry.route;
25829
26135
  return entry.effort ? { route, effort: entry.effort } : { route };
@@ -25842,10 +26148,10 @@ function rosterEntries(doc) {
25842
26148
  return entries;
25843
26149
  }
25844
26150
  function loadModelsFor(projectRoot, roster, writerIds) {
25845
- const modelsDir = join12(projectRoot, ".kxm", "models");
26151
+ const modelsDir = join13(projectRoot, ".kxm", "models");
25846
26152
  const wanted = /* @__PURE__ */ new Set();
25847
26153
  for (const entry of roster) wanted.add(entry.route);
25848
- if (existsSync11(modelsDir)) {
26154
+ if (existsSync12(modelsDir)) {
25849
26155
  for (const name of readdirSync7(modelsDir)) {
25850
26156
  if (!name.endsWith(".yaml") || name === "inventory.yaml") continue;
25851
26157
  wanted.add(name.slice(0, -5));
@@ -25862,12 +26168,12 @@ function loadModelsFor(projectRoot, roster, writerIds) {
25862
26168
  return models;
25863
26169
  }
25864
26170
  function criticVendors(projectRoot, writerIds) {
25865
- const dir = join12(projectRoot, ".kxm", "roles");
25866
- if (!existsSync11(dir)) return [];
26171
+ const dir = join13(projectRoot, ".kxm", "roles");
26172
+ if (!existsSync12(dir)) return [];
25867
26173
  const vendors = [];
25868
26174
  for (const name of readdirSync7(dir)) {
25869
26175
  if (!name.endsWith(".yaml")) continue;
25870
- const doc = readYaml(join12(dir, name));
26176
+ const doc = readYaml(join13(dir, name));
25871
26177
  const purpose = doc?.purpose;
25872
26178
  if (purpose !== "reviewer-arch" && purpose !== "reviewer-cli") continue;
25873
26179
  const first = rosterEntries(doc)[0];
@@ -25878,12 +26184,12 @@ function criticVendors(projectRoot, writerIds) {
25878
26184
  return vendors;
25879
26185
  }
25880
26186
  function loadAgentFallback(projectRoot, agentId, options) {
25881
- const agentsDir = join12(projectRoot, ".kxm", "agents");
26187
+ const agentsDir = join13(projectRoot, ".kxm", "agents");
25882
26188
  const agentFile = findYamlBasename(agentsDir, agentId, "agent") ?? agentId;
25883
- const agent = readYaml(join12(agentsDir, `${agentFile}.yaml`));
26189
+ const agent = readYaml(join13(agentsDir, `${agentFile}.yaml`));
25884
26190
  const roleId = typeof agent?.role === "string" ? agent.role : "";
25885
26191
  if (!roleId) return void 0;
25886
- const role = readYaml(join12(projectRoot, ".kxm", "roles", `${roleId}.yaml`));
26192
+ const role = readYaml(join13(projectRoot, ".kxm", "roles", `${roleId}.yaml`));
25887
26193
  if (!role) return void 0;
25888
26194
  const policyRecord = role.policy && typeof role.policy === "object" ? role.policy.fallback : void 0;
25889
26195
  const policy = parseFallbackPolicy(policyRecord);
@@ -25894,7 +26200,7 @@ function loadAgentFallback(projectRoot, agentId, options) {
25894
26200
  let cursor = typeof role.extends === "string" ? role.extends : "";
25895
26201
  while (cursor && !seenRoles.has(cursor)) {
25896
26202
  seenRoles.add(cursor);
25897
- const parent = readYaml(join12(projectRoot, ".kxm", "roles", `${cursor}.yaml`));
26203
+ const parent = readYaml(join13(projectRoot, ".kxm", "roles", `${cursor}.yaml`));
25898
26204
  extendsRoster = extendsRoster.concat(canonicalRoster(projectRoot, rosterEntries(parent)));
25899
26205
  cursor = typeof parent?.extends === "string" ? parent.extends : "";
25900
26206
  }
@@ -26242,7 +26548,7 @@ function pruneContextPacket(packet, tokenBudget) {
26242
26548
  // plugins/kxm/src/dispatch-context.ts
26243
26549
  import { spawnSync as spawnSync5 } from "node:child_process";
26244
26550
  import { readdirSync as readdirSync10 } from "node:fs";
26245
- import { extname as extname3, join as join15 } from "node:path";
26551
+ import { extname as extname3, join as join16 } from "node:path";
26246
26552
 
26247
26553
  // plugins/kxm/src/protocol.ts
26248
26554
  var DEFAULT_MESSAGE_TTL_MS = 24 * 60 * 6e4;
@@ -26874,8 +27180,8 @@ function memoryRecordToContextItem(record2, project) {
26874
27180
 
26875
27181
  // plugins/kxm/src/memory.ts
26876
27182
  var import_yaml9 = __toESM(require_dist(), 1);
26877
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, readdirSync as readdirSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "node:fs";
26878
- import { extname as extname2, join as join13, resolve as resolve7 } from "node:path";
27183
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
27184
+ import { extname as extname2, join as join14, resolve as resolve8 } from "node:path";
26879
27185
  var MEMORY_SCHEMA = "kxm.memory.v1";
26880
27186
  var VALID_SCOPES = /* @__PURE__ */ new Set(["agent", "project", "run", "operator"]);
26881
27187
  var VALID_AUTHORITIES = /* @__PURE__ */ new Set(["instruction", "evidence", "promoted"]);
@@ -26973,21 +27279,21 @@ function parseMemoryRecord(raw, filename = "memory.md") {
26973
27279
  };
26974
27280
  }
26975
27281
  function memoryDirectories(repoRoot) {
26976
- const root = resolve7(repoRoot);
26977
- const memoryDir = join13(root, ".kxm", "memory");
26978
- const candidatesDir = join13(memoryDir, "candidates");
27282
+ const root = resolve8(repoRoot);
27283
+ const memoryDir = join14(root, ".kxm", "memory");
27284
+ const candidatesDir = join14(memoryDir, "candidates");
26979
27285
  return { memoryDir, candidatesDir };
26980
27286
  }
26981
27287
  function loadAuthoredMemory(repoRoot) {
26982
27288
  const { memoryDir } = memoryDirectories(repoRoot);
26983
- if (!existsSync12(memoryDir)) return [];
27289
+ if (!existsSync13(memoryDir)) return [];
26984
27290
  const records = [];
26985
27291
  const entries = readdirSync8(memoryDir, { withFileTypes: true });
26986
27292
  for (const entry of entries) {
26987
27293
  if (entry.isFile() && extname2(entry.name) === ".md") {
26988
- const fullPath = join13(memoryDir, entry.name);
27294
+ const fullPath = join14(memoryDir, entry.name);
26989
27295
  try {
26990
- const text = readFileSync10(fullPath, "utf8");
27296
+ const text = readFileSync11(fullPath, "utf8");
26991
27297
  const record2 = parseMemoryRecord(text, entry.name);
26992
27298
  if (record2.lifecycle === "active") {
26993
27299
  records.push(record2);
@@ -27003,8 +27309,8 @@ function loadAuthoredMemory(repoRoot) {
27003
27309
  // plugins/kxm/src/skills.ts
27004
27310
  var import_yaml10 = __toESM(require_dist(), 1);
27005
27311
  import { createHash as createHash12 } from "node:crypto";
27006
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync9, readFileSync as readFileSync11, renameSync, rmSync, statSync as statSync3, writeFileSync as writeFileSync6 } from "node:fs";
27007
- import { dirname as dirname7, join as join14 } from "node:path";
27312
+ import { existsSync as existsSync14, mkdirSync as mkdirSync6, readdirSync as readdirSync9, readFileSync as readFileSync12, renameSync, rmSync, statSync as statSync3, writeFileSync as writeFileSync7 } from "node:fs";
27313
+ import { dirname as dirname8, join as join15 } from "node:path";
27008
27314
  var SKILL_CANDIDATE_SCHEMA = "kxm.skill-candidate.v1";
27009
27315
  var SKILL_EVALUATION_SCHEMA = "kxm.skill-evaluation.v1";
27010
27316
  var SKILL_DECISION_SCHEMA = "kxm.skill-decision.v1";
@@ -27106,24 +27412,24 @@ var SkillLifecycle = class {
27106
27412
  this.planned.push({ action: "write", target: file });
27107
27413
  return;
27108
27414
  }
27109
- mkdirSync5(dirname7(file), { recursive: true });
27110
- writeFileSync6(file, content);
27415
+ mkdirSync6(dirname8(file), { recursive: true });
27416
+ writeFileSync7(file, content);
27111
27417
  }
27112
27418
  dir(state) {
27113
- return join14(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
27419
+ return join15(this.root, state === "candidate" ? "candidates" : `${state}s`.replace("rejecteds", "rejected").replace("promoteds", "promoted"));
27114
27420
  }
27115
27421
  historyFile(id) {
27116
- return join14(this.root, "history", `${id}.jsonl`);
27422
+ return join15(this.root, "history", `${id}.jsonl`);
27117
27423
  }
27118
27424
  paths(state, id) {
27119
- const dir = join14(this.dir(state), id);
27120
- return { dir, metadata: join14(dir, "metadata.json"), skill: join14(dir, "SKILL.md") };
27425
+ const dir = join15(this.dir(state), id);
27426
+ return { dir, metadata: join15(dir, "metadata.json"), skill: join15(dir, "SKILL.md") };
27121
27427
  }
27122
27428
  appendHistory(id, record2) {
27123
27429
  const line = `${JSON.stringify(record2)}
27124
27430
  `;
27125
- if (existsSync13(this.historyFile(id))) {
27126
- const existing = readFileSync11(this.historyFile(id), "utf8");
27431
+ if (existsSync14(this.historyFile(id))) {
27432
+ const existing = readFileSync12(this.historyFile(id), "utf8");
27127
27433
  const lines = existing.split("\n").filter((entry) => entry.trim());
27128
27434
  this.write(this.historyFile(id), [...lines.slice(-499), line.trim()].join("\n") + "\n");
27129
27435
  } else {
@@ -27132,28 +27438,28 @@ var SkillLifecycle = class {
27132
27438
  }
27133
27439
  history(id) {
27134
27440
  const file = this.historyFile(id);
27135
- if (!existsSync13(file)) return [];
27136
- return readFileSync11(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
27441
+ if (!existsSync14(file)) return [];
27442
+ return readFileSync12(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
27137
27443
  }
27138
27444
  readMetadata(state, id) {
27139
27445
  const { metadata } = this.paths(state, id);
27140
- if (!existsSync13(metadata)) {
27446
+ if (!existsSync14(metadata)) {
27141
27447
  throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${state}`);
27142
27448
  }
27143
- return JSON.parse(readFileSync11(metadata, "utf8"));
27449
+ return JSON.parse(readFileSync12(metadata, "utf8"));
27144
27450
  }
27145
27451
  move(from, to, id) {
27146
- const fromDir = join14(this.dir(from), id);
27147
- const toDir = join14(this.dir(to), id);
27148
- if (!existsSync13(fromDir)) {
27452
+ const fromDir = join15(this.dir(from), id);
27453
+ const toDir = join15(this.dir(to), id);
27454
+ if (!existsSync14(fromDir)) {
27149
27455
  throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${from}`);
27150
27456
  }
27151
27457
  if (this.dryRun) {
27152
27458
  this.planned.push({ action: "move", target: `${fromDir} -> ${toDir}` });
27153
27459
  return;
27154
27460
  }
27155
- mkdirSync5(this.dir(to), { recursive: true });
27156
- if (existsSync13(toDir)) rmSync(toDir, { recursive: true, force: true });
27461
+ mkdirSync6(this.dir(to), { recursive: true });
27462
+ if (existsSync14(toDir)) rmSync(toDir, { recursive: true, force: true });
27157
27463
  renameSync(fromDir, toDir);
27158
27464
  }
27159
27465
  /** Submit a new skill candidate. Content is redacted of secret material at
@@ -27196,7 +27502,7 @@ var SkillLifecycle = class {
27196
27502
  const contentSha256 = skillContentSha256(content);
27197
27503
  const id = skillIdFor(name, contentSha256);
27198
27504
  const { metadata, skill } = this.paths("candidate", id);
27199
- if (existsSync13(metadata)) {
27505
+ if (existsSync14(metadata)) {
27200
27506
  throw new SkillLifecycleError(
27201
27507
  "skill_candidate_exists",
27202
27508
  `identical candidate ${id} already exists; changed behavior requires changed content`
@@ -27305,11 +27611,11 @@ var SkillLifecycle = class {
27305
27611
  };
27306
27612
  const candidatePaths = this.paths("candidate", candidateId);
27307
27613
  const promotedPaths = this.paths("promoted", candidateId);
27308
- const skillContent = readFileSync11(candidatePaths.skill, "utf8");
27309
- const metadataContent = readFileSync11(candidatePaths.metadata, "utf8");
27614
+ const skillContent = readFileSync12(candidatePaths.skill, "utf8");
27615
+ const metadataContent = readFileSync12(candidatePaths.metadata, "utf8");
27310
27616
  this.write(promotedPaths.skill, skillContent);
27311
27617
  this.write(promotedPaths.metadata, metadataContent);
27312
- const patchPath = join14(this.root, "patches", `${candidateId}.patch`);
27618
+ const patchPath = join15(this.root, "patches", `${candidateId}.patch`);
27313
27619
  const relSkillPath = `.kxm/skills/promoted/${candidateId}/SKILL.md`;
27314
27620
  const relMetaPath = `.kxm/skills/promoted/${candidateId}/metadata.json`;
27315
27621
  const patch = `${createUnifiedPatch(relSkillPath, skillContent)}${createUnifiedPatch(relMetaPath, metadataContent)}`;
@@ -27337,7 +27643,7 @@ var SkillLifecycle = class {
27337
27643
  verify(state, id) {
27338
27644
  const metadata = this.readMetadata(state, id);
27339
27645
  const { skill } = this.paths(state, id);
27340
- const content = readFileSync11(skill, "utf8");
27646
+ const content = readFileSync12(skill, "utf8");
27341
27647
  if (skillContentSha256(content) !== metadata.contentSha256) {
27342
27648
  throw new SkillLifecycleError(
27343
27649
  "skill_integrity_violation",
@@ -27355,7 +27661,7 @@ var SkillLifecycle = class {
27355
27661
  }
27356
27662
  list(state) {
27357
27663
  const dir = this.dir(state);
27358
- if (!existsSync13(dir)) return [];
27664
+ if (!existsSync14(dir)) return [];
27359
27665
  const ids = readdirSorted(dir);
27360
27666
  return ids.map((id) => {
27361
27667
  try {
@@ -27368,7 +27674,7 @@ var SkillLifecycle = class {
27368
27674
  read(state, id) {
27369
27675
  const metadata = this.readMetadata(state, id);
27370
27676
  const { skill } = this.paths(state, id);
27371
- return { metadata, content: readFileSync11(skill, "utf8") };
27677
+ return { metadata, content: readFileSync12(skill, "utf8") };
27372
27678
  }
27373
27679
  };
27374
27680
  function boundedList(value, field) {
@@ -27383,7 +27689,7 @@ function boundedList(value, field) {
27383
27689
  return [...new Set(refs)];
27384
27690
  }
27385
27691
  function readdirSorted(dir) {
27386
- return readdirSync9(dir).filter((entry) => statSync3(join14(dir, entry)).isDirectory()).sort();
27692
+ return readdirSync9(dir).filter((entry) => statSync3(join15(dir, entry)).isDirectory()).sort();
27387
27693
  }
27388
27694
 
27389
27695
  // plugins/kxm/src/dispatch-context.ts
@@ -27424,7 +27730,7 @@ function contextRoleForAgent(agentId) {
27424
27730
  return agentId;
27425
27731
  }
27426
27732
  function dispatchContextPresent(projectRoot) {
27427
- return hasTopLevelMarkdown(join15(projectRoot, ".kxm", "memory")) || hasAnyEntry(join15(projectRoot, ".kxm", "skills", "promoted"));
27733
+ return hasTopLevelMarkdown(join16(projectRoot, ".kxm", "memory")) || hasAnyEntry(join16(projectRoot, ".kxm", "skills", "promoted"));
27428
27734
  }
27429
27735
  function hasTopLevelMarkdown(dir) {
27430
27736
  try {
@@ -27500,7 +27806,7 @@ function loadDispatchContextSources(input) {
27500
27806
  }
27501
27807
  const promoted = [];
27502
27808
  try {
27503
- const lifecycle = new SkillLifecycle(join15(projectRoot, ".kxm", "skills"));
27809
+ const lifecycle = new SkillLifecycle(join16(projectRoot, ".kxm", "skills"));
27504
27810
  for (const metadata of lifecycle.list("promoted")) {
27505
27811
  try {
27506
27812
  promoted.push(lifecycle.verify("promoted", metadata.id));
@@ -27583,18 +27889,18 @@ function assembleDispatchContext(sources, input) {
27583
27889
  }
27584
27890
 
27585
27891
  // plugins/kxm/src/engine-artifacts.ts
27586
- import { join as join16 } from "node:path";
27892
+ import { join as join17 } from "node:path";
27587
27893
 
27588
27894
  // plugins/kxm/src/artifacts-exist.ts
27589
27895
  import { lstatSync as lstatSync5, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
27590
- import { isAbsolute as isAbsolute5, relative as relative4, resolve as resolve8 } from "node:path";
27896
+ import { isAbsolute as isAbsolute5, relative as relative4, resolve as resolve9 } from "node:path";
27591
27897
  function staysUnder(root, candidate) {
27592
27898
  const child = relative4(root, candidate);
27593
27899
  return child === "" || !isAbsolute5(child) && child !== ".." && !child.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`);
27594
27900
  }
27595
27901
  function verifyArtifactExists(rootInput, pathInput) {
27596
- const lexicalRoot = resolve8(rootInput);
27597
- const lexicalPath = resolve8(pathInput);
27902
+ const lexicalRoot = resolve9(rootInput);
27903
+ const lexicalPath = resolve9(pathInput);
27598
27904
  if (!staysUnder(lexicalRoot, lexicalPath)) {
27599
27905
  return { ok: false, error: "artifact_outside_workspace_assets", path: lexicalPath };
27600
27906
  }
@@ -27630,14 +27936,14 @@ function verifyArtifactExists(rootInput, pathInput) {
27630
27936
  // plugins/kxm/src/engine-artifacts.ts
27631
27937
  var kxmArtifactsGateSeams = {};
27632
27938
  function evaluateArtifactsGate(context, definition) {
27633
- const root = join16(context.projectRoot, ".kxm", "assets");
27939
+ const root = join17(context.projectRoot, ".kxm", "assets");
27634
27940
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
27635
27941
  const startTime = process.hrtime.bigint();
27636
27942
  let checkedCount = 0;
27637
27943
  let failedCount = 0;
27638
27944
  for (const [index, path] of definition.paths.entries()) {
27639
27945
  checkedCount += 1;
27640
- const result = verifyArtifactExists(root, join16(root, path));
27946
+ const result = verifyArtifactExists(root, join17(root, path));
27641
27947
  if (!result.ok) failedCount += 1;
27642
27948
  kxmArtifactsGateSeams.afterPathChecked?.({ path, index, checkedCount, failedCount });
27643
27949
  }
@@ -27793,8 +28099,8 @@ var CommandObserver = class {
27793
28099
  this.requestStop("error", "lost-close");
27794
28100
  }
27795
28101
  run() {
27796
- return new Promise((resolve13) => {
27797
- this.resolveOutcome = resolve13;
28102
+ return new Promise((resolve15) => {
28103
+ this.resolveOutcome = resolve15;
27798
28104
  try {
27799
28105
  this.start();
27800
28106
  } catch (error) {
@@ -29128,8 +29434,8 @@ var KxmRunScheduler = class _KxmRunScheduler {
29128
29434
  resolve: (_value) => void 0,
29129
29435
  reject: (_error) => void 0
29130
29436
  };
29131
- const settled = new Promise((resolve13, reject) => {
29132
- pending.resolve = resolve13;
29437
+ const settled = new Promise((resolve15, reject) => {
29438
+ pending.resolve = resolve15;
29133
29439
  pending.reject = reject;
29134
29440
  });
29135
29441
  void settled.then(void 0, () => void 0);
@@ -29668,9 +29974,9 @@ function readYamlFile(file) {
29668
29974
  return readModelDocument(file);
29669
29975
  }
29670
29976
  function readModelDocument(file) {
29671
- if (!existsSync14(file)) return void 0;
29977
+ if (!existsSync15(file)) return void 0;
29672
29978
  try {
29673
- const parsed = (0, import_yaml11.parse)(readFileSync12(file, "utf8"));
29979
+ const parsed = (0, import_yaml11.parse)(readFileSync13(file, "utf8"));
29674
29980
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
29675
29981
  return parsed;
29676
29982
  } catch {
@@ -29701,8 +30007,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
29701
30007
  }
29702
30008
  };
29703
30009
  }
29704
- const agentFile = findYamlBasename(join17(projectRoot, ".kxm", "agents"), agentId, "agent") ?? agentId;
29705
- const agent = readYamlFile(join17(projectRoot, ".kxm", "agents", `${agentFile}.yaml`));
30010
+ const agentFile = findYamlBasename(join18(projectRoot, ".kxm", "agents"), agentId, "agent") ?? agentId;
30011
+ const agent = readYamlFile(join18(projectRoot, ".kxm", "agents", `${agentFile}.yaml`));
29706
30012
  const role = typeof agent?.role === "string" ? agent.role : "";
29707
30013
  if (!role) {
29708
30014
  return {
@@ -29713,7 +30019,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
29713
30019
  }
29714
30020
  };
29715
30021
  }
29716
- const roleDoc = readYamlFile(join17(projectRoot, ".kxm", "roles", `${role}.yaml`));
30022
+ const roleDoc = readYamlFile(join18(projectRoot, ".kxm", "roles", `${role}.yaml`));
29717
30023
  const roster = Array.isArray(roleDoc?.roster) ? roleDoc.roster : void 0;
29718
30024
  if (!roster) {
29719
30025
  return {
@@ -29729,8 +30035,8 @@ function resolveProducerRoute(projectRoot, step, agentId) {
29729
30035
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
29730
30036
  const record2 = entry;
29731
30037
  if (typeof record2.route !== "string" || record2.route.length === 0) continue;
29732
- const routeFile = findYamlBasename(join17(projectRoot, ".kxm", "models"), record2.route, "route") ?? record2.route;
29733
- const modelPath = join17(projectRoot, ".kxm", "models", `${routeFile}.yaml`);
30038
+ const routeFile = findYamlBasename(join18(projectRoot, ".kxm", "models"), record2.route, "route") ?? record2.route;
30039
+ const modelPath = join18(projectRoot, ".kxm", "models", `${routeFile}.yaml`);
29734
30040
  const doc = readModelDocument(modelPath);
29735
30041
  if (!doc) {
29736
30042
  return {
@@ -32070,9 +32376,9 @@ var RuntimeHubClient = class {
32070
32376
 
32071
32377
  // plugins/kxm/src/hub-binding.ts
32072
32378
  import { spawnSync as spawnSync6 } from "node:child_process";
32073
- import { existsSync as existsSync15, mkdirSync as mkdirSync6, readFileSync as readFileSync13, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
32074
- import { homedir as homedir2 } from "node:os";
32075
- import { dirname as dirname8, isAbsolute as isAbsolute6, join as join18, resolve as resolve9 } from "node:path";
32379
+ import { existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync14, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync8 } from "node:fs";
32380
+ import { homedir as homedir3 } from "node:os";
32381
+ import { dirname as dirname9, isAbsolute as isAbsolute6, join as join19, resolve as resolve10 } from "node:path";
32076
32382
  var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
32077
32383
  var CloudTokenError = class extends Error {
32078
32384
  code;
@@ -32095,20 +32401,20 @@ function resolveUserStateRoot(env) {
32095
32401
  const explicit = env.KXM_STATE_HOME?.trim();
32096
32402
  if (explicit) {
32097
32403
  if (!isAbsolute6(explicit)) throw new HubBindingError("local_state_root_not_absolute");
32098
- return resolve9(explicit);
32404
+ return resolve10(explicit);
32099
32405
  }
32100
32406
  if (process.platform === "win32") {
32101
32407
  const localAppData = env.LOCALAPPDATA?.trim();
32102
- const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join18(homedir2(), "AppData", "Local");
32103
- return resolve9(base2, "KXM");
32408
+ const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join19(homedir3(), "AppData", "Local");
32409
+ return resolve10(base2, "KXM");
32104
32410
  }
32105
- if (process.platform === "darwin") return resolve9(homedir2(), "Library", "Application Support", "KXM");
32411
+ if (process.platform === "darwin") return resolve10(homedir3(), "Library", "Application Support", "KXM");
32106
32412
  const xdgState = env.XDG_STATE_HOME?.trim();
32107
- const base = xdgState && isAbsolute6(xdgState) ? xdgState : join18(homedir2(), ".local", "state");
32108
- return resolve9(base, "kxm");
32413
+ const base = xdgState && isAbsolute6(xdgState) ? xdgState : join19(homedir3(), ".local", "state");
32414
+ return resolve10(base, "kxm");
32109
32415
  }
32110
32416
  function hubBindingFile(env = process.env) {
32111
- return join18(resolveUserStateRoot(env), "hub-binding.json");
32417
+ return join19(resolveUserStateRoot(env), "hub-binding.json");
32112
32418
  }
32113
32419
  function validateHubUrl(raw) {
32114
32420
  let parsed;
@@ -32204,16 +32510,27 @@ function runTokenCommand(command, env) {
32204
32510
  }
32205
32511
  return stdout.trim();
32206
32512
  }
32513
+ function hubBindingScope(url) {
32514
+ let host;
32515
+ try {
32516
+ host = new URL(url).hostname.toLowerCase();
32517
+ } catch {
32518
+ return "remote";
32519
+ }
32520
+ if (host === "localhost" || host === "::1" || host === "[::1]" || host.endsWith(".localhost")) return "loopback";
32521
+ const v4 = /^127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/.exec(host);
32522
+ return v4 && [v4[1], v4[2], v4[3]].every((part) => Number(part) <= 255) ? "loopback" : "remote";
32523
+ }
32207
32524
  function isIsoTimestamp(value) {
32208
32525
  if (Number.isNaN(Date.parse(value))) return false;
32209
32526
  return value === new Date(value).toISOString();
32210
32527
  }
32211
32528
  function readHubBinding(env = process.env) {
32212
32529
  const file = hubBindingFile(env);
32213
- if (!existsSync15(file)) return void 0;
32530
+ if (!existsSync16(file)) return void 0;
32214
32531
  let parsed;
32215
32532
  try {
32216
- parsed = JSON.parse(readFileSync13(file, "utf8"));
32533
+ parsed = JSON.parse(readFileSync14(file, "utf8"));
32217
32534
  } catch {
32218
32535
  throw new HubBindingError(`malformed hub binding at ${file}`);
32219
32536
  }
@@ -32264,12 +32581,197 @@ function readHubBinding(env = process.env) {
32264
32581
  }
32265
32582
 
32266
32583
  // plugins/kxm/src/hub-env.ts
32267
- import { existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync14, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
32268
- import { homedir as homedir3 } from "node:os";
32269
- import { dirname as dirname9, isAbsolute as isAbsolute7, join as join19, resolve as resolve10 } from "node:path";
32584
+ import { existsSync as existsSync18, mkdirSync as mkdirSync8, readFileSync as readFileSync16, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync9 } from "node:fs";
32585
+ import { homedir as homedir4 } from "node:os";
32586
+ import { dirname as dirname11, isAbsolute as isAbsolute7, join as join21, resolve as resolve12 } from "node:path";
32270
32587
 
32271
- // plugins/kxm/src/project-name.ts
32588
+ // plugins/kxm/src/hub-identity.ts
32272
32589
  var import_yaml12 = __toESM(require_dist(), 1);
32590
+ import { spawnSync as spawnSync7 } from "node:child_process";
32591
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "node:fs";
32592
+ import { basename as basename4, dirname as dirname10, join as join20, resolve as resolve11 } from "node:path";
32593
+ var OP_TIMEOUT_MS = 15e3;
32594
+ var OP_MAX_BUFFER = 4096;
32595
+ function normalizeUrl(raw) {
32596
+ try {
32597
+ return validateHubUrl(raw);
32598
+ } catch {
32599
+ return void 0;
32600
+ }
32601
+ }
32602
+ function projectYamlId(start) {
32603
+ let dir = resolve11(start);
32604
+ for (; ; ) {
32605
+ const file = join20(dir, ".kxm", "project.yaml");
32606
+ if (existsSync17(file)) {
32607
+ try {
32608
+ const doc = (0, import_yaml12.parse)(readFileSync15(file, "utf8"));
32609
+ if (doc && typeof doc === "object" && !Array.isArray(doc) && typeof doc.id === "string" && doc.id.trim()) {
32610
+ return doc.id.trim();
32611
+ }
32612
+ } catch {
32613
+ }
32614
+ return void 0;
32615
+ }
32616
+ const parent = dirname10(dir);
32617
+ if (parent === dir) return void 0;
32618
+ dir = parent;
32619
+ }
32620
+ }
32621
+ function packageName(cwd) {
32622
+ try {
32623
+ const pkg = JSON.parse(readFileSync15(join20(cwd, "package.json"), "utf8"));
32624
+ if (typeof pkg.name === "string" && pkg.name.trim().length > 0) return pkg.name.trim();
32625
+ } catch {
32626
+ }
32627
+ return void 0;
32628
+ }
32629
+ function activeBinding(env) {
32630
+ try {
32631
+ return readHubBinding(env);
32632
+ } catch (error) {
32633
+ if (error instanceof HubBindingError) return void 0;
32634
+ throw error;
32635
+ }
32636
+ }
32637
+ function endpointFor(mode, settings) {
32638
+ return mode === "cloud" ? settings.cloud : settings.local;
32639
+ }
32640
+ function resolveProjectIdentity(cwd, env = process.env, explicit) {
32641
+ const fromExplicit = explicit?.trim();
32642
+ if (fromExplicit) return { project: fromExplicit, source: "flag", sourceLabel: "--project" };
32643
+ const fromEnv = env.KXM_PROJECT?.trim();
32644
+ if (fromEnv) return { project: fromEnv, source: "env", sourceLabel: "KXM_PROJECT" };
32645
+ const settings = loadHubSettings(cwd, env);
32646
+ const mode = settings.mode ?? (activeBinding(env)?.cloud ? "cloud" : "local");
32647
+ const fromConfig = endpointFor(mode, settings)?.project?.trim();
32648
+ if (fromConfig) {
32649
+ return { project: fromConfig, source: "config", sourceLabel: `.kxm/config.yaml hub.${mode}.project` };
32650
+ }
32651
+ const fromProject = projectYamlId(cwd);
32652
+ if (fromProject) return { project: fromProject, source: "project.yaml", sourceLabel: ".kxm/project.yaml id" };
32653
+ const fromPackage = packageName(cwd);
32654
+ if (fromPackage) return { project: fromPackage, source: "package.json", sourceLabel: "package.json name" };
32655
+ return { project: basename4(cwd), source: "directory", sourceLabel: "directory name" };
32656
+ }
32657
+ function opReferenceFromTokenCommand(command) {
32658
+ try {
32659
+ const args = splitTokenCommand(command);
32660
+ if (args[0] === "op" && args[1] === "read" && args[2] && isHubOpReference(args[2])) return args[2];
32661
+ } catch {
32662
+ return void 0;
32663
+ }
32664
+ return void 0;
32665
+ }
32666
+ function defaultOpRead(reference, env) {
32667
+ if (!isHubOpReference(reference)) {
32668
+ throw new CloudTokenError("cloud_token_command_invalid", `refusing to resolve ${reference}; an op:// reference is required`);
32669
+ }
32670
+ const result = spawnSync7("op", ["read", reference], {
32671
+ encoding: "utf8",
32672
+ shell: false,
32673
+ timeout: OP_TIMEOUT_MS,
32674
+ maxBuffer: OP_MAX_BUFFER,
32675
+ env,
32676
+ windowsHide: true
32677
+ });
32678
+ if (result.error || result.status !== 0) {
32679
+ throw new CloudTokenError(
32680
+ "cloud_token_command_failed",
32681
+ `op read failed for ${reference}; the token was not saved`
32682
+ );
32683
+ }
32684
+ const line = (result.stdout ?? "").trim();
32685
+ if (!line || line.split(/\r?\n/).length !== 1) {
32686
+ throw new CloudTokenError(
32687
+ "cloud_token_command_failed",
32688
+ `op read did not print a single token for ${reference}; the token was not saved`
32689
+ );
32690
+ }
32691
+ return line;
32692
+ }
32693
+ function resolveKeyReference(ref, env, opRead = defaultOpRead) {
32694
+ if (!ref) return void 0;
32695
+ if (ref.env) {
32696
+ const value = env[ref.env]?.trim();
32697
+ if (value) return { value, source: `env:${ref.env}` };
32698
+ }
32699
+ if (ref.op) {
32700
+ const value = opRead(ref.op, env).trim();
32701
+ if (!value || value.split(/\r?\n/).length !== 1) {
32702
+ throw new CloudTokenError("cloud_token_command_failed", `op read did not print a single token for ${ref.op}`);
32703
+ }
32704
+ return { value, source: `op:${ref.op}` };
32705
+ }
32706
+ return void 0;
32707
+ }
32708
+ function keySourceFor(input) {
32709
+ const ref = input.endpoint?.key;
32710
+ if (input.mode === "local" && input.env.KXM_AUTH_TOKEN?.trim()) return "env:KXM_AUTH_TOKEN";
32711
+ if (ref?.env && input.env[ref.env]?.trim()) return `env:${ref.env}`;
32712
+ if (ref?.op) return `op:${ref.op}`;
32713
+ if (ref?.env) return `env:${ref.env}`;
32714
+ if (input.mode === "cloud") {
32715
+ if (input.binding?.tokenEnv) return `env:${input.binding.tokenEnv}`;
32716
+ if (input.binding?.tokenCommand) {
32717
+ const op = opReferenceFromTokenCommand(input.binding.tokenCommand);
32718
+ return op ? `op:${op}` : "command";
32719
+ }
32720
+ return "missing";
32721
+ }
32722
+ if (input.hasSavedProjectToken?.(input.project)) return "hub-env";
32723
+ return "missing";
32724
+ }
32725
+ function describeHubConnection(cwd, env = process.env, hooks = {}) {
32726
+ const settings = loadHubSettings(cwd, env);
32727
+ const binding = activeBinding(env);
32728
+ const mode = settings.mode ?? (binding?.cloud ? "cloud" : "local");
32729
+ const modeSource = settings.mode ? "config" : binding?.cloud ? "binding" : "default";
32730
+ const endpoint = endpointFor(mode, settings);
32731
+ const fromEnv = env.KXM_SERVER_URL?.trim();
32732
+ const fromConfig = endpoint?.url?.trim();
32733
+ const fromBinding = binding?.url;
32734
+ let url = "http://127.0.0.1:7331";
32735
+ let urlSource = "default";
32736
+ if (fromEnv) {
32737
+ url = fromEnv.replace(/\/$/, "");
32738
+ urlSource = "env";
32739
+ } else if (fromConfig) {
32740
+ url = fromConfig.replace(/\/$/, "");
32741
+ urlSource = "config";
32742
+ } else if (fromBinding) {
32743
+ url = fromBinding;
32744
+ urlSource = "binding";
32745
+ }
32746
+ const identity = resolveProjectIdentity(cwd, env, hooks.explicitProject);
32747
+ const configuredCloudUrl = settings.cloud?.url ?? (binding?.cloud ? binding.url : void 0);
32748
+ let scope;
32749
+ if (mode === "cloud") {
32750
+ const override = fromEnv ? normalizeUrl(fromEnv) : void 0;
32751
+ const named = configuredCloudUrl ? normalizeUrl(configuredCloudUrl) : void 0;
32752
+ scope = override && named && override !== named ? hubBindingScope(url) : "remote";
32753
+ } else {
32754
+ scope = hubBindingScope(url);
32755
+ }
32756
+ return {
32757
+ ...identity,
32758
+ mode,
32759
+ modeSource,
32760
+ url,
32761
+ urlSource,
32762
+ scope,
32763
+ ...endpoint ? { endpoint } : {},
32764
+ ...binding ? { binding } : {},
32765
+ keySource: keySourceFor({
32766
+ mode,
32767
+ env,
32768
+ ...endpoint ? { endpoint } : {},
32769
+ ...binding ? { binding } : {},
32770
+ project: identity.project,
32771
+ ...hooks.hasSavedProjectToken ? { hasSavedProjectToken: hooks.hasSavedProjectToken } : {}
32772
+ })
32773
+ };
32774
+ }
32273
32775
 
32274
32776
  // plugins/kxm/src/hub-env.ts
32275
32777
  var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
@@ -32283,27 +32785,27 @@ function resolveUserStateRoot2(env) {
32283
32785
  const explicit = env.KXM_STATE_HOME?.trim();
32284
32786
  if (explicit) {
32285
32787
  if (!isAbsolute7(explicit)) throw new HubEnvError("local_state_root_not_absolute");
32286
- return resolve10(explicit);
32788
+ return resolve12(explicit);
32287
32789
  }
32288
32790
  if (process.platform === "win32") {
32289
32791
  const localAppData = env.LOCALAPPDATA?.trim();
32290
- const base2 = localAppData && isAbsolute7(localAppData) ? localAppData : join19(homedir3(), "AppData", "Local");
32291
- return resolve10(base2, "KXM");
32792
+ const base2 = localAppData && isAbsolute7(localAppData) ? localAppData : join21(homedir4(), "AppData", "Local");
32793
+ return resolve12(base2, "KXM");
32292
32794
  }
32293
- if (process.platform === "darwin") return resolve10(homedir3(), "Library", "Application Support", "KXM");
32795
+ if (process.platform === "darwin") return resolve12(homedir4(), "Library", "Application Support", "KXM");
32294
32796
  const xdgState = env.XDG_STATE_HOME?.trim();
32295
- const base = xdgState && isAbsolute7(xdgState) ? xdgState : join19(homedir3(), ".local", "state");
32296
- return resolve10(base, "kxm");
32797
+ const base = xdgState && isAbsolute7(xdgState) ? xdgState : join21(homedir4(), ".local", "state");
32798
+ return resolve12(base, "kxm");
32297
32799
  }
32298
32800
  function hubEnvFile(env = process.env) {
32299
- return join19(resolveUserStateRoot2(env), "hub-env.json");
32801
+ return join21(resolveUserStateRoot2(env), "hub-env.json");
32300
32802
  }
32301
32803
  function readHubEnvRecord(env = process.env) {
32302
32804
  const file = hubEnvFile(env);
32303
- if (!existsSync16(file)) return void 0;
32805
+ if (!existsSync18(file)) return void 0;
32304
32806
  let parsed;
32305
32807
  try {
32306
- parsed = JSON.parse(readFileSync14(file, "utf8"));
32808
+ parsed = JSON.parse(readFileSync16(file, "utf8"));
32307
32809
  } catch (error) {
32308
32810
  throw new HubEnvError(`hub env file is malformed at ${file}: ${error instanceof Error ? error.message : String(error)}`);
32309
32811
  }
@@ -32335,31 +32837,31 @@ function readHubEnvRecord(env = process.env) {
32335
32837
  ...record2.projectTokens !== void 0 ? { projectTokens: record2.projectTokens } : {}
32336
32838
  };
32337
32839
  }
32338
- function activeCloudBinding(env) {
32339
- try {
32340
- const binding = readHubBinding(env);
32341
- return binding?.cloud ? binding : void 0;
32342
- } catch (error) {
32343
- if (error instanceof HubBindingError) {
32344
- throw new HubEnvError(
32345
- `${error.message}; refusing to guess a credential \u2014 repair or remove ${hubBindingFile(env)}`
32346
- );
32347
- }
32348
- throw error;
32349
- }
32840
+ function cloudModeToken(cwd, env, explicitProject, opRead) {
32841
+ const connection = describeHubConnection(cwd, env, explicitProject === void 0 ? {} : { explicitProject });
32842
+ if (connection.mode !== "cloud") return void 0;
32843
+ const fromConfig = resolveKeyReference(connection.endpoint?.key, env, opRead);
32844
+ if (fromConfig) return fromConfig.value;
32845
+ if (connection.binding?.cloud) return resolveCloudHubToken(connection.binding, env);
32846
+ throw new CloudTokenError(
32847
+ "cloud_token_missing",
32848
+ "cloud hub token is missing; the local hub-env token was not used"
32849
+ );
32350
32850
  }
32351
- function resolveClientHubAuthToken(env, project) {
32352
- const cloud = activeCloudBinding(env);
32353
- if (cloud) return resolveCloudHubToken(cloud, env);
32851
+ function resolveClientHubAuthToken(env, project, cwd = process.cwd(), opRead) {
32852
+ const cloud = cloudModeToken(cwd, env, void 0, opRead);
32853
+ if (cloud) return cloud;
32354
32854
  const envToken = env.KXM_AUTH_TOKEN?.trim();
32355
32855
  if (envToken) return envToken;
32856
+ const fromConfig = resolveKeyReference(describeHubConnection(cwd, env).endpoint?.key, env, opRead);
32857
+ if (fromConfig) return fromConfig.value;
32356
32858
  const record2 = readHubEnvRecord(env);
32357
32859
  return record2?.projectTokens?.[project]?.trim() || record2?.authToken?.trim() || void 0;
32358
32860
  }
32359
32861
 
32360
32862
  // plugins/kxm/src/logger.ts
32361
- import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync8, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
32362
- import { dirname as dirname10 } from "node:path";
32863
+ import { appendFileSync, existsSync as existsSync19, mkdirSync as mkdirSync9, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
32864
+ import { dirname as dirname12 } from "node:path";
32363
32865
  var LOG_LEVEL_PRIORITY = {
32364
32866
  debug: 10,
32365
32867
  info: 20,
@@ -32396,7 +32898,7 @@ function redactLogValue(val, key) {
32396
32898
  function rotateLogFiles(filePath, maxFiles) {
32397
32899
  for (let i = maxFiles; i >= 1; i--) {
32398
32900
  const current = `${filePath}.${i}`;
32399
- if (existsSync17(current)) {
32901
+ if (existsSync19(current)) {
32400
32902
  if (i >= maxFiles) {
32401
32903
  try {
32402
32904
  unlinkSync2(current);
@@ -32410,7 +32912,7 @@ function rotateLogFiles(filePath, maxFiles) {
32410
32912
  }
32411
32913
  }
32412
32914
  }
32413
- if (existsSync17(filePath)) {
32915
+ if (existsSync19(filePath)) {
32414
32916
  try {
32415
32917
  renameSync4(filePath, `${filePath}.1`);
32416
32918
  } catch {
@@ -32427,7 +32929,7 @@ function createLogger(options) {
32427
32929
  const shouldStdout = options.stdout ?? !isDaemon;
32428
32930
  const correlationDefaults = options.correlation ?? {};
32429
32931
  let currentSize = 0;
32430
- if (filePath && existsSync17(filePath)) {
32932
+ if (filePath && existsSync19(filePath)) {
32431
32933
  try {
32432
32934
  currentSize = statSync5(filePath).size;
32433
32935
  } catch {
@@ -32465,7 +32967,7 @@ function createLogger(options) {
32465
32967
  currentSize = 0;
32466
32968
  }
32467
32969
  try {
32468
- mkdirSync8(dirname10(filePath), { recursive: true });
32970
+ mkdirSync9(dirname12(filePath), { recursive: true });
32469
32971
  appendFileSync(filePath, line, { encoding: "utf8", mode: 384 });
32470
32972
  currentSize += lineBytes;
32471
32973
  } catch {
@@ -32508,13 +33010,13 @@ function createLogger(options) {
32508
33010
 
32509
33011
  // plugins/kxm/src/runtime-supervisor.ts
32510
33012
  function kxmSupervisorTokenFile(paths) {
32511
- return join20(paths.runtimeDir, "supervisor.token");
33013
+ return join22(paths.runtimeDir, "supervisor.token");
32512
33014
  }
32513
33015
  function publishKxmSupervisorToken(paths, token) {
32514
33016
  const file = kxmSupervisorTokenFile(paths);
32515
- mkdirSync9(dirname11(file), { recursive: true, mode: 448 });
33017
+ mkdirSync10(dirname13(file), { recursive: true, mode: 448 });
32516
33018
  const temp = `${file}.${process.pid}.tmp`;
32517
- writeFileSync9(temp, `${token}
33019
+ writeFileSync10(temp, `${token}
32518
33020
  `, { encoding: "utf8", mode: 384 });
32519
33021
  try {
32520
33022
  chmodSync2(temp, 384);
@@ -32536,7 +33038,7 @@ function readKxmSupervisorToken(paths) {
32536
33038
  if (stat.isSymbolicLink() || !stat.isFile()) {
32537
33039
  throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
32538
33040
  }
32539
- const token = readFileSync15(file, "utf8").trim();
33041
+ const token = readFileSync17(file, "utf8").trim();
32540
33042
  return token.length >= 32 ? token : void 0;
32541
33043
  }
32542
33044
  function processAlive(pid) {
@@ -32550,16 +33052,16 @@ function processAlive(pid) {
32550
33052
  var HEARTBEAT_STALE_MS = 15e3;
32551
33053
  var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
32552
33054
  function supervisorErrorFile(paths) {
32553
- return join20(paths.runtimeDir, "supervisor.error");
33055
+ return join22(paths.runtimeDir, "supervisor.error");
32554
33056
  }
32555
33057
  function clearSupervisorError(paths) {
32556
33058
  const file = supervisorErrorFile(paths);
32557
- if (existsSync18(file)) rmSync4(file, { force: true });
33059
+ if (existsSync20(file)) rmSync4(file, { force: true });
32558
33060
  }
32559
33061
  function recordSupervisorError(paths, message) {
32560
33062
  try {
32561
- mkdirSync9(paths.runtimeDir, { recursive: true, mode: 448 });
32562
- writeFileSync9(supervisorErrorFile(paths), `${message}
33063
+ mkdirSync10(paths.runtimeDir, { recursive: true, mode: 448 });
33064
+ writeFileSync10(supervisorErrorFile(paths), `${message}
32563
33065
  `, { encoding: "utf8", mode: 384 });
32564
33066
  } catch {
32565
33067
  }
@@ -32571,7 +33073,7 @@ function readRecentSupervisorError(paths) {
32571
33073
  const ageMs = Date.now() - stat.mtimeMs;
32572
33074
  if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
32573
33075
  try {
32574
- return readFileSync15(file, "utf8").trim();
33076
+ return readFileSync17(file, "utf8").trim();
32575
33077
  } catch {
32576
33078
  return void 0;
32577
33079
  }
@@ -32610,7 +33112,7 @@ function supervisorStatusOf(record2) {
32610
33112
  };
32611
33113
  }
32612
33114
  function kxmSupervisorStatus(paths, options = {}) {
32613
- if (!existsSync18(paths.registryDb)) return { running: false };
33115
+ if (!existsSync20(paths.registryDb)) return { running: false };
32614
33116
  if (options.readOnly) {
32615
33117
  const database = openReadOnlyDatabase(paths.registryDb);
32616
33118
  try {
@@ -32676,7 +33178,7 @@ async function ensureKxmSupervisor(options = {}) {
32676
33178
  throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
32677
33179
  }
32678
33180
  clearSupervisorError(paths);
32679
- const scriptPath = join20(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
33181
+ const scriptPath = join22(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
32680
33182
  const spawnImpl = options.spawnImpl ?? ((script, env) => {
32681
33183
  const child = spawn3(process.execPath, [script], {
32682
33184
  detached: true,
@@ -32761,8 +33263,8 @@ async function waitForDriveSessions(settled, graceMs) {
32761
33263
  try {
32762
33264
  await Promise.race([
32763
33265
  Promise.allSettled(settled),
32764
- new Promise((resolve13) => {
32765
- timeout = setTimeout(resolve13, graceMs);
33266
+ new Promise((resolve15) => {
33267
+ timeout = setTimeout(resolve15, graceMs);
32766
33268
  timeout.unref?.();
32767
33269
  })
32768
33270
  ]);
@@ -32899,7 +33401,7 @@ function syncFailureText(error) {
32899
33401
  return `${code ? `${code}: ` : ""}${message}`.replace(/(kxm_[A-Za-z0-9_]+|[A-Za-z0-9._-]{40,})/g, "[redacted]").slice(0, 300);
32900
33402
  }
32901
33403
  function runtimeSupervisorLogFile(paths) {
32902
- return join20(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
33404
+ return join22(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
32903
33405
  }
32904
33406
  async function startKxmRuntimeSupervisor(options = {}) {
32905
33407
  const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
@@ -32915,8 +33417,8 @@ async function startKxmRuntimeSupervisor(options = {}) {
32915
33417
  }
32916
33418
  }
32917
33419
  async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, env) {
32918
- mkdirSync9(paths.runtimeDir, { recursive: true, mode: 448 });
32919
- mkdirSync9(paths.projectsDir, { recursive: true, mode: 448 });
33420
+ mkdirSync10(paths.runtimeDir, { recursive: true, mode: 448 });
33421
+ mkdirSync10(paths.projectsDir, { recursive: true, mode: 448 });
32920
33422
  const logger = createLogger({
32921
33423
  component: "runtime",
32922
33424
  path: runtimeSupervisorLogFile(paths),
@@ -33028,8 +33530,8 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
33028
33530
  openRunIds = unsettledRunIds(existing2);
33029
33531
  } else {
33030
33532
  const registration = registry.projectByRoot(projectRoot);
33031
- const eventsPath = join20(paths.projectsDir, registration?.projectKey ?? projectRuntimeKey(projectRoot), "run-events.db");
33032
- if (registration && existsSync18(eventsPath)) {
33533
+ const eventsPath = join22(paths.projectsDir, registration?.projectKey ?? projectRuntimeKey(projectRoot), "run-events.db");
33534
+ if (registration && existsSync20(eventsPath)) {
33033
33535
  const store = new KxmRunEventStore(eventsPath);
33034
33536
  try {
33035
33537
  openRunIds = store.runsForProject(registration.projectId, 1e4).filter((run) => !SETTLED_RUN_STATUS.has(run.status)).map((run) => run.runId);
@@ -33545,7 +34047,7 @@ function handoffSuffix(handoff) {
33545
34047
 
33546
34048
  // plugins/kxm/src/pi-producer.ts
33547
34049
  import { spawn as spawn4 } from "node:child_process";
33548
- import { join as join21 } from "node:path";
34050
+ import { join as join23 } from "node:path";
33549
34051
  import { StringDecoder } from "node:string_decoder";
33550
34052
  function formatPiSessionKey(params) {
33551
34053
  if (params.agentId === "coordinator") {
@@ -33761,8 +34263,8 @@ var PiSession = class {
33761
34263
  }
33762
34264
  const id = `cmd_${++this.commandCounter}`;
33763
34265
  const payload = { ...command, id };
33764
- return new Promise((resolve13, reject) => {
33765
- this.pendingCommands.set(id, { resolve: resolve13, reject });
34266
+ return new Promise((resolve15, reject) => {
34267
+ this.pendingCommands.set(id, { resolve: resolve15, reject });
33766
34268
  try {
33767
34269
  this.process.stdin.write(JSON.stringify(payload) + "\n");
33768
34270
  } catch (err) {
@@ -33782,7 +34284,7 @@ var PiSession = class {
33782
34284
  return { outcome: "cancelled", text: "aborted", usage: {} };
33783
34285
  }
33784
34286
  this.status = "busy";
33785
- return new Promise((resolve13, reject) => {
34287
+ return new Promise((resolve15, reject) => {
33786
34288
  let signalCleanup;
33787
34289
  if (signal) {
33788
34290
  const onAbort = () => {
@@ -33796,7 +34298,7 @@ var PiSession = class {
33796
34298
  signalCleanup = () => signal.removeEventListener("abort", onAbort);
33797
34299
  }
33798
34300
  this.activePrompt = {
33799
- resolve: resolve13,
34301
+ resolve: resolve15,
33800
34302
  reject,
33801
34303
  allowedOutcomes,
33802
34304
  text: "",
@@ -33919,7 +34421,7 @@ function createKxmPiProducer(options = {}) {
33919
34421
  const args = ["--mode", "rpc", "--name", displayName];
33920
34422
  if (options.sessionDir) {
33921
34423
  const safeDirName = key.replace(/[^a-zA-Z0-9_-]/g, "_");
33922
- args.push("--session-dir", join21(options.sessionDir, request.runId, safeDirName));
34424
+ args.push("--session-dir", join23(options.sessionDir, request.runId, safeDirName));
33923
34425
  }
33924
34426
  if (model) {
33925
34427
  args.push("--model", model);
@@ -34048,8 +34550,8 @@ function createKxmPiProducer(options = {}) {
34048
34550
 
34049
34551
  // plugins/kxm/src/improve.ts
34050
34552
  import { createHash as createHash17 } from "node:crypto";
34051
- import { existsSync as existsSync19, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "node:fs";
34052
- import { join as join22, relative as relative5, resolve as resolve11 } from "node:path";
34553
+ import { existsSync as existsSync21, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "node:fs";
34554
+ import { join as join24, relative as relative5, resolve as resolve13 } from "node:path";
34053
34555
  var CANDIDATE_SCHEMA = "kxm.candidate.v1";
34054
34556
  var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
34055
34557
  var IMPROVEMENT_REPORT_V1_SCHEMA = "kxm.improvement-report.v1";
@@ -34305,8 +34807,8 @@ function groupRoutingRecords(records, options = {}) {
34305
34807
  }).map((entry) => entry.row);
34306
34808
  }
34307
34809
  function buildImprovementReport(records, options = {}) {
34308
- const projectRoot = options.projectRoot ? resolve11(options.projectRoot) : process.cwd();
34309
- const candidatesDir = options.candidatesDir ? resolve11(options.candidatesDir) : join22(projectRoot, ".kxm", "candidates");
34810
+ const projectRoot = options.projectRoot ? resolve13(options.projectRoot) : process.cwd();
34811
+ const candidatesDir = options.candidatesDir ? resolve13(options.candidatesDir) : join24(projectRoot, ".kxm", "candidates");
34310
34812
  const promotionPolicy = options.promotionPolicy ?? "manual_pr";
34311
34813
  const groups = groupRoutingRecords(records, options);
34312
34814
  const candidates = [];
@@ -34320,7 +34822,7 @@ function buildImprovementReport(records, options = {}) {
34320
34822
  group.workflowId
34321
34823
  );
34322
34824
  const diffFileName = `${group.candidateId}.diff`;
34323
- const diffFilePath = join22(candidatesDir, diffFileName);
34825
+ const diffFilePath = join24(candidatesDir, diffFileName);
34324
34826
  const relDiffPath = relative5(projectRoot, diffFilePath).replace(/\\/g, "/");
34325
34827
  const candidate = {
34326
34828
  schema: CANDIDATE_SCHEMA,
@@ -34342,12 +34844,12 @@ function buildImprovementReport(records, options = {}) {
34342
34844
  createdAt: nowIso()
34343
34845
  };
34344
34846
  if (!options.dryRun) {
34345
- if (!existsSync19(candidatesDir)) {
34346
- mkdirSync10(candidatesDir, { recursive: true });
34847
+ if (!existsSync21(candidatesDir)) {
34848
+ mkdirSync11(candidatesDir, { recursive: true });
34347
34849
  }
34348
- writeFileSync10(diffFilePath, diff, "utf8");
34349
- const jsonFilePath = join22(candidatesDir, `${group.candidateId}.json`);
34350
- writeFileSync10(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
34850
+ writeFileSync11(diffFilePath, diff, "utf8");
34851
+ const jsonFilePath = join24(candidatesDir, `${group.candidateId}.json`);
34852
+ writeFileSync11(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
34351
34853
  }
34352
34854
  candidates.push(candidate);
34353
34855
  }
@@ -34377,10 +34879,10 @@ function buildImprovementReport(records, options = {}) {
34377
34879
  }
34378
34880
  function writeImprovementReport(improvementsDir, report, dryRun = false) {
34379
34881
  const stamp = report.createdAt.replace(/[:.]/g, "-");
34380
- const path = join22(improvementsDir, `${stamp}.json`);
34882
+ const path = join24(improvementsDir, `${stamp}.json`);
34381
34883
  if (!dryRun) {
34382
- mkdirSync10(improvementsDir, { recursive: true });
34383
- writeFileSync10(path, `${JSON.stringify(report, null, 2)}
34884
+ mkdirSync11(improvementsDir, { recursive: true });
34885
+ writeFileSync11(path, `${JSON.stringify(report, null, 2)}
34384
34886
  `, { encoding: "utf8" });
34385
34887
  }
34386
34888
  return path;
@@ -35047,8 +35549,8 @@ Instructions for Operator:
35047
35549
 
35048
35550
  // plugins/kxm/src/modes.ts
35049
35551
  var import_yaml13 = __toESM(require_dist(), 1);
35050
- import { existsSync as existsSync20, readFileSync as readFileSync17 } from "node:fs";
35051
- import { join as join23 } from "node:path";
35552
+ import { existsSync as existsSync22, readFileSync as readFileSync19 } from "node:fs";
35553
+ import { join as join25 } from "node:path";
35052
35554
  var DEFAULT_MODES_CONFIG = Object.freeze({
35053
35555
  schema: "kxm.modes.v1",
35054
35556
  majorModes: {
@@ -35111,12 +35613,12 @@ function loadModesConfig(projectRoot) {
35111
35613
  if (!projectRoot) {
35112
35614
  return DEFAULT_MODES_CONFIG;
35113
35615
  }
35114
- const modesPath = join23(projectRoot, ".kxm", "modes.yaml");
35115
- if (!existsSync20(modesPath)) {
35616
+ const modesPath = join25(projectRoot, ".kxm", "modes.yaml");
35617
+ if (!existsSync22(modesPath)) {
35116
35618
  return DEFAULT_MODES_CONFIG;
35117
35619
  }
35118
35620
  try {
35119
- const raw = readFileSync17(modesPath, "utf8");
35621
+ const raw = readFileSync19(modesPath, "utf8");
35120
35622
  const parsed = (0, import_yaml13.parse)(raw);
35121
35623
  if (parsed && parsed.schema === "kxm.modes.v1" && parsed.majorModes) {
35122
35624
  return {
@@ -35202,11 +35704,11 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
35202
35704
  estimatedTokens: estimateTokens(baseSystemPromptChars)
35203
35705
  });
35204
35706
  for (const relPath of resolved.contextFiles) {
35205
- const fullPath = join23(projectRoot, relPath);
35707
+ const fullPath = join25(projectRoot, relPath);
35206
35708
  let chars = 0;
35207
- if (existsSync20(fullPath)) {
35709
+ if (existsSync22(fullPath)) {
35208
35710
  try {
35209
- chars = readFileSync17(fullPath, "utf8").length;
35711
+ chars = readFileSync19(fullPath, "utf8").length;
35210
35712
  } catch {
35211
35713
  chars = 0;
35212
35714
  }
@@ -35337,10 +35839,10 @@ ${divider}
35337
35839
  }
35338
35840
 
35339
35841
  // plugins/kxm/src/ssh-remote.ts
35340
- import { spawnSync as spawnSync7 } from "node:child_process";
35341
- import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync18, readdirSync as readdirSync11, rmSync as rmSync5, statSync as statSync6 } from "node:fs";
35342
- import { homedir as homedir4 } from "node:os";
35343
- import { join as join24, resolve as resolve12 } from "node:path";
35842
+ import { spawnSync as spawnSync8 } from "node:child_process";
35843
+ import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync20, readdirSync as readdirSync11, rmSync as rmSync5, statSync as statSync6 } from "node:fs";
35844
+ import { homedir as homedir5 } from "node:os";
35845
+ import { join as join26, resolve as resolve14 } from "node:path";
35344
35846
  var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
35345
35847
  var MAX_SSH_OUTPUT_LINES = 2e3;
35346
35848
  var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
@@ -35366,12 +35868,12 @@ function truncateSshOutput(raw) {
35366
35868
  return { text, truncated };
35367
35869
  }
35368
35870
  function parseSshConfig(configPath) {
35369
- const targetPath = configPath ?? join24(homedir4(), ".ssh", "config");
35370
- if (!existsSync21(targetPath)) {
35871
+ const targetPath = configPath ?? join26(homedir5(), ".ssh", "config");
35872
+ if (!existsSync23(targetPath)) {
35371
35873
  return [];
35372
35874
  }
35373
35875
  try {
35374
- const content = readFileSync18(targetPath, "utf-8");
35876
+ const content = readFileSync20(targetPath, "utf-8");
35375
35877
  const lines = content.split("\n");
35376
35878
  const hosts = [];
35377
35879
  let currentHosts = [];
@@ -35413,7 +35915,7 @@ function parseSshConfig(configPath) {
35413
35915
  return [];
35414
35916
  }
35415
35917
  }
35416
- function resolveSshHostG(host, execFn = spawnSync7) {
35918
+ function resolveSshHostG(host, execFn = spawnSync8) {
35417
35919
  try {
35418
35920
  const result = execFn("ssh", ["-G", host], { encoding: "utf-8" });
35419
35921
  if (result.status !== 0 || !result.stdout) {
@@ -35448,15 +35950,15 @@ function resolveSshHostG(host, execFn = spawnSync7) {
35448
35950
  }
35449
35951
  }
35450
35952
  function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
35451
- const resolved = resolve12(socketDir);
35452
- if (!existsSync21(resolved)) {
35453
- mkdirSync11(resolved, { recursive: true, mode: 448 });
35953
+ const resolved = resolve14(socketDir);
35954
+ if (!existsSync23(resolved)) {
35955
+ mkdirSync12(resolved, { recursive: true, mode: 448 });
35454
35956
  }
35455
35957
  return resolved;
35456
35958
  }
35457
35959
  function buildSshArgs(options) {
35458
35960
  const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
35459
- const controlPath = join24(socketDir, "%C");
35961
+ const controlPath = join26(socketDir, "%C");
35460
35962
  const persist2 = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
35461
35963
  const args = [
35462
35964
  "-o",
@@ -35479,9 +35981,9 @@ function buildSshArgs(options) {
35479
35981
  args.push(options.host);
35480
35982
  return args;
35481
35983
  }
35482
- function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync7) {
35984
+ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync8) {
35483
35985
  const resolvedDir = ensureSocketDir(socketDir);
35484
- const controlPath = join24(resolvedDir, "%C");
35986
+ const controlPath = join26(resolvedDir, "%C");
35485
35987
  try {
35486
35988
  const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
35487
35989
  encoding: "utf-8"
@@ -35491,9 +35993,9 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
35491
35993
  return false;
35492
35994
  }
35493
35995
  }
35494
- function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync7) {
35996
+ function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync8) {
35495
35997
  const resolvedDir = ensureSocketDir(socketDir);
35496
- const controlPath = join24(resolvedDir, "%C");
35998
+ const controlPath = join26(resolvedDir, "%C");
35497
35999
  try {
35498
36000
  const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
35499
36001
  encoding: "utf-8"
@@ -35509,7 +36011,7 @@ function pruneSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
35509
36011
  try {
35510
36012
  const entries = readdirSync11(resolvedDir);
35511
36013
  for (const entry of entries) {
35512
- const fullPath = join24(resolvedDir, entry);
36014
+ const fullPath = join26(resolvedDir, entry);
35513
36015
  try {
35514
36016
  const stat = statSync6(fullPath);
35515
36017
  if (stat.isSocket()) {
@@ -35525,7 +36027,7 @@ function pruneSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
35525
36027
  }
35526
36028
  function executeSshRun(params) {
35527
36029
  const startTime = Date.now();
35528
- const execSyncFn = params.execFn ?? spawnSync7;
36030
+ const execSyncFn = params.execFn ?? spawnSync8;
35529
36031
  if (params.action === "info") {
35530
36032
  if (params.host) {
35531
36033
  const hostInfo = resolveSshHostG(params.host, execSyncFn);