@kontextmind/kxm 0.7.121 → 0.7.123

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.
@@ -18560,8 +18560,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
18560
18560
  const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
18561
18561
  if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
18562
18562
  }
18563
- const join54 = objectValue(step.join);
18564
- const minimumPassed = join54 && typeof join54.minimumPassed === "number" ? join54.minimumPassed : void 0;
18563
+ const join56 = objectValue(step.join);
18564
+ const minimumPassed = join56 && typeof join56.minimumPassed === "number" ? join56.minimumPassed : void 0;
18565
18565
  if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
18566
18566
  const distinctBy = names(assignment?.distinctBy);
18567
18567
  if (distinctBy.length > 0) {
@@ -20863,7 +20863,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
20863
20863
  const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
20864
20864
  const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
20865
20865
  const assignments = compileAssignments(step, id, agent, sink);
20866
- const join54 = compileJoin(step, id, sink);
20866
+ const join56 = compileJoin(step, id, sink);
20867
20867
  const requiredEvidence = compileEvidence(step, id, sink);
20868
20868
  const transitions = compileTransitions(step, id, index, stepIndex, sink);
20869
20869
  const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
@@ -20891,7 +20891,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
20891
20891
  transitions: orderedTransitions,
20892
20892
  requiresPlanHash: requirePlanHash.includes(id),
20893
20893
  assignments,
20894
- join: join54
20894
+ join: join56
20895
20895
  };
20896
20896
  if (kind === "agent" || kind === "moa") {
20897
20897
  if (!agent) return void 0;
@@ -20941,15 +20941,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
20941
20941
  };
20942
20942
  }
20943
20943
  function compileJoin(step, stepId, sink) {
20944
- const join54 = objectValue2(step.join);
20945
- if (!join54) return { strategy: "all" };
20946
- const declared = stringValue2(join54.strategy);
20944
+ const join56 = objectValue2(step.join);
20945
+ if (!join56) return { strategy: "all" };
20946
+ const declared = stringValue2(join56.strategy);
20947
20947
  const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
20948
- const minimumPassed = compileOptionalCount(join54.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
20948
+ const minimumPassed = compileOptionalCount(join56.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
20949
20949
  const compiled = {
20950
20950
  strategy,
20951
20951
  ...minimumPassed !== void 0 ? { minimumPassed } : {},
20952
- ...typeof join54.cancelRemaining === "boolean" ? { cancelRemaining: join54.cancelRemaining } : {}
20952
+ ...typeof join56.cancelRemaining === "boolean" ? { cancelRemaining: join56.cancelRemaining } : {}
20953
20953
  };
20954
20954
  return compiled;
20955
20955
  }
@@ -30324,10 +30324,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
30324
30324
  * @param {string} flag
30325
30325
  * @private
30326
30326
  */
30327
- unknownOption(flag) {
30327
+ unknownOption(flag2) {
30328
30328
  if (this._allowUnknownOption) return;
30329
30329
  let suggestion = "";
30330
- if (flag.startsWith("--") && this._showSuggestionAfterError) {
30330
+ if (flag2.startsWith("--") && this._showSuggestionAfterError) {
30331
30331
  let candidateFlags = [];
30332
30332
  let command = this;
30333
30333
  do {
@@ -30335,9 +30335,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
30335
30335
  candidateFlags = candidateFlags.concat(moreFlags);
30336
30336
  command = command.parent;
30337
30337
  } while (command && !command._enablePositionalOptions);
30338
- suggestion = suggestSimilar(flag, candidateFlags);
30338
+ suggestion = suggestSimilar(flag2, candidateFlags);
30339
30339
  }
30340
- const message = `error: unknown option '${flag}'${suggestion}`;
30340
+ const message = `error: unknown option '${flag2}'${suggestion}`;
30341
30341
  this.error(message, { code: "commander.unknownOption" });
30342
30342
  }
30343
30343
  /**
@@ -34136,7 +34136,7 @@ async function cmdWorkflowDefinitions(runtime, options) {
34136
34136
  }
34137
34137
  async function cmdWorkflowAdd(runtime, workflowId, options) {
34138
34138
  const scope = options.scope ?? "local";
34139
- const refuse3 = (error, message, code = 2) => {
34139
+ const refuse4 = (error, message, code = 2) => {
34140
34140
  print(runtime.io, runtime.json, { ok: false, command: "workflow add", error, message }, `workflow add failed: ${message}`);
34141
34141
  return code;
34142
34142
  };
@@ -34144,12 +34144,12 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
34144
34144
  let content;
34145
34145
  if (options.template !== void 0) {
34146
34146
  if (options.file !== void 0 || options.pick !== void 0) {
34147
- return refuse3("workflow_add_conflict", "--template cannot be combined with --file or --pick");
34147
+ return refuse4("workflow_add_conflict", "--template cannot be combined with --file or --pick");
34148
34148
  }
34149
- if (!workflowId) return refuse3("workflow_id_required", "usage: kxm workflow add <workflowId> --template <name>");
34149
+ if (!workflowId) return refuse4("workflow_id_required", "usage: kxm workflow add <workflowId> --template <name>");
34150
34150
  const template = Object.hasOwn(WORKFLOW_TEMPLATES, options.template) ? WORKFLOW_TEMPLATES[options.template] : void 0;
34151
34151
  if (!template) {
34152
- return refuse3("workflow_template_unknown", `unknown template ${options.template}; choose ${Object.keys(WORKFLOW_TEMPLATES).join(", ")}`);
34152
+ return refuse4("workflow_template_unknown", `unknown template ${options.template}; choose ${Object.keys(WORKFLOW_TEMPLATES).join(", ")}`);
34153
34153
  }
34154
34154
  content = { ...template, ...options.description !== void 0 ? { description: options.description } : {} };
34155
34155
  } else if (!workflowId || options.pick) {
@@ -34169,7 +34169,7 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
34169
34169
  }
34170
34170
  const picked = await resolvePickItem(runtime.io, `Select a workflow template to add (${scope})`, candidates, options.pick, runtime.env);
34171
34171
  if (!picked) {
34172
- return refuse3("workflow_id_required", "provide a workflowId or select an available workflow with --pick <id>", 1);
34172
+ return refuse4("workflow_id_required", "provide a workflowId or select an available workflow with --pick <id>", 1);
34173
34173
  }
34174
34174
  workflowId ??= picked.id;
34175
34175
  if (options.file === void 0) {
@@ -34191,7 +34191,7 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
34191
34191
  if (scope === "local") {
34192
34192
  const projectRoot = discoverKxmProjectRoot(runtime.cwd);
34193
34193
  if (!projectRoot) {
34194
- return refuse3("project_not_found", "local workflows belong to a KXM project; run kxm init at the repository root, or pass --scope global");
34194
+ return refuse4("project_not_found", "local workflows belong to a KXM project; run kxm init at the repository root, or pass --scope global");
34195
34195
  }
34196
34196
  const issues = kxmWorkflowWriteIssues(projectRoot, workflowId, document);
34197
34197
  if (issues.length > 0) {
@@ -34226,7 +34226,7 @@ ${issues.map((entry) => ` ${entry.file}: ${entry.code}: ${entry.message}`).join
34226
34226
  );
34227
34227
  return 0;
34228
34228
  } catch (err) {
34229
- return refuse3("workflow_add_failed", err instanceof Error ? err.message : String(err), 1);
34229
+ return refuse4("workflow_add_failed", err instanceof Error ? err.message : String(err), 1);
34230
34230
  }
34231
34231
  }
34232
34232
  async function cmdWorkflowRemove(runtime, workflowId, options) {
@@ -36612,19 +36612,90 @@ async function cmdPluginInstall(runtime, options) {
36612
36612
  return ok ? 0 : 1;
36613
36613
  }
36614
36614
 
36615
+ // plugins/kxm/src/cli/docs.ts
36616
+ init_project_config();
36617
+ init_types();
36618
+ import { spawn as spawn4 } from "node:child_process";
36619
+ import { existsSync as existsSync29 } from "node:fs";
36620
+ import { join as join35 } from "node:path";
36621
+ var GENERATOR = "plans/kxm-roadmap/update-dashboard.mjs";
36622
+ var SERVER = "ops/docs-site/serve.py";
36623
+ function requireProject(runtime, command) {
36624
+ const root = discoverKxmProjectRoot(runtime.cwd);
36625
+ if (!root) {
36626
+ print(
36627
+ runtime.io,
36628
+ runtime.json,
36629
+ { ok: false, command, error: "project_required" },
36630
+ `kxm ${command} requires a KXM project (run kxm init first)`
36631
+ );
36632
+ return 1;
36633
+ }
36634
+ return root;
36635
+ }
36636
+ function requireFile(runtime, command, root, relative8, error) {
36637
+ const file = join35(root, relative8);
36638
+ if (existsSync29(file)) return file;
36639
+ print(
36640
+ runtime.io,
36641
+ runtime.json,
36642
+ { ok: false, command, error, path: relative8 },
36643
+ `kxm ${command} requires ${relative8}`
36644
+ );
36645
+ return 1;
36646
+ }
36647
+ function printCommand(runtime, command, line) {
36648
+ print(
36649
+ runtime.io,
36650
+ runtime.json,
36651
+ { ok: true, command, dryRun: true, detail: line },
36652
+ line
36653
+ );
36654
+ return 0;
36655
+ }
36656
+ function runInherited(command, args, cwd) {
36657
+ return new Promise((resolveExit) => {
36658
+ const child = spawn4(command, [...args], { cwd, stdio: "inherit" });
36659
+ child.once("error", () => resolveExit(1));
36660
+ child.once("exit", (code) => resolveExit(code ?? 1));
36661
+ });
36662
+ }
36663
+ async function cmdDocsBuild(runtime) {
36664
+ const command = "docs build";
36665
+ const root = requireProject(runtime, command);
36666
+ if (typeof root === "number") return root;
36667
+ const file = requireFile(runtime, command, root, GENERATOR, "docs_generator_missing");
36668
+ if (typeof file === "number") return file;
36669
+ const line = `node ${GENERATOR}`;
36670
+ if (runtime.dryRun) return printCommand(runtime, command, line);
36671
+ return runInherited(process.execPath, [file], root);
36672
+ }
36673
+ async function cmdDocsServe(runtime, options = {}) {
36674
+ const command = "docs serve";
36675
+ const root = requireProject(runtime, command);
36676
+ if (typeof root === "number") return root;
36677
+ const file = requireFile(runtime, command, root, SERVER, "docs_server_missing");
36678
+ if (typeof file === "number") return file;
36679
+ const args = [file];
36680
+ if (options.port !== void 0 && options.port !== "") args.push("--port", options.port);
36681
+ const line = ["python3", SERVER, ...args.slice(1)].join(" ");
36682
+ if (runtime.dryRun) return printCommand(runtime, command, line);
36683
+ return runInherited("python3", args, root);
36684
+ }
36685
+
36615
36686
  // plugins/kxm/src/cli/lanes.ts
36616
36687
  init_project_config();
36617
36688
  init_runtime_supervisor();
36618
36689
  init_types();
36619
36690
  import { spawnSync as spawnSync6 } from "node:child_process";
36620
- import { chmodSync as chmodSync6, existsSync as existsSync29, mkdirSync as mkdirSync24, readFileSync as readFileSync29, writeFileSync as writeFileSync22 } from "node:fs";
36621
- import { basename as basename8, dirname as dirname18, join as join35, resolve as resolve25 } from "node:path";
36691
+ import { chmodSync as chmodSync6, existsSync as existsSync30, mkdirSync as mkdirSync24, readFileSync as readFileSync29, writeFileSync as writeFileSync22 } from "node:fs";
36692
+ import { basename as basename8, dirname as dirname18, join as join36, resolve as resolve25 } from "node:path";
36622
36693
  var LANE_SCHEMA = "kxm.lanes.v1";
36623
36694
  var SHA_RE = /^[a-f0-9]{40,64}$/;
36624
36695
  var TIMESTAMP_RE = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]{1,9})?Z$/;
36625
36696
  var SETTLED_RUN = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
36626
36697
  function lanesFile(runtime) {
36627
- return join35(runtime.dirs.state, "lanes.json");
36698
+ return join36(runtime.dirs.state, "lanes.json");
36628
36699
  }
36629
36700
  function gitEnv() {
36630
36701
  return Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_")));
@@ -36672,7 +36743,7 @@ function isLaneFile(value) {
36672
36743
  }
36673
36744
  function loadLanes(runtime, command) {
36674
36745
  const file = lanesFile(runtime);
36675
- if (!existsSync29(file)) return { schema: LANE_SCHEMA, lanes: {} };
36746
+ if (!existsSync30(file)) return { schema: LANE_SCHEMA, lanes: {} };
36676
36747
  try {
36677
36748
  const parsed = JSON.parse(readFileSync29(file, "utf8"));
36678
36749
  if (!isLaneFile(parsed)) return refuse(runtime, command, "lanes_unreadable", `lane record ${file} is malformed`);
@@ -36731,7 +36802,7 @@ function withLaneCwd(runtime, unit, command = "lane") {
36731
36802
  const loaded = loadLanes(runtime, command);
36732
36803
  if (typeof loaded === "number") return loaded;
36733
36804
  const lane = loaded.lanes[unit];
36734
- if (!lane || !existsSync29(lane.path)) {
36805
+ if (!lane || !existsSync30(lane.path)) {
36735
36806
  return refuse(runtime, command, "lane_missing", `lane ${unit} is not recorded or its worktree is absent`, { unit });
36736
36807
  }
36737
36808
  return {
@@ -36802,7 +36873,7 @@ function aheadBehind(path4, baseSha) {
36802
36873
  return { behind: Number(match[1]), ahead: Number(match[2]) };
36803
36874
  }
36804
36875
  function laneView(unit, record) {
36805
- const exists = existsSync29(record.path);
36876
+ const exists = existsSync30(record.path);
36806
36877
  const counts = exists ? aheadBehind(record.path, record.baseSha) : { ahead: null, behind: null };
36807
36878
  return {
36808
36879
  unit,
@@ -36893,7 +36964,7 @@ async function cmdLaneCreate(runtime, unit, options = {}) {
36893
36964
  const loaded = loadLanes(runtime, command);
36894
36965
  if (typeof loaded === "number") return loaded;
36895
36966
  const path4 = laneWorktreePath(root, unit);
36896
- if (loaded.lanes[unit] || existsSync29(path4) || branchExists(root, unit)) {
36967
+ if (loaded.lanes[unit] || existsSync30(path4) || branchExists(root, unit)) {
36897
36968
  return refuse(runtime, command, "lane_exists", `lane ${unit} already exists`, { unit });
36898
36969
  }
36899
36970
  const baseSha = resolveBase(root, base);
@@ -36918,7 +36989,7 @@ async function cmdLaneCreate(runtime, unit, options = {}) {
36918
36989
  return refuse(runtime, command, "lane_git_failed", `git worktree add failed: ${added.stderr.trim().slice(0, 300)}`, { unit });
36919
36990
  }
36920
36991
  const recordedPath = discoverKxmProjectRoot(path4) ?? path4;
36921
- if (!existsSync29(join35(recordedPath, ".kxm", "project.yaml"))) {
36992
+ if (!existsSync30(join36(recordedPath, ".kxm", "project.yaml"))) {
36922
36993
  git2(root, ["worktree", "remove", "--force", path4]);
36923
36994
  return refuse(runtime, command, "lane_not_project", `lane ${recordedPath} has no .kxm/project.yaml; the worktree was removed`, { unit, path: recordedPath });
36924
36995
  }
@@ -36982,7 +37053,7 @@ async function cmdLaneDrop(runtime, unit, options = {}) {
36982
37053
  if (!record) return refuse(runtime, command, "lane_missing", `lane ${unit} is not recorded`, { unit });
36983
37054
  const force = options.force === true;
36984
37055
  if (!force) {
36985
- if (existsSync29(record.path)) {
37056
+ if (existsSync30(record.path)) {
36986
37057
  const dirty = porcelainCount(record.path);
36987
37058
  if (dirty === null) {
36988
37059
  return refuse(runtime, command, "lane_git_failed", `lane ${unit} worktree status could not be read`, { unit });
@@ -37001,7 +37072,7 @@ async function cmdLaneDrop(runtime, unit, options = {}) {
37001
37072
  ], `drop lane ${unit}; branch ${record.branch} is not deleted`);
37002
37073
  return 0;
37003
37074
  }
37004
- if (existsSync29(record.path)) {
37075
+ if (existsSync30(record.path)) {
37005
37076
  const removed = git2(root, ["worktree", "remove", ...force ? ["--force"] : [], record.path]);
37006
37077
  if (removed.status !== 0) {
37007
37078
  return refuse(runtime, command, "lane_git_failed", `git worktree remove failed: ${removed.stderr.trim().slice(0, 300)}`, { unit });
@@ -37071,8 +37142,8 @@ async function cmdLaneRun(runtime, unit, options) {
37071
37142
  init_project_config();
37072
37143
  init_repo_root();
37073
37144
  init_types();
37074
- import { spawn as spawn4 } from "node:child_process";
37075
- import { join as join36 } from "node:path";
37145
+ import { spawn as spawn5 } from "node:child_process";
37146
+ import { join as join37 } from "node:path";
37076
37147
  function childEnv() {
37077
37148
  const env = {};
37078
37149
  for (const [name, value] of Object.entries(process.env)) {
@@ -37091,7 +37162,7 @@ function cmdLand(runtime, options = {}) {
37091
37162
  if (!root) {
37092
37163
  return Promise.resolve(refuse2(runtime, "project_required", "land requires a KXM project (run kxm init first)"));
37093
37164
  }
37094
- const script = join36(findKxmRepoRoot(import.meta.url), "scripts", "pr-land.mjs");
37165
+ const script = join37(findKxmRepoRoot(import.meta.url), "scripts", "pr-land.mjs");
37095
37166
  const args = [script];
37096
37167
  if (options.pr) args.push("--pr", options.pr);
37097
37168
  if (options.stage) args.push("--stage", options.stage);
@@ -37099,7 +37170,7 @@ function cmdLand(runtime, options = {}) {
37099
37170
  if (runtime.json) args.push("--json");
37100
37171
  if (runtime.dryRun) args.push("--dry-run");
37101
37172
  return new Promise((resolveExit) => {
37102
- const child = spawn4(process.execPath, args, { cwd: root, env: childEnv(), windowsHide: true });
37173
+ const child = spawn5(process.execPath, args, { cwd: root, env: childEnv(), windowsHide: true });
37103
37174
  child.stdout.on("data", (chunk) => runtime.io.stdout(chunk.toString("utf8")));
37104
37175
  child.stderr.on("data", (chunk) => runtime.io.stderr(chunk.toString("utf8")));
37105
37176
  child.once("error", () => resolveExit(1));
@@ -37107,11 +37178,116 @@ function cmdLand(runtime, options = {}) {
37107
37178
  });
37108
37179
  }
37109
37180
 
37181
+ // plugins/kxm/src/cli/assign.ts
37182
+ init_project_config();
37183
+ init_types();
37184
+ import { spawnSync as spawnSync7 } from "node:child_process";
37185
+ import { existsSync as existsSync31 } from "node:fs";
37186
+ import { join as join38 } from "node:path";
37187
+ var kxmAssignCliSeams = {};
37188
+ var RUNNER_REL = "scripts/assignment-run.mjs";
37189
+ function refuse3(runtime, command, error, text) {
37190
+ print(runtime.io, runtime.json, { ok: false, command, error }, text);
37191
+ return 1;
37192
+ }
37193
+ function flag(value) {
37194
+ if (value === void 0) throw new Error("assign invocation missing a parsed flag");
37195
+ return value;
37196
+ }
37197
+ function runnerArgv(subcommand, args) {
37198
+ switch (subcommand) {
37199
+ case "run":
37200
+ return ["run", "--manifest", flag(args.manifest)];
37201
+ case "witness":
37202
+ return ["witness", "--record-dir", flag(args.recordDir)];
37203
+ case "plan-current":
37204
+ return [
37205
+ "plan-current",
37206
+ "--task-dir",
37207
+ flag(args.taskDir),
37208
+ "--plan",
37209
+ flag(args.plan),
37210
+ "--sha256",
37211
+ flag(args.sha256),
37212
+ "--base-commit",
37213
+ flag(args.baseCommit),
37214
+ "--expected-generation",
37215
+ flag(args.expectedGeneration)
37216
+ ];
37217
+ case "attribute":
37218
+ return [
37219
+ "attribute",
37220
+ "--task-dir",
37221
+ flag(args.taskDir),
37222
+ "--record-dir",
37223
+ flag(args.recordDir),
37224
+ "--class",
37225
+ flag(args.classification),
37226
+ "--explanation-file",
37227
+ flag(args.explanationFile)
37228
+ ];
37229
+ case "observe-cost":
37230
+ return ["observe-cost", "--task-dir", flag(args.taskDir), "--input", flag(args.input)];
37231
+ case "accept": {
37232
+ const argv = [
37233
+ "accept",
37234
+ "--task-dir",
37235
+ flag(args.taskDir),
37236
+ "--commit",
37237
+ flag(args.commit),
37238
+ "--record-dir",
37239
+ flag(args.recordDir)
37240
+ ];
37241
+ for (const critic of args.critics ?? []) argv.push("--critic", critic);
37242
+ if (args.observedPr !== void 0) argv.push("--observed-pr", args.observedPr);
37243
+ if (args.observedCi !== void 0) argv.push("--observed-ci", args.observedCi);
37244
+ return argv;
37245
+ }
37246
+ case "change-report":
37247
+ return ["change-report", "--task-dir", flag(args.taskDir)];
37248
+ default: {
37249
+ const unreachable = subcommand;
37250
+ throw new Error(`unknown assign verb ${String(unreachable)}`);
37251
+ }
37252
+ }
37253
+ }
37254
+ async function cmdAssign(runtime, subcommand, args) {
37255
+ const command = `assign ${subcommand}`;
37256
+ const root = discoverKxmProjectRoot(runtime.cwd);
37257
+ if (!root) return refuse3(runtime, command, "project_required", `${command} requires a KXM project (run kxm init first)`);
37258
+ if (!existsSync31(join38(root, "scripts", "assignment-run.mjs"))) {
37259
+ return refuse3(runtime, command, "assign_runner_missing", `${command} requires scripts/assignment-run.mjs in the project root`);
37260
+ }
37261
+ const argv = ["node", RUNNER_REL, ...runnerArgv(subcommand, args)];
37262
+ if (runtime.dryRun) {
37263
+ const payload = { schema: CLI_RESULT_SCHEMA, ok: true, command, dryRun: true, argv };
37264
+ runtime.io.stdout(runtime.json ? `${JSON.stringify(payload)}
37265
+ ` : `${argv.join(" ")}
37266
+ `);
37267
+ return 0;
37268
+ }
37269
+ const spawn6 = kxmAssignCliSeams.spawn ?? ((commandName, commandArgs, options) => {
37270
+ const result2 = spawnSync7(commandName, commandArgs, {
37271
+ cwd: options.cwd,
37272
+ stdio: options.stdio,
37273
+ env: options.env,
37274
+ windowsHide: true
37275
+ });
37276
+ return { status: result2.status, ...result2.error ? { error: result2.error } : {} };
37277
+ });
37278
+ const result = spawn6("node", argv.slice(1), { cwd: root, stdio: "inherit", env: runtime.env });
37279
+ if (result.status === null) {
37280
+ const detail = result.error?.message ?? "the assignment runner could not be started";
37281
+ return refuse3(runtime, command, "assign_spawn_failed", detail);
37282
+ }
37283
+ return result.status;
37284
+ }
37285
+
37110
37286
  // plugins/kxm/src/cli/hub.ts
37111
37287
  init_redact();
37112
37288
  import { randomUUID as randomUUID13 } from "node:crypto";
37113
- import { existsSync as existsSync35, mkdirSync as mkdirSync28, readFileSync as readFileSync35, readdirSync as readdirSync12, rmSync as rmSync11, writeFileSync as writeFileSync25 } from "node:fs";
37114
- import { join as join46, resolve as resolve28 } from "node:path";
37289
+ import { existsSync as existsSync37, mkdirSync as mkdirSync28, readFileSync as readFileSync35, readdirSync as readdirSync12, rmSync as rmSync11, writeFileSync as writeFileSync25 } from "node:fs";
37290
+ import { join as join48, resolve as resolve28 } from "node:path";
37115
37291
  init_hub_env();
37116
37292
  init_envelope();
37117
37293
 
@@ -42809,7 +42985,7 @@ import * as path2 from "node:path";
42809
42985
 
42810
42986
  // node_modules/@earendil-works/pi-tui/dist/native-module-path.js
42811
42987
  import { createRequire as createRequire2 } from "node:module";
42812
- import { dirname as dirname19, join as join37 } from "node:path";
42988
+ import { dirname as dirname19, join as join39 } from "node:path";
42813
42989
  import { fileURLToPath as fileURLToPath2 } from "node:url";
42814
42990
  var moduleRequire = createRequire2(import.meta.url);
42815
42991
  var TUI_PACKAGE_NAME = "@earendil-works/pi-tui";
@@ -42818,10 +42994,10 @@ function getNativeModuleCandidates(nativePath, options = {}) {
42818
42994
  const candidates = [];
42819
42995
  try {
42820
42996
  const packageEntry = (options.resolvePackage ?? moduleRequire.resolve)(TUI_PACKAGE_NAME);
42821
- candidates.push(join37(dirname19(packageEntry), "..", nativePath));
42997
+ candidates.push(join39(dirname19(packageEntry), "..", nativePath));
42822
42998
  } catch {
42823
42999
  }
42824
- candidates.push(join37(moduleDir, "..", nativePath), join37(moduleDir, nativePath), join37(dirname19(options.execPath ?? process.execPath), nativePath));
43000
+ candidates.push(join39(moduleDir, "..", nativePath), join39(moduleDir, nativePath), join39(dirname19(options.execPath ?? process.execPath), nativePath));
42825
43001
  return Array.from(new Set(candidates));
42826
43002
  }
42827
43003
 
@@ -45552,8 +45728,8 @@ var MAX_RENDER_WRITE_CHARS = 1024 * 1024;
45552
45728
 
45553
45729
  // plugins/kxm/src/tui.ts
45554
45730
  import { mkdirSync as mkdirSync25 } from "node:fs";
45555
- import { join as join41, resolve as resolve27, dirname as dirname20 } from "node:path";
45556
- import { spawnSync as spawnSync7 } from "node:child_process";
45731
+ import { join as join43, resolve as resolve27, dirname as dirname20 } from "node:path";
45732
+ import { spawnSync as spawnSync8 } from "node:child_process";
45557
45733
 
45558
45734
  // packages/core/tui/src/types/surface.ts
45559
45735
  var KXM_TUI_LIMITS = Object.freeze({
@@ -45696,9 +45872,9 @@ var SHARED_EFFECT_KINDS = Object.freeze([
45696
45872
  // plugins/kxm/src/local-snapshot.ts
45697
45873
  init_sqlite();
45698
45874
  init_telemetry();
45699
- import { existsSync as existsSync30, readdirSync as readdirSync11, readFileSync as readFileSync30 } from "node:fs";
45875
+ import { existsSync as existsSync32, readdirSync as readdirSync11, readFileSync as readFileSync30 } from "node:fs";
45700
45876
  import { homedir as homedir6 } from "node:os";
45701
- import { isAbsolute as isAbsolute9, join as join40, resolve as resolve26 } from "node:path";
45877
+ import { isAbsolute as isAbsolute9, join as join42, resolve as resolve26 } from "node:path";
45702
45878
  var DEFAULT_BUSY_TIMEOUT_MS = 5e3;
45703
45879
  var RUNTIME_PROJECT_KEY = /^[A-Za-z0-9_-][A-Za-z0-9._-]*$/;
45704
45880
  function processExists2(pid) {
@@ -45823,36 +45999,36 @@ function readOpenMessageMetadata(database, where = OPEN_MESSAGE_WHERE, params =
45823
45999
  return messages;
45824
46000
  }
45825
46001
  function resolveKxmSnapshotPaths(cwd, env = process.env) {
45826
- const stateDir = env.KXM_STATE_DIR?.trim() || join40(cwd, ".kxm", "state");
46002
+ const stateDir = env.KXM_STATE_DIR?.trim() || join42(cwd, ".kxm", "state");
45827
46003
  const configured = env.KXM_DATA_PATH?.trim();
45828
- const dataPath = configured ? resolve26(cwd, configured) : join40(stateDir, "kxm.db");
46004
+ const dataPath = configured ? resolve26(cwd, configured) : join42(stateDir, "kxm.db");
45829
46005
  return { dataPath, stateDir };
45830
46006
  }
45831
46007
  function resolveKxmStateRoot(stateDir, options) {
45832
- if (options?.kxmStateRoot && existsSync30(options.kxmStateRoot)) {
46008
+ if (options?.kxmStateRoot && existsSync32(options.kxmStateRoot)) {
45833
46009
  return resolve26(options.kxmStateRoot);
45834
46010
  }
45835
- if (existsSync30(join40(stateDir, "runtime", "registry.db")) || existsSync30(join40(stateDir, "runtime", "projects"))) {
46011
+ if (existsSync32(join42(stateDir, "runtime", "registry.db")) || existsSync32(join42(stateDir, "runtime", "projects"))) {
45836
46012
  return stateDir;
45837
46013
  }
45838
46014
  const env = options?.env ?? process.env;
45839
46015
  const explicit = env.KXM_STATE_HOME?.trim() || env.KXM_USER_STATE_DIR?.trim() || env.KXM_STATE_ROOT?.trim();
45840
- if (explicit && isAbsolute9(explicit) && existsSync30(resolve26(explicit))) {
46016
+ if (explicit && isAbsolute9(explicit) && existsSync32(resolve26(explicit))) {
45841
46017
  return resolve26(explicit);
45842
46018
  }
45843
46019
  let base;
45844
46020
  if (process.platform === "win32") {
45845
46021
  const localAppData = env.LOCALAPPDATA?.trim();
45846
- base = localAppData && isAbsolute9(localAppData) ? localAppData : join40(homedir6(), "AppData", "Local");
46022
+ base = localAppData && isAbsolute9(localAppData) ? localAppData : join42(homedir6(), "AppData", "Local");
45847
46023
  base = resolve26(base, "KXM");
45848
46024
  } else if (process.platform === "darwin") {
45849
46025
  base = resolve26(homedir6(), "Library", "Application Support", "KXM");
45850
46026
  } else {
45851
46027
  const xdgState = env.XDG_STATE_HOME?.trim();
45852
- base = xdgState && isAbsolute9(xdgState) ? xdgState : join40(homedir6(), ".local", "state");
46028
+ base = xdgState && isAbsolute9(xdgState) ? xdgState : join42(homedir6(), ".local", "state");
45853
46029
  base = resolve26(base, "kxm");
45854
46030
  }
45855
- if (existsSync30(base)) return base;
46031
+ if (existsSync32(base)) return base;
45856
46032
  return void 0;
45857
46033
  }
45858
46034
  function readRuntimeRuns(eventDb, projectId) {
@@ -45885,7 +46061,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
45885
46061
  let legacyRuns = [];
45886
46062
  let legacyRunTotal = 0;
45887
46063
  let plans = [];
45888
- if (existsSync30(dataPath)) {
46064
+ if (existsSync32(dataPath)) {
45889
46065
  hasLegacy = true;
45890
46066
  const database = openReadOnlyDatabase(dataPath);
45891
46067
  try {
@@ -45916,11 +46092,11 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
45916
46092
  let kxmRunTotal = 0;
45917
46093
  const kxmStateRoot = scope && !scope.runtimeProjectId ? void 0 : resolveKxmStateRoot(stateDir, options);
45918
46094
  if (kxmStateRoot) {
45919
- const runtimeDir = join40(kxmStateRoot, "runtime");
45920
- const registryDbPath = join40(runtimeDir, "registry.db");
45921
- const projectsDir = join40(runtimeDir, "projects");
46095
+ const runtimeDir = join42(kxmStateRoot, "runtime");
46096
+ const registryDbPath = join42(runtimeDir, "registry.db");
46097
+ const projectsDir = join42(runtimeDir, "projects");
45922
46098
  const projectKeys = /* @__PURE__ */ new Set();
45923
- if (existsSync30(registryDbPath)) {
46099
+ if (existsSync32(registryDbPath)) {
45924
46100
  hasKxm = true;
45925
46101
  try {
45926
46102
  const regDb = openReadOnlyDatabase(registryDbPath);
@@ -45936,7 +46112,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
45936
46112
  } catch {
45937
46113
  }
45938
46114
  }
45939
- if (!scope && existsSync30(projectsDir)) {
46115
+ if (!scope && existsSync32(projectsDir)) {
45940
46116
  try {
45941
46117
  for (const entry of readdirSync11(projectsDir, { withFileTypes: true })) {
45942
46118
  if (entry.isDirectory()) {
@@ -45948,8 +46124,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
45948
46124
  }
45949
46125
  for (const key of projectKeys) {
45950
46126
  if (scope && !RUNTIME_PROJECT_KEY.test(key)) continue;
45951
- const eventDbPath = join40(projectsDir, key, "run-events.db");
45952
- if (existsSync30(eventDbPath)) {
46127
+ const eventDbPath = join42(projectsDir, key, "run-events.db");
46128
+ if (existsSync32(eventDbPath)) {
45953
46129
  hasKxm = true;
45954
46130
  try {
45955
46131
  const eventDb = openReadOnlyDatabase(eventDbPath);
@@ -45967,10 +46143,10 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
45967
46143
  }
45968
46144
  }
45969
46145
  const pids = [];
45970
- if (existsSync30(stateDir)) {
46146
+ if (existsSync32(stateDir)) {
45971
46147
  for (const file of readdirSync11(stateDir).filter((name) => name.endsWith(".pid"))) {
45972
46148
  try {
45973
- const record = JSON.parse(readFileSync30(join40(stateDir, file), "utf8"));
46149
+ const record = JSON.parse(readFileSync30(join42(stateDir, file), "utf8"));
45974
46150
  pids.push({
45975
46151
  file,
45976
46152
  ...record.role ? { role: record.role } : {},
@@ -46009,8 +46185,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
46009
46185
  } else {
46010
46186
  source = "legacy";
46011
46187
  }
46012
- const telemetryFile = join40(stateDir, "telemetry.jsonl");
46013
- const spend = existsSync30(telemetryFile) ? readRoutingRecords(telemetryFile) : [];
46188
+ const telemetryFile = join42(stateDir, "telemetry.jsonl");
46189
+ const spend = existsSync32(telemetryFile) ? readRoutingRecords(telemetryFile) : [];
46014
46190
  return {
46015
46191
  source,
46016
46192
  agents: agents.sort((a, b2) => Number(b2.online) - Number(a.online) || a.name.localeCompare(b2.name)),
@@ -46110,16 +46286,16 @@ function applyMeshTuiKey(view, key, itemCount = 0) {
46110
46286
  function copyToClipboard(text) {
46111
46287
  try {
46112
46288
  if (process.platform === "darwin") {
46113
- const proc = spawnSync7("pbcopy", { input: text, encoding: "utf8", windowsHide: true });
46289
+ const proc = spawnSync8("pbcopy", { input: text, encoding: "utf8", windowsHide: true });
46114
46290
  return proc.status === 0;
46115
46291
  }
46116
46292
  if (process.platform === "win32") {
46117
- const proc = spawnSync7("clip", { input: text, encoding: "utf8", windowsHide: true });
46293
+ const proc = spawnSync8("clip", { input: text, encoding: "utf8", windowsHide: true });
46118
46294
  return proc.status === 0;
46119
46295
  }
46120
- const wl = spawnSync7("wl-copy", [text], { encoding: "utf8", windowsHide: true });
46296
+ const wl = spawnSync8("wl-copy", [text], { encoding: "utf8", windowsHide: true });
46121
46297
  if (wl.status === 0) return true;
46122
- const xclip = spawnSync7("xclip", ["-selection", "clipboard"], { input: text, encoding: "utf8", windowsHide: true });
46298
+ const xclip = spawnSync8("xclip", ["-selection", "clipboard"], { input: text, encoding: "utf8", windowsHide: true });
46123
46299
  return xclip.status === 0;
46124
46300
  } catch {
46125
46301
  return false;
@@ -46127,7 +46303,7 @@ function copyToClipboard(text) {
46127
46303
  }
46128
46304
  function spawnDegradeWorktree(repoRoot, runId, options) {
46129
46305
  const runner = options?.execFn ?? ((cmd, args) => {
46130
- const res = spawnSync7(cmd, args, {
46306
+ const res = spawnSync8(cmd, args, {
46131
46307
  cwd: repoRoot,
46132
46308
  encoding: "utf8",
46133
46309
  windowsHide: true,
@@ -46144,7 +46320,7 @@ function spawnDegradeWorktree(repoRoot, runId, options) {
46144
46320
  const cleanRunId = runId.replace(/^run_/, "");
46145
46321
  const desc = options?.description ? slugifyBranchPart(options.description, 30) : "degrade";
46146
46322
  const branchName = `kxm/run-${cleanRunId}-${desc}`;
46147
- const relativeWtPath = join41(".kxm", "worktrees", `run-${cleanRunId}-${desc}`);
46323
+ const relativeWtPath = join43(".kxm", "worktrees", `run-${cleanRunId}-${desc}`);
46148
46324
  const absoluteWtPath = resolve27(repoRoot, relativeWtPath);
46149
46325
  const jumpCommand = `cd "${absoluteWtPath}"`;
46150
46326
  try {
@@ -46911,10 +47087,10 @@ async function runMeshTui(input) {
46911
47087
  }
46912
47088
 
46913
47089
  // plugins/kxm/src/session-work.ts
46914
- import { spawnSync as spawnSync8 } from "node:child_process";
47090
+ import { spawnSync as spawnSync9 } from "node:child_process";
46915
47091
  import { randomUUID as randomUUID12 } from "node:crypto";
46916
- import { existsSync as existsSync31, mkdirSync as mkdirSync26, readFileSync as readFileSync31, renameSync as renameSync8, writeFileSync as writeFileSync23 } from "node:fs";
46917
- import { join as join42 } from "node:path";
47092
+ import { existsSync as existsSync33, mkdirSync as mkdirSync26, readFileSync as readFileSync31, renameSync as renameSync8, writeFileSync as writeFileSync23 } from "node:fs";
47093
+ import { join as join44 } from "node:path";
46918
47094
  init_hub_binding();
46919
47095
  init_telemetry();
46920
47096
  var MAX_SESSION_BRIEF_TASKS = 5;
@@ -46972,10 +47148,10 @@ function formatShipLine(ship) {
46972
47148
  }
46973
47149
  function readGitShip(cwd) {
46974
47150
  try {
46975
- const dirty = spawnSync8("git", ["-C", cwd, "status", "--porcelain"], { encoding: "utf8", windowsHide: true });
47151
+ const dirty = spawnSync9("git", ["-C", cwd, "status", "--porcelain"], { encoding: "utf8", windowsHide: true });
46976
47152
  if (dirty.status !== 0) return void 0;
46977
47153
  const isDirty = dirty.stdout.trim().length > 0;
46978
- const upstream = spawnSync8("git", ["-C", cwd, "rev-list", "--count", "@{u}..HEAD"], { encoding: "utf8", windowsHide: true });
47154
+ const upstream = spawnSync9("git", ["-C", cwd, "rev-list", "--count", "@{u}..HEAD"], { encoding: "utf8", windowsHide: true });
46979
47155
  if (upstream.status === 0) {
46980
47156
  return {
46981
47157
  dirty: isDirty,
@@ -46983,9 +47159,9 @@ function readGitShip(cwd) {
46983
47159
  };
46984
47160
  }
46985
47161
  for (const baseRef of ["origin/HEAD", "main", "origin/main", "master", "origin/master"]) {
46986
- const mb = spawnSync8("git", ["-C", cwd, "merge-base", baseRef, "HEAD"], { encoding: "utf8", windowsHide: true });
47162
+ const mb = spawnSync9("git", ["-C", cwd, "merge-base", baseRef, "HEAD"], { encoding: "utf8", windowsHide: true });
46987
47163
  if (mb.status === 0 && mb.stdout.trim()) {
46988
- const count = spawnSync8("git", ["-C", cwd, "rev-list", "--count", `${mb.stdout.trim()}..HEAD`], { encoding: "utf8", windowsHide: true });
47164
+ const count = spawnSync9("git", ["-C", cwd, "rev-list", "--count", `${mb.stdout.trim()}..HEAD`], { encoding: "utf8", windowsHide: true });
46989
47165
  if (count.status === 0) {
46990
47166
  return {
46991
47167
  dirty: isDirty,
@@ -47073,9 +47249,9 @@ function buildSessionBrief(snapshot, current, hub, ship, updateLatest, cost, ses
47073
47249
  };
47074
47250
  }
47075
47251
  function readCachedSessionBrief(stateDir) {
47076
- const file = join42(stateDir, "session-brief.json");
47252
+ const file = join44(stateDir, "session-brief.json");
47077
47253
  try {
47078
- if (!existsSync31(file)) return void 0;
47254
+ if (!existsSync33(file)) return void 0;
47079
47255
  const raw = readFileSync31(file, "utf8");
47080
47256
  const parsed = JSON.parse(raw);
47081
47257
  if (parsed && parsed.schema === "kxm.session-brief.v1" && typeof parsed.generatedAt === "string") {
@@ -47092,7 +47268,7 @@ function readCachedSessionBrief(stateDir) {
47092
47268
  function writeCachedSessionBrief(stateDir, brief) {
47093
47269
  try {
47094
47270
  mkdirSync26(stateDir, { recursive: true, mode: 448 });
47095
- const file = join42(stateDir, "session-brief.json");
47271
+ const file = join44(stateDir, "session-brief.json");
47096
47272
  const tmp = `${file}.tmp.${randomUUID12().slice(0, 8)}`;
47097
47273
  writeFileSync23(tmp, JSON.stringify(brief, null, 2), { encoding: "utf8", mode: 384 });
47098
47274
  renameSync8(tmp, file);
@@ -47101,8 +47277,8 @@ function writeCachedSessionBrief(stateDir, brief) {
47101
47277
  }
47102
47278
  function estimateSessionCost(stateDir) {
47103
47279
  try {
47104
- const telemetryFile = join42(stateDir, "telemetry.jsonl");
47105
- if (!existsSync31(telemetryFile)) return void 0;
47280
+ const telemetryFile = join44(stateDir, "telemetry.jsonl");
47281
+ if (!existsSync33(telemetryFile)) return void 0;
47106
47282
  const records = readRoutingRecords(telemetryFile);
47107
47283
  if (records.length === 0) return void 0;
47108
47284
  let totalCost = 0;
@@ -47274,11 +47450,11 @@ init_hub_binding();
47274
47450
 
47275
47451
  // plugins/kxm/src/kxm-install-kind.ts
47276
47452
  init_bindings();
47277
- import { existsSync as existsSync32, readFileSync as readFileSync32 } from "node:fs";
47278
- import { dirname as dirname21, join as join43 } from "node:path";
47453
+ import { existsSync as existsSync34, readFileSync as readFileSync32 } from "node:fs";
47454
+ import { dirname as dirname21, join as join45 } from "node:path";
47279
47455
  function packageIsKxm(root) {
47280
47456
  try {
47281
- const pkg = JSON.parse(readFileSync32(join43(root, "package.json"), "utf8"));
47457
+ const pkg = JSON.parse(readFileSync32(join45(root, "package.json"), "utf8"));
47282
47458
  return pkg.name === "@kontextmind/kxm";
47283
47459
  } catch {
47284
47460
  return false;
@@ -47327,12 +47503,12 @@ function report(kind, root) {
47327
47503
  return { kind, root, instruction: installKindInstruction(kind, root) };
47328
47504
  }
47329
47505
  function classifyInstallRoot(probe) {
47330
- const piGitRoot = join43(probe.homeDir, ".pi", "agent", "git");
47506
+ const piGitRoot = join45(probe.homeDir, ".pi", "agent", "git");
47331
47507
  if (isUnder(probe.repoRoot, piGitRoot, probe.platform)) return report("pi-git", probe.repoRoot);
47332
- const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() || join43(probe.homeDir, ".claude");
47333
- const pluginsRoot = join43(claudeHome, "plugins");
47508
+ const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() || join45(probe.homeDir, ".claude");
47509
+ const pluginsRoot = join45(claudeHome, "plugins");
47334
47510
  if (isUnder(probe.moduleDir, pluginsRoot, probe.platform)) return report("claude-marketplace", probe.moduleDir);
47335
- const hasGit = existsSync32(join43(probe.repoRoot, ".git"));
47511
+ const hasGit = existsSync34(join45(probe.repoRoot, ".git"));
47336
47512
  if (hasGit && packageIsKxm(probe.repoRoot)) return report("source", probe.repoRoot);
47337
47513
  if (isNpmPackageLayout(probe.repoRoot, probe.platform) && packageIsKxm(probe.repoRoot) && !hasGit) {
47338
47514
  return report("npm-package", probe.repoRoot);
@@ -47356,12 +47532,12 @@ init_bindings();
47356
47532
 
47357
47533
  // plugins/kxm/src/kxm-update-config.ts
47358
47534
  var import_yaml16 = __toESM(require_dist(), 1);
47359
- import { existsSync as existsSync33, readFileSync as readFileSync33 } from "node:fs";
47360
- import { join as join44 } from "node:path";
47535
+ import { existsSync as existsSync35, readFileSync as readFileSync33 } from "node:fs";
47536
+ import { join as join46 } from "node:path";
47361
47537
  init_bindings();
47362
47538
  function loadKxmUpdateConfig(env = process.env) {
47363
- const path4 = join44(kxmUserStateRoot({ env }), "update.yaml");
47364
- if (!existsSync33(path4)) return { schema: KXM_UPDATE_SCHEMA, auto: false, source: "github" };
47539
+ const path4 = join46(kxmUserStateRoot({ env }), "update.yaml");
47540
+ if (!existsSync35(path4)) return { schema: KXM_UPDATE_SCHEMA, auto: false, source: "github" };
47365
47541
  let parsed;
47366
47542
  try {
47367
47543
  parsed = (0, import_yaml16.parse)(readFileSync33(path4, "utf8"));
@@ -47392,8 +47568,8 @@ function loadKxmUpdateConfig(env = process.env) {
47392
47568
  // plugins/kxm/src/session.ts
47393
47569
  init_protocol();
47394
47570
  init_envelope();
47395
- import { existsSync as existsSync34, mkdirSync as mkdirSync27, readFileSync as readFileSync34, writeFileSync as writeFileSync24 } from "node:fs";
47396
- import { join as join45 } from "node:path";
47571
+ import { existsSync as existsSync36, mkdirSync as mkdirSync27, readFileSync as readFileSync34, writeFileSync as writeFileSync24 } from "node:fs";
47572
+ import { join as join47 } from "node:path";
47397
47573
  var SESSION_SCHEMA = "kxm.session.v1";
47398
47574
  var SessionConfigError = class extends Error {
47399
47575
  code = "session_config_invalid";
@@ -47403,12 +47579,12 @@ var SessionConfigError = class extends Error {
47403
47579
  }
47404
47580
  };
47405
47581
  function workflowAssetDirs(assetsDir, workflowId) {
47406
- const root = join45(assetsDir, "workflows", workflowId);
47407
- return [root, join45(root, "inputs"), join45(root, "outputs"), join45(root, "generated")];
47582
+ const root = join47(assetsDir, "workflows", workflowId);
47583
+ return [root, join47(root, "inputs"), join47(root, "outputs"), join47(root, "generated")];
47408
47584
  }
47409
47585
  function sessionAssetDirs(assetsDir, sessionId) {
47410
- const root = join45(assetsDir, "sessions", sessionId);
47411
- return [root, join45(root, "inputs"), join45(root, "outputs")];
47586
+ const root = join47(assetsDir, "sessions", sessionId);
47587
+ return [root, join47(root, "inputs"), join47(root, "outputs")];
47412
47588
  }
47413
47589
  function rosterNames(configDir) {
47414
47590
  return [...loadRosterMap(configDir).values()].map((row) => String(row.name));
@@ -47458,7 +47634,7 @@ function workerFromRosterRow(name, row, project) {
47458
47634
  function loadRosterMap(configDir) {
47459
47635
  const byName = /* @__PURE__ */ new Map();
47460
47636
  for (const [file, key] of [["agents.json", "agents"], ["gates.json", "gates"]]) {
47461
- const path4 = join45(configDir, file);
47637
+ const path4 = join47(configDir, file);
47462
47638
  for (const row of loadRoster(path4, key)) {
47463
47639
  const name = String(row.name).trim();
47464
47640
  const lowered = name.toLowerCase();
@@ -47472,7 +47648,7 @@ function loadRosterMap(configDir) {
47472
47648
  return byName;
47473
47649
  }
47474
47650
  function loadRoster(path4, key) {
47475
- if (!existsSync34(path4)) return [];
47651
+ if (!existsSync36(path4)) return [];
47476
47652
  let parsed;
47477
47653
  try {
47478
47654
  parsed = JSON.parse(readFileSync34(path4, "utf8"));
@@ -47500,7 +47676,7 @@ function loadRoster(path4, key) {
47500
47676
  });
47501
47677
  }
47502
47678
  function createSession(input) {
47503
- const assetDir = input.mode === "workflow" && input.workflowId ? join45("assets", "workflows", input.workflowId) : join45("assets", "sessions", input.id);
47679
+ const assetDir = input.mode === "workflow" && input.workflowId ? join47("assets", "workflows", input.workflowId) : join47("assets", "sessions", input.id);
47504
47680
  return {
47505
47681
  schema: SESSION_SCHEMA,
47506
47682
  id: input.id,
@@ -47513,8 +47689,8 @@ function createSession(input) {
47513
47689
  };
47514
47690
  }
47515
47691
  function writeSession(assetsDir, session, dryRun = false) {
47516
- const dir = join45(assetsDir, "sessions", session.id);
47517
- const path4 = join45(dir, "session.json");
47692
+ const dir = join47(assetsDir, "sessions", session.id);
47693
+ const path4 = join47(dir, "session.json");
47518
47694
  if (!dryRun) {
47519
47695
  mkdirSync27(dir, { recursive: true });
47520
47696
  writeFileSync24(path4, `${JSON.stringify(session, null, 2)}
@@ -47570,9 +47746,9 @@ function moduleInstallRoot() {
47570
47746
  }
47571
47747
  }
47572
47748
  function warnIgnoredProjectUpdateYaml(runtime) {
47573
- const projectFile = join46(runtime.dirs.workspace, "update.yaml");
47574
- if (!existsSync35(projectFile)) return;
47575
- const userFile = join46(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
47749
+ const projectFile = join48(runtime.dirs.workspace, "update.yaml");
47750
+ if (!existsSync37(projectFile)) return;
47751
+ const userFile = join48(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
47576
47752
  runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}
47577
47753
  `);
47578
47754
  }
@@ -47620,7 +47796,7 @@ async function cmdDash(runtime, options = {}) {
47620
47796
  return 2;
47621
47797
  }
47622
47798
  const screen = requested;
47623
- const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join46(runtime.dirs.state, "kxm.db"));
47799
+ const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join48(runtime.dirs.state, "kxm.db"));
47624
47800
  if (runtime.dryRun) {
47625
47801
  print(runtime.io, runtime.json, {
47626
47802
  ok: true,
@@ -47666,7 +47842,7 @@ async function cmdHub(runtime) {
47666
47842
  config = loadKxmUpdateConfig(runtime.env);
47667
47843
  } catch (error) {
47668
47844
  if (error instanceof KxmUpdateConfigError) {
47669
- const yamlPath = join46(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
47845
+ const yamlPath = join48(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
47670
47846
  runtime.io.stderr(`kxm: ${error.message}; update check skipped; fix or remove ${yamlPath}
47671
47847
  `);
47672
47848
  } else {
@@ -47853,7 +48029,7 @@ async function cmdWorker(runtime, options) {
47853
48029
  return await (runtime.io.spawnWorker ?? ((launchEnv) => spawnScript("kxm-worker.mjs", launchEnv)))(extraEnv);
47854
48030
  }
47855
48031
  async function cmdStop(runtime, waitMsFlag) {
47856
- const pids = existsSync35(runtime.dirs.state) ? readdirSync12(runtime.dirs.state).filter((name) => name.endsWith(".pid")) : [];
48032
+ const pids = existsSync37(runtime.dirs.state) ? readdirSync12(runtime.dirs.state).filter((name) => name.endsWith(".pid")) : [];
47857
48033
  if (runtime.dryRun) {
47858
48034
  print(runtime.io, runtime.json, { ok: true, command: "stop", dryRun: true, pidFiles: pids }, "would signal pid files");
47859
48035
  return 0;
@@ -47868,7 +48044,7 @@ async function cmdStop(runtime, waitMsFlag) {
47868
48044
  const orphans = [];
47869
48045
  for (const file of pids) {
47870
48046
  try {
47871
- const record = JSON.parse(readFileSync35(join46(runtime.dirs.state, file), "utf8"));
48047
+ const record = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
47872
48048
  const expectedControl = file === "hub.pid" ? "hub.stop" : file.startsWith("worker-") ? `${file.slice(0, -4)}.stop` : void 0;
47873
48049
  const expectedRole = file === "hub.pid" ? "hub" : file.startsWith("worker-") ? "worker" : void 0;
47874
48050
  if (record.version !== 1 || !Number.isInteger(record.pid) || record.pid <= 0 || !record.startedAt || !expectedControl || record.controlFile !== expectedControl || record.role !== expectedRole) {
@@ -47888,7 +48064,7 @@ async function cmdStop(runtime, waitMsFlag) {
47888
48064
  ignored.push(file);
47889
48065
  continue;
47890
48066
  }
47891
- writeFileSync25(join46(runtime.dirs.state, record.controlFile), `${JSON.stringify({ startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {}, requestedAt: (/* @__PURE__ */ new Date()).toISOString() })}
48067
+ writeFileSync25(join48(runtime.dirs.state, record.controlFile), `${JSON.stringify({ startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {}, requestedAt: (/* @__PURE__ */ new Date()).toISOString() })}
47892
48068
  `, { encoding: "utf8", mode: 384 });
47893
48069
  requested.push(file);
47894
48070
  records.set(file, { pid: record.pid, startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {} });
@@ -47906,7 +48082,7 @@ async function cmdStop(runtime, waitMsFlag) {
47906
48082
  while (Date.now() <= deadline && stopped.size < requested.length) {
47907
48083
  for (const [file, record] of records) {
47908
48084
  try {
47909
- const current = JSON.parse(readFileSync35(join46(runtime.dirs.state, file), "utf8"));
48085
+ const current = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
47910
48086
  if (current.pid !== record.pid || current.startedAt !== record.startedAt || current.generation !== record.generation || !processExists(record.pid)) stopped.add(file);
47911
48087
  } catch {
47912
48088
  stopped.add(file);
@@ -47919,7 +48095,7 @@ async function cmdStop(runtime, waitMsFlag) {
47919
48095
  for (const file of orphans) {
47920
48096
  while (Date.now() <= deadlineOrphans) {
47921
48097
  try {
47922
- const current = JSON.parse(readFileSync35(join46(runtime.dirs.state, file), "utf8"));
48098
+ const current = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
47923
48099
  if (!Number.isInteger(current.serverPid) || !processExists(current.serverPid)) break;
47924
48100
  } catch {
47925
48101
  break;
@@ -47927,14 +48103,14 @@ async function cmdStop(runtime, waitMsFlag) {
47927
48103
  await (runtime.io.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))))(100);
47928
48104
  }
47929
48105
  try {
47930
- const current = JSON.parse(readFileSync35(join46(runtime.dirs.state, file), "utf8"));
48106
+ const current = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
47931
48107
  if (Number.isInteger(current.serverPid) && processExists(current.serverPid)) {
47932
48108
  try {
47933
48109
  process.kill(current.serverPid, "SIGKILL");
47934
48110
  } catch {
47935
48111
  }
47936
48112
  }
47937
- rmSync11(join46(runtime.dirs.state, file), { force: true });
48113
+ rmSync11(join48(runtime.dirs.state, file), { force: true });
47938
48114
  } catch {
47939
48115
  }
47940
48116
  stopped.add(file);
@@ -47945,11 +48121,11 @@ async function cmdStop(runtime, waitMsFlag) {
47945
48121
  }
47946
48122
  async function cmdSessionStatus(runtime) {
47947
48123
  const stateDir = runtime.dirs.state;
47948
- const names3 = existsSync35(stateDir) ? readdirSync12(stateDir) : [];
48124
+ const names3 = existsSync37(stateDir) ? readdirSync12(stateDir) : [];
47949
48125
  const claims = [];
47950
48126
  for (const file of names3.filter((name) => name.endsWith(".pid"))) {
47951
48127
  try {
47952
- const record = JSON.parse(readFileSync35(join46(stateDir, file), "utf8"));
48128
+ const record = JSON.parse(readFileSync35(join48(stateDir, file), "utf8"));
47953
48129
  claims.push({
47954
48130
  file,
47955
48131
  role: record.role,
@@ -47964,7 +48140,7 @@ async function cmdSessionStatus(runtime) {
47964
48140
  const recoveries = [];
47965
48141
  for (const file of names3.filter((name) => name.startsWith("worker-recovery-") && name.endsWith(".json"))) {
47966
48142
  try {
47967
- const envelope = JSON.parse(readFileSync35(join46(stateDir, file), "utf8"));
48143
+ const envelope = JSON.parse(readFileSync35(join48(stateDir, file), "utf8"));
47968
48144
  recoveries.push({
47969
48145
  file,
47970
48146
  reason: envelope.reason,
@@ -47990,7 +48166,7 @@ async function cmdSessionStatus(runtime) {
47990
48166
  async function cmdAuthToken(runtime, options = {}) {
47991
48167
  const tokenFile = sessionTokenPath(runtime.env.KXM_USER_CONFIG_DIR);
47992
48168
  if (options.clear && runtime.dryRun) {
47993
- const present = existsSync35(tokenFile);
48169
+ const present = existsSync37(tokenFile);
47994
48170
  printPlan(runtime, { command: "auth token", cleared: present }, present ? [{ action: "delete", target: tokenFile }] : [], present ? "clear the session token from disk" : "no session token file to clear");
47995
48171
  return 0;
47996
48172
  }
@@ -48079,7 +48255,7 @@ async function cmdSessionBrief(runtime, options = {}) {
48079
48255
  print(runtime.io, runtime.json, { ok: true, command: "session brief", sessionToken }, sessionToken);
48080
48256
  return 0;
48081
48257
  }
48082
- const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join46(runtime.dirs.state, "kxm.db"));
48258
+ const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join48(runtime.dirs.state, "kxm.db"));
48083
48259
  const env = {
48084
48260
  ...runtime.env,
48085
48261
  KXM_STATE_DIR: runtime.dirs.state,
@@ -48105,7 +48281,7 @@ async function cmdSessionBrief(runtime, options = {}) {
48105
48281
  writeCache: !runtime.dryRun
48106
48282
  });
48107
48283
  if (runtime.dryRun) {
48108
- if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target: join46(runtime.dirs.state, "session-brief.json") });
48284
+ if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target: join48(runtime.dirs.state, "session-brief.json") });
48109
48285
  print(runtime.io, runtime.json, { ...brief, dryRun: true, planned }, [
48110
48286
  options.status ? brief.statusLine : formatSessionBriefText(brief),
48111
48287
  ...planned.map((change) => `dry run: would ${change.action} ${change.target}`)
@@ -48187,11 +48363,11 @@ init_redact();
48187
48363
  init_telemetry();
48188
48364
  init_routing();
48189
48365
  init_prices();
48190
- import { spawnSync as spawnSync10 } from "node:child_process";
48366
+ import { spawnSync as spawnSync11 } from "node:child_process";
48191
48367
  import { createHash as createHash17 } from "node:crypto";
48192
- import { existsSync as existsSync42, mkdtempSync as mkdtempSync3, readFileSync as readFileSync40, rmSync as rmSync13 } from "node:fs";
48368
+ import { existsSync as existsSync44, mkdtempSync as mkdtempSync3, readFileSync as readFileSync40, rmSync as rmSync13 } from "node:fs";
48193
48369
  import { tmpdir as tmpdir2 } from "node:os";
48194
- import { basename as basename11, extname as extname3, join as join52, resolve as resolve33 } from "node:path";
48370
+ import { basename as basename11, extname as extname3, join as join54, resolve as resolve33 } from "node:path";
48195
48371
  import { createInterface as createInterface3 } from "node:readline";
48196
48372
 
48197
48373
  // plugins/kxm/src/improve.ts
@@ -48199,8 +48375,8 @@ init_routing();
48199
48375
  init_protocol();
48200
48376
  init_relevance();
48201
48377
  import { createHash as createHash16 } from "node:crypto";
48202
- import { existsSync as existsSync36, mkdirSync as mkdirSync29, writeFileSync as writeFileSync26 } from "node:fs";
48203
- import { join as join47, relative as relative7, resolve as resolve29 } from "node:path";
48378
+ import { existsSync as existsSync38, mkdirSync as mkdirSync29, writeFileSync as writeFileSync26 } from "node:fs";
48379
+ import { join as join49, relative as relative7, resolve as resolve29 } from "node:path";
48204
48380
  var CANDIDATE_SCHEMA = "kxm.candidate.v1";
48205
48381
  var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
48206
48382
  function classifyCandidateKind(stepId, agentRole) {
@@ -48456,7 +48632,7 @@ function groupRoutingRecords(records, options = {}) {
48456
48632
  }
48457
48633
  function buildImprovementReport(records, options = {}) {
48458
48634
  const projectRoot = options.projectRoot ? resolve29(options.projectRoot) : process.cwd();
48459
- const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) : join47(projectRoot, ".kxm", "candidates");
48635
+ const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) : join49(projectRoot, ".kxm", "candidates");
48460
48636
  const promotionPolicy = options.promotionPolicy ?? "manual_pr";
48461
48637
  const groups = groupRoutingRecords(records, options);
48462
48638
  const candidates = [];
@@ -48470,7 +48646,7 @@ function buildImprovementReport(records, options = {}) {
48470
48646
  group.workflowId
48471
48647
  );
48472
48648
  const diffFileName = `${group.candidateId}.diff`;
48473
- const diffFilePath = join47(candidatesDir, diffFileName);
48649
+ const diffFilePath = join49(candidatesDir, diffFileName);
48474
48650
  const relDiffPath = relative7(projectRoot, diffFilePath).replace(/\\/g, "/");
48475
48651
  const candidate = {
48476
48652
  schema: CANDIDATE_SCHEMA,
@@ -48492,11 +48668,11 @@ function buildImprovementReport(records, options = {}) {
48492
48668
  createdAt: nowIso()
48493
48669
  };
48494
48670
  if (!options.dryRun) {
48495
- if (!existsSync36(candidatesDir)) {
48671
+ if (!existsSync38(candidatesDir)) {
48496
48672
  mkdirSync29(candidatesDir, { recursive: true });
48497
48673
  }
48498
48674
  writeFileSync26(diffFilePath, diff, "utf8");
48499
- const jsonFilePath = join47(candidatesDir, `${group.candidateId}.json`);
48675
+ const jsonFilePath = join49(candidatesDir, `${group.candidateId}.json`);
48500
48676
  writeFileSync26(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
48501
48677
  }
48502
48678
  candidates.push(candidate);
@@ -48525,7 +48701,7 @@ function buildImprovementReport(records, options = {}) {
48525
48701
  }
48526
48702
  function writeImprovementReport(improvementsDir, report2, dryRun = false) {
48527
48703
  const stamp = report2.createdAt.replace(/[:.]/g, "-");
48528
- const path4 = join47(improvementsDir, `${stamp}.json`);
48704
+ const path4 = join49(improvementsDir, `${stamp}.json`);
48529
48705
  if (!dryRun) {
48530
48706
  mkdirSync29(improvementsDir, { recursive: true });
48531
48707
  writeFileSync26(path4, `${JSON.stringify(report2, null, 2)}
@@ -48609,7 +48785,7 @@ init_project_config();
48609
48785
  init_runtime_store();
48610
48786
  init_routing();
48611
48787
  init_telemetry();
48612
- import { existsSync as existsSync37 } from "node:fs";
48788
+ import { existsSync as existsSync39 } from "node:fs";
48613
48789
  import { resolve as resolve30 } from "node:path";
48614
48790
  var ENGINE_EVENTS_SQL = "SELECT run_id, sequence, event_type, payload FROM events WHERE event_type IN ('routing.attempt.recorded','step.entered','run.status_changed') ORDER BY run_id, sequence";
48615
48791
  var SIMULATED_HARNESS = "driver-simulated";
@@ -48632,7 +48808,7 @@ function readEngineRoutingRecords(path4) {
48632
48808
  undecided: 0,
48633
48809
  duplicatesDropped: 0
48634
48810
  };
48635
- if (!existsSync37(path4)) return { records: [], source };
48811
+ if (!existsSync39(path4)) return { records: [], source };
48636
48812
  source.exists = true;
48637
48813
  let rows;
48638
48814
  let database;
@@ -48708,7 +48884,7 @@ function readEngineRoutingRecords(path4) {
48708
48884
  };
48709
48885
  }
48710
48886
  function readJsonlSource(kind, path4) {
48711
- const exists = existsSync37(path4);
48887
+ const exists = existsSync39(path4);
48712
48888
  const records = exists ? readRoutingRecords(path4).map((entry) => entry.routing) : [];
48713
48889
  return { records, source: { kind, path: path4, exists, records: records.length, duplicatesDropped: 0 } };
48714
48890
  }
@@ -48753,8 +48929,8 @@ function loadRoutingSources(options) {
48753
48929
  // plugins/kxm/src/modes.ts
48754
48930
  var import_yaml17 = __toESM(require_dist(), 1);
48755
48931
  init_prices();
48756
- import { existsSync as existsSync38, readFileSync as readFileSync37 } from "node:fs";
48757
- import { join as join48 } from "node:path";
48932
+ import { existsSync as existsSync40, readFileSync as readFileSync37 } from "node:fs";
48933
+ import { join as join50 } from "node:path";
48758
48934
  var DEFAULT_MODES_CONFIG = Object.freeze({
48759
48935
  schema: "kxm.modes.v1",
48760
48936
  majorModes: {
@@ -48817,8 +48993,8 @@ function loadModesConfig(projectRoot) {
48817
48993
  if (!projectRoot) {
48818
48994
  return DEFAULT_MODES_CONFIG;
48819
48995
  }
48820
- const modesPath = join48(projectRoot, ".kxm", "modes.yaml");
48821
- if (!existsSync38(modesPath)) {
48996
+ const modesPath = join50(projectRoot, ".kxm", "modes.yaml");
48997
+ if (!existsSync40(modesPath)) {
48822
48998
  return DEFAULT_MODES_CONFIG;
48823
48999
  }
48824
49000
  try {
@@ -48908,9 +49084,9 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
48908
49084
  estimatedTokens: estimateTokens(baseSystemPromptChars)
48909
49085
  });
48910
49086
  for (const relPath of resolved.contextFiles) {
48911
- const fullPath = join48(projectRoot, relPath);
49087
+ const fullPath = join50(projectRoot, relPath);
48912
49088
  let chars = 0;
48913
- if (existsSync38(fullPath)) {
49089
+ if (existsSync40(fullPath)) {
48914
49090
  try {
48915
49091
  chars = readFileSync37(fullPath, "utf8").length;
48916
49092
  } catch {
@@ -49044,10 +49220,10 @@ ${divider}
49044
49220
 
49045
49221
  // plugins/kxm/src/ssh-remote.ts
49046
49222
  init_safety_integrity();
49047
- import { spawnSync as spawnSync9 } from "node:child_process";
49048
- import { existsSync as existsSync39, mkdirSync as mkdirSync30, readFileSync as readFileSync38, readdirSync as readdirSync13, rmSync as rmSync12, statSync as statSync5 } from "node:fs";
49223
+ import { spawnSync as spawnSync10 } from "node:child_process";
49224
+ import { existsSync as existsSync41, mkdirSync as mkdirSync30, readFileSync as readFileSync38, readdirSync as readdirSync13, rmSync as rmSync12, statSync as statSync5 } from "node:fs";
49049
49225
  import { homedir as homedir8 } from "node:os";
49050
- import { join as join49, resolve as resolve31 } from "node:path";
49226
+ import { join as join51, resolve as resolve31 } from "node:path";
49051
49227
  var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
49052
49228
  var MAX_SSH_OUTPUT_LINES = 2e3;
49053
49229
  var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
@@ -49073,8 +49249,8 @@ function truncateSshOutput(raw) {
49073
49249
  return { text, truncated };
49074
49250
  }
49075
49251
  function parseSshConfig(configPath) {
49076
- const targetPath = configPath ?? join49(homedir8(), ".ssh", "config");
49077
- if (!existsSync39(targetPath)) {
49252
+ const targetPath = configPath ?? join51(homedir8(), ".ssh", "config");
49253
+ if (!existsSync41(targetPath)) {
49078
49254
  return [];
49079
49255
  }
49080
49256
  try {
@@ -49120,7 +49296,7 @@ function parseSshConfig(configPath) {
49120
49296
  return [];
49121
49297
  }
49122
49298
  }
49123
- function resolveSshHostG(host, execFn = spawnSync9) {
49299
+ function resolveSshHostG(host, execFn = spawnSync10) {
49124
49300
  try {
49125
49301
  const result = execFn("ssh", ["-G", host], { encoding: "utf-8" });
49126
49302
  if (result.status !== 0 || !result.stdout) {
@@ -49156,14 +49332,14 @@ function resolveSshHostG(host, execFn = spawnSync9) {
49156
49332
  }
49157
49333
  function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
49158
49334
  const resolved = resolve31(socketDir);
49159
- if (!existsSync39(resolved)) {
49335
+ if (!existsSync41(resolved)) {
49160
49336
  mkdirSync30(resolved, { recursive: true, mode: 448 });
49161
49337
  }
49162
49338
  return resolved;
49163
49339
  }
49164
49340
  function buildSshArgs(options) {
49165
49341
  const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
49166
- const controlPath = join49(socketDir, "%C");
49342
+ const controlPath = join51(socketDir, "%C");
49167
49343
  const persist = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
49168
49344
  const args = [
49169
49345
  "-o",
@@ -49186,9 +49362,9 @@ function buildSshArgs(options) {
49186
49362
  args.push(options.host);
49187
49363
  return args;
49188
49364
  }
49189
- function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync9) {
49365
+ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync10) {
49190
49366
  const resolvedDir = ensureSocketDir(socketDir);
49191
- const controlPath = join49(resolvedDir, "%C");
49367
+ const controlPath = join51(resolvedDir, "%C");
49192
49368
  try {
49193
49369
  const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
49194
49370
  encoding: "utf-8"
@@ -49198,9 +49374,9 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
49198
49374
  return false;
49199
49375
  }
49200
49376
  }
49201
- function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync9) {
49377
+ function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync10) {
49202
49378
  const resolvedDir = ensureSocketDir(socketDir);
49203
- const controlPath = join49(resolvedDir, "%C");
49379
+ const controlPath = join51(resolvedDir, "%C");
49204
49380
  try {
49205
49381
  const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
49206
49382
  encoding: "utf-8"
@@ -49212,7 +49388,7 @@ function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
49212
49388
  }
49213
49389
  function executeSshRun(params) {
49214
49390
  const startTime = Date.now();
49215
- const execSyncFn = params.execFn ?? spawnSync9;
49391
+ const execSyncFn = params.execFn ?? spawnSync10;
49216
49392
  if (params.action === "info") {
49217
49393
  if (params.host) {
49218
49394
  const hostInfo = resolveSshHostG(params.host, execSyncFn);
@@ -49648,9 +49824,9 @@ complete -c kxm -n "__fish_seen_subcommand_from goal" -a "create list get"
49648
49824
  }
49649
49825
 
49650
49826
  // plugins/kxm/src/completion-install.ts
49651
- import { existsSync as existsSync40, mkdirSync as mkdirSync31, readFileSync as readFileSync39, writeFileSync as writeFileSync27 } from "node:fs";
49827
+ import { existsSync as existsSync42, mkdirSync as mkdirSync31, readFileSync as readFileSync39, writeFileSync as writeFileSync27 } from "node:fs";
49652
49828
  import { homedir as homedir9 } from "node:os";
49653
- import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as isAbsolute10, join as join50, resolve as resolve32 } from "node:path";
49829
+ import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as isAbsolute10, join as join52, resolve as resolve32 } from "node:path";
49654
49830
  var COMPLETION_MARKER = "# kxm completion";
49655
49831
  var PATH_MARKER = "# kxm path";
49656
49832
  function detectShell(env = process.env, platform = process.platform) {
@@ -49672,25 +49848,25 @@ function completionScriptPath(shell, options = {}) {
49672
49848
  const env = options.env ?? process.env;
49673
49849
  const explicit = options.configDir ?? env.KXM_USER_CONFIG_DIR?.trim();
49674
49850
  const base = explicit && explicit.length > 0 ? resolve32(explicit) : resolve32(effectiveHome(options), ".config", "kxm");
49675
- return join50(base, "completions", `kxm.${shell}`);
49851
+ return join52(base, "completions", `kxm.${shell}`);
49676
49852
  }
49677
49853
  function bashRcCandidate(options) {
49678
49854
  const home = effectiveHome(options);
49679
- const candidates = [join50(home, ".bashrc"), join50(home, ".bash_profile")];
49680
- const existing = candidates.find((candidate) => existsSync40(candidate));
49855
+ const candidates = [join52(home, ".bashrc"), join52(home, ".bash_profile")];
49856
+ const existing = candidates.find((candidate) => existsSync42(candidate));
49681
49857
  return existing ?? candidates[0];
49682
49858
  }
49683
49859
  function zshRcCandidate(options) {
49684
49860
  const env = options.env ?? process.env;
49685
49861
  const home = effectiveHome(options);
49686
- if (env.ZDOTDIR?.trim()) return join50(resolve32(env.ZDOTDIR.trim()), ".zshrc");
49687
- return join50(home, ".zshrc");
49862
+ if (env.ZDOTDIR?.trim()) return join52(resolve32(env.ZDOTDIR.trim()), ".zshrc");
49863
+ return join52(home, ".zshrc");
49688
49864
  }
49689
49865
  function fishCompletionTarget(shell, options) {
49690
49866
  const env = options.env ?? process.env;
49691
49867
  const home = effectiveHome(options);
49692
- if (env.XDG_CONFIG_HOME?.trim()) return join50(resolve32(env.XDG_CONFIG_HOME.trim()), "fish", "completions", "kxm.fish");
49693
- return join50(home, ".config", "fish", "completions", "kxm.fish");
49868
+ if (env.XDG_CONFIG_HOME?.trim()) return join52(resolve32(env.XDG_CONFIG_HOME.trim()), "fish", "completions", "kxm.fish");
49869
+ return join52(home, ".config", "fish", "completions", "kxm.fish");
49694
49870
  }
49695
49871
  function completionRcTarget(shell, options = {}) {
49696
49872
  if (shell === "fish") {
@@ -49722,13 +49898,13 @@ function installShellCompletion(shellInput, options = {}) {
49722
49898
  const scriptPath = completionScriptPath(shell, options);
49723
49899
  const { rcFile } = completionRcTarget(shell, options);
49724
49900
  const script = generateShellCompletion(shell);
49725
- const existingScript = existsSync40(scriptPath);
49901
+ const existingScript = existsSync42(scriptPath);
49726
49902
  const existingScriptMatches = existingScript && readFileSync39(scriptPath, "utf8") === script;
49727
49903
  let rcModified = false;
49728
49904
  let alreadyInstalled = false;
49729
49905
  if (shell === "fish") {
49730
49906
  const fishTarget = fishCompletionTarget(shell, options);
49731
- const fishInstalled = existsSync40(fishTarget) && readFileSync39(fishTarget, "utf8") === script;
49907
+ const fishInstalled = existsSync42(fishTarget) && readFileSync39(fishTarget, "utf8") === script;
49732
49908
  alreadyInstalled = fishInstalled;
49733
49909
  if (!options.dryRun && (!fishInstalled || options.overwrite)) {
49734
49910
  mkdirSync31(resolve32(fishTarget, ".."), { recursive: true });
@@ -49745,7 +49921,7 @@ function installShellCompletion(shellInput, options = {}) {
49745
49921
  }
49746
49922
  if (rcFile) {
49747
49923
  const line = sourceLine(shell, scriptPath);
49748
- const rcContent = existsSync40(rcFile) ? readFileSync39(rcFile, "utf8") : "";
49924
+ const rcContent = existsSync42(rcFile) ? readFileSync39(rcFile, "utf8") : "";
49749
49925
  alreadyInstalled = rcContent.includes(line) || rcContent.includes(`${COMPLETION_MARKER}`);
49750
49926
  }
49751
49927
  if (!options.dryRun) {
@@ -49761,7 +49937,7 @@ ${marker}
49761
49937
  ${line}
49762
49938
  `;
49763
49939
  mkdirSync31(resolve32(rcFile, ".."), { recursive: true });
49764
- writeFileSync27(rcFile, (existsSync40(rcFile) ? readFileSync39(rcFile, "utf8") : "") + stanza, { encoding: "utf8" });
49940
+ writeFileSync27(rcFile, (existsSync42(rcFile) ? readFileSync39(rcFile, "utf8") : "") + stanza, { encoding: "utf8" });
49765
49941
  rcModified = true;
49766
49942
  }
49767
49943
  }
@@ -49778,13 +49954,13 @@ function kxmBinDir(env = process.env) {
49778
49954
  const argv1 = env.KXM_ENTRY ?? process.argv[1];
49779
49955
  if (argv1 && isAbsolute10(argv1)) {
49780
49956
  const dir = dirname24(argv1);
49781
- if (existsSync40(join50(dir, process.platform === "win32" ? "kxm.cmd" : "kxm"))) return dir;
49957
+ if (existsSync42(join52(dir, process.platform === "win32" ? "kxm.cmd" : "kxm"))) return dir;
49782
49958
  }
49783
49959
  const pathEnv = env.PATH ?? "";
49784
49960
  for (const part of pathEnv.split(delimiter)) {
49785
49961
  if (!part) continue;
49786
49962
  const candidate = resolve32(part, process.platform === "win32" ? "kxm.cmd" : "kxm");
49787
- if (existsSync40(candidate)) return resolve32(part);
49963
+ if (existsSync42(candidate)) return resolve32(part);
49788
49964
  }
49789
49965
  return void 0;
49790
49966
  }
@@ -49802,7 +49978,7 @@ function installPathEntry(shellInput, options = {}) {
49802
49978
  }
49803
49979
  const { rcFile } = completionRcTarget(shell, options);
49804
49980
  const line = pathLine(binDir);
49805
- const rcContent = existsSync40(rcFile ?? "") ? readFileSync39(rcFile, "utf8") : "";
49981
+ const rcContent = existsSync42(rcFile ?? "") ? readFileSync39(rcFile, "utf8") : "";
49806
49982
  const alreadyInstalled = rcContent.includes(binDir) || (options.env?.PATH ?? process.env.PATH ?? "").split(delimiter).includes(binDir);
49807
49983
  if (!options.dryRun && rcFile && !alreadyInstalled) {
49808
49984
  mkdirSync31(dirname24(rcFile), { recursive: true });
@@ -49817,8 +49993,8 @@ ${line}
49817
49993
  // plugins/kxm/src/init-guide-setup.ts
49818
49994
  var import_yaml18 = __toESM(require_dist(), 1);
49819
49995
  init_routes();
49820
- import { existsSync as existsSync41, mkdirSync as mkdirSync32, writeFileSync as writeFileSync28 } from "node:fs";
49821
- import { dirname as dirname25, join as join51 } from "node:path";
49996
+ import { existsSync as existsSync43, mkdirSync as mkdirSync32, writeFileSync as writeFileSync28 } from "node:fs";
49997
+ import { dirname as dirname25, join as join53 } from "node:path";
49822
49998
  var ADMITTED_GUIDE_BINDINGS = Object.freeze({
49823
49999
  "anthropic/claude-fable-5.1": { harness: "claude", provider: "anthropic", model: "fable" },
49824
50000
  "anthropic/fable": { harness: "claude", provider: "anthropic", model: "fable" },
@@ -50209,13 +50385,13 @@ function renderGuideSetupFiles(projectRoot, plan) {
50209
50385
  const stage = roleStages.get(role);
50210
50386
  if (!stage) continue;
50211
50387
  files.push({
50212
- path: join51(projectRoot, ".kxm", "agents", `${role}.yaml`),
50388
+ path: join53(projectRoot, ".kxm", "agents", `${role}.yaml`),
50213
50389
  content: (0, import_yaml18.stringify)(agentDocument(role, stage, binding))
50214
50390
  });
50215
50391
  }
50216
50392
  for (const workflow of plan.workflows) {
50217
50393
  files.push({
50218
- path: join51(projectRoot, ".kxm", "workflows", `${workflow.slug}.yaml`),
50394
+ path: join53(projectRoot, ".kxm", "workflows", `${workflow.slug}.yaml`),
50219
50395
  content: (0, import_yaml18.stringify)(workflowDocument(workflow))
50220
50396
  });
50221
50397
  }
@@ -50232,7 +50408,7 @@ function mergeGuideRouteAdmission(projectRoot, plan) {
50232
50408
  }
50233
50409
  if (added.length === 0) return added;
50234
50410
  policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
50235
- const path4 = join51(projectRoot, ".kxm", "routes.yaml");
50411
+ const path4 = join53(projectRoot, ".kxm", "routes.yaml");
50236
50412
  mkdirSync32(dirname25(path4), { recursive: true });
50237
50413
  writeFileSync28(path4, (0, import_yaml18.stringify)(policy), "utf8");
50238
50414
  return added;
@@ -50241,7 +50417,7 @@ function writeGuideSetupFiles(files) {
50241
50417
  const written = [];
50242
50418
  const existed = [];
50243
50419
  for (const file of files) {
50244
- if (existsSync41(file.path)) {
50420
+ if (existsSync43(file.path)) {
50245
50421
  existed.push(file.path);
50246
50422
  continue;
50247
50423
  }
@@ -50274,7 +50450,7 @@ init_types();
50274
50450
  init_repo_root();
50275
50451
  function cliSpawn(runtime, command, args, extra) {
50276
50452
  if (runtime.io.spawnSync) return runtime.io.spawnSync(command, args);
50277
- const result = spawnSync10(command, [...args], {
50453
+ const result = spawnSync11(command, [...args], {
50278
50454
  encoding: "utf8",
50279
50455
  windowsHide: true,
50280
50456
  shell: process.platform === "win32",
@@ -50312,7 +50488,7 @@ function applyKxmPackageUpdate(runtime, notice) {
50312
50488
  detail: `release v${notice.latest} has no sha256 digest for ${name}; refusing to install`
50313
50489
  };
50314
50490
  }
50315
- const releaseDir = mkdtempSync3(join52(tmpdir2(), "kxm-pkg-update-"));
50491
+ const releaseDir = mkdtempSync3(join54(tmpdir2(), "kxm-pkg-update-"));
50316
50492
  try {
50317
50493
  const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset);
50318
50494
  if (runtime.dryRun) {
@@ -50321,7 +50497,7 @@ function applyKxmPackageUpdate(runtime, notice) {
50321
50497
  for (const step of planned) {
50322
50498
  if (step.kind === "verify") {
50323
50499
  if (!verifyReleaseAssetDigest(step.path, step.sha256)) {
50324
- const actual = existsSync42(step.path) ? createHash17("sha256").update(readFileSync40(step.path)).digest("hex") : "missing";
50500
+ const actual = existsSync44(step.path) ? createHash17("sha256").update(readFileSync40(step.path)).digest("hex") : "missing";
50325
50501
  return {
50326
50502
  ok: false,
50327
50503
  error: "release_digest_mismatch",
@@ -50599,7 +50775,7 @@ async function cmdValidate(runtime, fileFlag) {
50599
50775
  }
50600
50776
  const selectedFile = explicitFile || configuredFile;
50601
50777
  const file = selectedFile ? resolve33(runtime.cwd, selectedFile) : void 0;
50602
- if (file && !existsSync42(file)) {
50778
+ if (file && !existsSync44(file)) {
50603
50779
  printWorker(runtime, worker, { ok: false, command: "validate", error: "file_not_found", file }, `workflow file not found: ${file}`);
50604
50780
  return 1;
50605
50781
  }
@@ -50699,7 +50875,7 @@ async function cmdImprove(runtime, options = {}) {
50699
50875
  print(runtime.io, runtime.json, { ok: false, command: "improve", error: "config_invalid", detail: message }, `config_invalid: ${message}`);
50700
50876
  return 1;
50701
50877
  }
50702
- const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) : join52(root, ".kxm", "candidates");
50878
+ const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) : join54(root, ".kxm", "candidates");
50703
50879
  const report2 = buildImprovementReport(loaded.records, {
50704
50880
  candidatesDir,
50705
50881
  projectRoot: root,
@@ -50708,7 +50884,7 @@ async function cmdImprove(runtime, options = {}) {
50708
50884
  autoThreshold: config.improvement.autoThreshold,
50709
50885
  halfLifeDays: config.improvement.telemetryHalfLifeDays
50710
50886
  });
50711
- const reportDir = join52(runtime.dirs.assets, "improvements");
50887
+ const reportDir = join54(runtime.dirs.assets, "improvements");
50712
50888
  const reportPath = writeImprovementReport(reportDir, report2, runtime.dryRun);
50713
50889
  const text = [
50714
50890
  "Sources:",
@@ -50852,7 +51028,7 @@ async function maybeOfferCompletionInstall(runtime) {
50852
51028
  if (!pathNeeded) {
50853
51029
  const scriptPath = completionScriptPath(shell, { env: runtime.env, configDir: runtime.env.KXM_USER_CONFIG_DIR });
50854
51030
  const { rcFile } = completionRcTarget(shell, { env: runtime.env });
50855
- if (rcFile && existsSync42(rcFile)) {
51031
+ if (rcFile && existsSync44(rcFile)) {
50856
51032
  try {
50857
51033
  if (readFileSync40(rcFile, "utf8").includes(scriptPath)) return;
50858
51034
  } catch {
@@ -51017,7 +51193,7 @@ async function cmdRoutingReport(runtime, options) {
51017
51193
  let catalog;
51018
51194
  if (includeEquivalentListCost) {
51019
51195
  try {
51020
- const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) : join52(runtime.dirs.workspace, "prices.yaml");
51196
+ const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) : join54(runtime.dirs.workspace, "prices.yaml");
51021
51197
  catalog = loadPriceCatalog(pricesPath);
51022
51198
  } catch {
51023
51199
  }
@@ -51131,6 +51307,13 @@ var DRY_RUN_COMMANDS = /* @__PURE__ */ new Set([
51131
51307
  "lane drop",
51132
51308
  "lane run",
51133
51309
  "land",
51310
+ "assign run",
51311
+ "assign witness",
51312
+ "assign plan-current",
51313
+ "assign attribute",
51314
+ "assign observe-cost",
51315
+ "assign accept",
51316
+ "assign change-report",
51134
51317
  "plugin install",
51135
51318
  "plugin",
51136
51319
  "runs status",
@@ -51231,7 +51414,9 @@ var DRY_RUN_COMMANDS = /* @__PURE__ */ new Set([
51231
51414
  "task run",
51232
51415
  "task sync",
51233
51416
  "studio layout",
51234
- "studio serve"
51417
+ "studio serve",
51418
+ "docs build",
51419
+ "docs serve"
51235
51420
  ]);
51236
51421
  var DryRunRefused = class extends Error {
51237
51422
  code;
@@ -51439,6 +51624,47 @@ function createProgram(ctx, result) {
51439
51624
  ...options.bodyFile !== void 0 ? { bodyFile: options.bodyFile } : {}
51440
51625
  });
51441
51626
  });
51627
+ const assignCmd = addGlobalOptions(program2.command("assign").description("Run this repository's developer assignment runner"));
51628
+ assignCmd.helpCommand("help", "Show assign help");
51629
+ addGlobalOptions(assignCmd.command("run").description("Dispatch a bound assignment manifest")).requiredOption("--manifest <path>", "Absolute path to the assignment manifest").action(async function assignRunAction(options) {
51630
+ result.code = await cmdAssign(runtimeFrom(ctx, this), "run", { manifest: options.manifest });
51631
+ });
51632
+ addGlobalOptions(assignCmd.command("witness").description("Run the fixed verification witness for an existing assignment")).requiredOption("--record-dir <path>", "Absolute path to the assignment record directory").action(async function assignWitnessAction(options) {
51633
+ result.code = await cmdAssign(runtimeFrom(ctx, this), "witness", { recordDir: options.recordDir });
51634
+ });
51635
+ addGlobalOptions(assignCmd.command("plan-current").description("Stamp or advance the current-plan pointer")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--plan <path>", "Absolute path to the plan file").requiredOption("--sha256 <hex>", "SHA-256 of the plan file").requiredOption("--base-commit <sha>", "Base commit the pointer records").requiredOption("--expected-generation <n>", "Generation the pointer must currently have").action(async function assignPlanCurrentAction(options) {
51636
+ result.code = await cmdAssign(runtimeFrom(ctx, this), "plan-current", {
51637
+ taskDir: options.taskDir,
51638
+ plan: options.plan,
51639
+ sha256: options.sha256,
51640
+ baseCommit: options.baseCommit,
51641
+ expectedGeneration: options.expectedGeneration
51642
+ });
51643
+ });
51644
+ addGlobalOptions(assignCmd.command("attribute").description("Attach a private attribution note")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--record-dir <path>", "Absolute path to the assignment record directory").requiredOption("--class <class>", "orchestration, model, environment, or unclassified").requiredOption("--explanation-file <path>", "Absolute path to the note file").action(async function assignAttributeAction(options) {
51645
+ result.code = await cmdAssign(runtimeFrom(ctx, this), "attribute", {
51646
+ taskDir: options.taskDir,
51647
+ recordDir: options.recordDir,
51648
+ classification: options.class,
51649
+ explanationFile: options.explanationFile
51650
+ });
51651
+ });
51652
+ addGlobalOptions(assignCmd.command("observe-cost").description("Import one historical cost observation as cost-only")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--input <path>", "Absolute path to the observation file").action(async function assignObserveCostAction(options) {
51653
+ result.code = await cmdAssign(runtimeFrom(ctx, this), "observe-cost", { taskDir: options.taskDir, input: options.input });
51654
+ });
51655
+ addGlobalOptions(assignCmd.command("accept").description("Bind an exact witnessed commit and two critic PASS records")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--commit <sha>", "Commit to accept").requiredOption("--record-dir <path>", "Absolute path to the writer record directory").requiredOption("--critic <path>", "Absolute path to a critic record directory; pass twice", (value, previous) => previous.concat(value), []).option("--observed-pr <id>", "Observed pull request id").option("--observed-ci <id>", "Observed CI run id").action(async function assignAcceptAction(options) {
51656
+ result.code = await cmdAssign(runtimeFrom(ctx, this), "accept", {
51657
+ taskDir: options.taskDir,
51658
+ commit: options.commit,
51659
+ recordDir: options.recordDir,
51660
+ critics: options.critic,
51661
+ ...options.observedPr !== void 0 ? { observedPr: options.observedPr } : {},
51662
+ ...options.observedCi !== void 0 ? { observedCi: options.observedCi } : {}
51663
+ });
51664
+ });
51665
+ addGlobalOptions(assignCmd.command("change-report").description("Report attempts, rework, costs, and retained verification history")).requiredOption("--task-dir <path>", "Absolute path to the task directory").action(async function assignChangeReportAction(options) {
51666
+ result.code = await cmdAssign(runtimeFrom(ctx, this), "change-report", { taskDir: options.taskDir });
51667
+ });
51442
51668
  addGlobalOptions(program2.command("run").description("Create a KXM run without executing steps; follow its prerequisites, then kxm runs drive <runId> --wait").argument("[workflow]", "Workflow id to run").argument("[prompt...]", "Run prompt (events keep its hash; the full text is kept in a local 0600 sidecar file)").option("--brief <file>", "Read the run prompt from a file instead of the positional prompt").option("--lane <unit>", "Discover the project from this lane's worktree").action(async function runAction(workflow2, promptParts, options) {
51443
51669
  result.code = await cmdKxmRunCli(runtimeFrom(ctx, this), workflow2, promptParts, options);
51444
51670
  }));
@@ -51470,6 +51696,14 @@ function createProgram(ctx, result) {
51470
51696
  addGlobalOptions(runCmd.command("list").description("List recent runs for the current project")).action(async function runListAction() {
51471
51697
  result.code = await cmdKxmRunList(runtimeFrom(ctx, this));
51472
51698
  });
51699
+ const docsCmd = addGlobalOptions(program2.command("docs").description("Build and serve the tailnet docs site"));
51700
+ docsCmd.helpCommand("help", "Show docs help");
51701
+ addGlobalOptions(docsCmd.command("build").description("Regenerate the docs site from the roadmap state")).action(async function docsBuildAction() {
51702
+ result.code = await cmdDocsBuild(runtimeFrom(ctx, this));
51703
+ });
51704
+ addGlobalOptions(docsCmd.command("serve").description("Serve the built docs site on this machine's tailnet address")).option("--port <port>", "Port passed through to the docs server").action(async function docsServeAction(options) {
51705
+ result.code = await cmdDocsServe(runtimeFrom(ctx, this), options);
51706
+ });
51473
51707
  const tenantCmd = addGlobalOptions(program2.command("tenant").description("Composed tenant reads for machine clients (portal)"));
51474
51708
  tenantCmd.helpCommand("help", "Show tenant help");
51475
51709
  addGlobalOptions(tenantCmd.command("status").description("Read hub metadata and authoritative Runtime run state as one labeled view")).action(async function tenantStatusAction() {