@kontextmind/kxm 0.7.122 → 0.7.124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.kxm/workflows/implement-only.yaml +20 -0
  3. package/.kxm/workflows/review-arch-only.yaml +20 -0
  4. package/.kxm/workflows/review-cli-only.yaml +20 -0
  5. package/CHANGELOG.md +31 -3
  6. package/docs/architecture/access-schema.yaml +60 -0
  7. package/docs/architecture/access.md +33 -0
  8. package/docs/architecture/agent-path.md +36 -0
  9. package/docs/architecture/authentication.md +29 -0
  10. package/docs/architecture/hosted-direction.md +59 -0
  11. package/docs/architecture/index.md +19 -0
  12. package/docs/architecture/inventory.md +38 -0
  13. package/docs/architecture/platform.md +48 -0
  14. package/docs/assets/logo.png +0 -0
  15. package/docs/contributing/assignment-runner.md +15 -4
  16. package/docs/index.md +56 -0
  17. package/docs/javascripts/mermaid-init.js +83 -0
  18. package/docs/javascripts/mermaid.min.js +4376 -0
  19. package/docs/reference/cli-reference.md +57 -4
  20. package/docs/reference/config-reference.md +2 -1
  21. package/docs/reference/workflow-catalog.md +10 -0
  22. package/docs/reference/workflow-definitions.md +1 -1
  23. package/docs/robots.txt +44 -0
  24. package/docs/stylesheets/extra.css +100 -0
  25. package/package.json +1 -1
  26. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  27. package/plugins/kxm/dist/cli.js +265 -165
  28. package/plugins/kxm/dist/mcp-server.js +1 -1
  29. package/plugins/kxm/dist/runtime-supervisor.js +209 -72
  30. package/plugins/kxm/dist/runtime.js +233 -94
  31. package/plugins/kxm/package.json +1 -1
  32. package/plugins/kxm/skills/kxm/SKILL.md +1 -2
  33. package/plugins/kxm/skills/kxm-runs/SKILL.md +7 -0
  34. package/plugins/kxm/src/cli/docs.ts +78 -0
  35. package/plugins/kxm/src/cli/project.ts +14 -2
  36. package/plugins/kxm/src/cli.ts +14 -0
  37. package/plugins/kxm/src/engine-fold.ts +15 -7
  38. package/plugins/kxm/src/engine-plan.ts +10 -1
  39. package/plugins/kxm/src/engine.ts +105 -2
  40. package/plugins/kxm/src/mcp-server.ts +1 -1
  41. package/plugins/kxm/src/oneshot-evidence.ts +44 -0
  42. package/plugins/kxm/src/oneshot-producer.ts +5 -5
  43. package/plugins/kxm/src/runtime-service.ts +10 -0
  44. package/plugins/kxm/src/runtime-store.ts +1 -0
  45. package/plugins/kxm/src/runtime-supervisor.ts +2 -0
  46. package/schemas/drive-receipt.schema.json +1 -0
  47. package/schemas/project.schema.json +2 -1
  48. package/schemas/roadmap-state.schema.json +147 -0
@@ -17207,8 +17207,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
17207
17207
  const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
17208
17208
  if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
17209
17209
  }
17210
- const join24 = objectValue(step.join);
17211
- const minimumPassed = join24 && typeof join24.minimumPassed === "number" ? join24.minimumPassed : void 0;
17210
+ const join23 = objectValue(step.join);
17211
+ const minimumPassed = join23 && typeof join23.minimumPassed === "number" ? join23.minimumPassed : void 0;
17212
17212
  if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
17213
17213
  const distinctBy = names(assignment?.distinctBy);
17214
17214
  if (distinctBy.length > 0) {
@@ -20676,9 +20676,12 @@ function authorizedCancelStep(state, step, current, status) {
20676
20676
  }
20677
20677
  const currentAttempt = currentAttemptOf(assignment);
20678
20678
  if (!currentAttempt?.resultClass) return false;
20679
- members.push({ resultClass: currentAttempt.resultClass, outcome: currentAttempt.outcome });
20679
+ members.push({ resultClass: currentAttempt.resultClass, outcome: currentAttempt.outcome, producerError: currentAttempt.producerError });
20680
20680
  }
20681
20681
  if (members.some((member) => member.resultClass === "outcome_unknown" || member.resultClass === "producer_rejected")) {
20682
+ if (members.every((member) => member.resultClass === "producer_rejected" && member.producerError === "executing_unrecorded")) {
20683
+ return true;
20684
+ }
20682
20685
  return false;
20683
20686
  }
20684
20687
  const declared = members.filter((member) => member.resultClass === "outcome");
@@ -21032,8 +21035,8 @@ function isProvenFailure(state, plan) {
21032
21035
  return Boolean(step && used >= step.maxAttempts);
21033
21036
  }
21034
21037
  function foldDriveOpened(state, event) {
21035
- if (state.status !== "running" && state.status !== "blocked_uncertain") {
21036
- throw runtimeError("run_events_illegal", state.runId, "run.drive_opened is only legal while running or blocked_uncertain");
21038
+ if (state.status !== "running" && state.status !== "blocked_uncertain" && state.status !== "cancelling") {
21039
+ throw runtimeError("run_events_illegal", state.runId, "run.drive_opened is only legal while running, blocked_uncertain, or cancelling");
21037
21040
  }
21038
21041
  const driveId = stringPayload(event, "driveId");
21039
21042
  const mode = stringPayload(event, "mode");
@@ -21367,9 +21370,13 @@ function foldAssignmentAdvance(state, plan, event, next) {
21367
21370
  }
21368
21371
  }
21369
21372
  if (attemptId && attempt) {
21373
+ const producerError = typeof event.payload.producerError === "string" ? event.payload.producerError : void 0;
21370
21374
  nextAssignment = {
21371
21375
  ...nextAssignment,
21372
- attempts: { ...nextAssignment.attempts, [attemptId]: { ...attempt, resultClass } }
21376
+ attempts: {
21377
+ ...nextAssignment.attempts,
21378
+ [attemptId]: { ...attempt, resultClass, ...producerError !== void 0 ? { producerError } : {} }
21379
+ }
21373
21380
  };
21374
21381
  }
21375
21382
  }
@@ -21884,7 +21891,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
21884
21891
  const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
21885
21892
  const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
21886
21893
  const assignments = compileAssignments(step, id, agent, sink);
21887
- const join24 = compileJoin(step, id, sink);
21894
+ const join23 = compileJoin(step, id, sink);
21888
21895
  const requiredEvidence = compileEvidence(step, id, sink);
21889
21896
  const transitions = compileTransitions(step, id, index, stepIndex, sink);
21890
21897
  const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
@@ -21912,7 +21919,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
21912
21919
  transitions: orderedTransitions,
21913
21920
  requiresPlanHash: requirePlanHash.includes(id),
21914
21921
  assignments,
21915
- join: join24
21922
+ join: join23
21916
21923
  };
21917
21924
  if (kind === "agent" || kind === "moa") {
21918
21925
  if (!agent) return void 0;
@@ -21962,15 +21969,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
21962
21969
  };
21963
21970
  }
21964
21971
  function compileJoin(step, stepId, sink) {
21965
- const join24 = objectValue2(step.join);
21966
- if (!join24) return { strategy: "all" };
21967
- const declared = stringValue2(join24.strategy);
21972
+ const join23 = objectValue2(step.join);
21973
+ if (!join23) return { strategy: "all" };
21974
+ const declared = stringValue2(join23.strategy);
21968
21975
  const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
21969
- const minimumPassed = compileOptionalCount(join24.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
21976
+ const minimumPassed = compileOptionalCount(join23.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
21970
21977
  const compiled = {
21971
21978
  strategy,
21972
21979
  ...minimumPassed !== void 0 ? { minimumPassed } : {},
21973
- ...typeof join24.cancelRemaining === "boolean" ? { cancelRemaining: join24.cancelRemaining } : {}
21980
+ ...typeof join23.cancelRemaining === "boolean" ? { cancelRemaining: join23.cancelRemaining } : {}
21974
21981
  };
21975
21982
  return compiled;
21976
21983
  }
@@ -22254,7 +22261,7 @@ var CONTROL_ROOT_REQUIRED = ["repositoryId", "projectKey"];
22254
22261
  var GATE_REGISTRY_SCHEMA = "kxm.gate-registry.v1";
22255
22262
  var REVISION_REQUIRED = ["config", "executorPolicy", "toolPolicy", "memory"];
22256
22263
  var PROJECT_LIMIT_REQUIRED = ["maxConcurrentRuns"];
22257
- var PROJECT_LIMIT_OPTIONAL = ["maxRunDurationMs", "maxAgentTimeMs"];
22264
+ var PROJECT_LIMIT_OPTIONAL = ["maxRunDurationMs", "maxAgentTimeMs", "agentStepTimeoutMs"];
22258
22265
  var PLAN_REQUIRED = ["schema", "workflowId", "coordinator", "limits", "transitionBudget", "hasBackEdges", "entryStepId", "order", "steps", "requirePlanHash"];
22259
22266
  var PLAN_OPTIONAL = ["sourcePath", "reproOracle", "planHash"];
22260
22267
  var LIMIT_OPTIONAL = ["maxTransitions", "maxRunDurationMs", "maxAgentTimeMs", "maxModelCost", "currency"];
@@ -22406,7 +22413,8 @@ function parseEnvelope(parsed, run) {
22406
22413
  const projectLimits = {
22407
22414
  maxConcurrentRuns: asCount(limitsValue.maxConcurrentRuns, run.runId, "projectLimits.maxConcurrentRuns"),
22408
22415
  ...limitsValue.maxRunDurationMs !== void 0 ? { maxRunDurationMs: asDuration(limitsValue.maxRunDurationMs, run.runId, "projectLimits.maxRunDurationMs") } : {},
22409
- ...limitsValue.maxAgentTimeMs !== void 0 ? { maxAgentTimeMs: asDuration(limitsValue.maxAgentTimeMs, run.runId, "projectLimits.maxAgentTimeMs") } : {}
22416
+ ...limitsValue.maxAgentTimeMs !== void 0 ? { maxAgentTimeMs: asDuration(limitsValue.maxAgentTimeMs, run.runId, "projectLimits.maxAgentTimeMs") } : {},
22417
+ ...limitsValue.agentStepTimeoutMs !== void 0 ? { agentStepTimeoutMs: asAgentStepTimeout(limitsValue.agentStepTimeoutMs, run.runId, "projectLimits.agentStepTimeoutMs") } : {}
22410
22418
  };
22411
22419
  const plan = freezeKxmCompiledPlan(parseCompiledPlan(value.plan, run.runId));
22412
22420
  return {
@@ -22809,6 +22817,12 @@ function asDuration(value, runId, label) {
22809
22817
  }
22810
22818
  return value;
22811
22819
  }
22820
+ function asAgentStepTimeout(value, runId, label) {
22821
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 6e4) {
22822
+ throw runtimeError("run_plan_corrupt", runId, `${label} is below 60000`);
22823
+ }
22824
+ return value;
22825
+ }
22812
22826
  function asCost(value, runId, label) {
22813
22827
  if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
22814
22828
  throw runtimeError("run_plan_corrupt", runId, `${label} is not a positive cost`);
@@ -23449,13 +23463,18 @@ function kxmDeclaredExecutorIds(bundle) {
23449
23463
  ...[...bundle.agents.values()].map((agent) => agent.value.executor).filter((value) => typeof value === "string")
23450
23464
  ].filter((value) => value !== void 0))].sort();
23451
23465
  }
23466
+ var KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS = 36e5;
23467
+ var KXM_MIN_AGENT_STEP_TIMEOUT_MS = 6e4;
23452
23468
  function kxmProjectAdmissionLimits(bundle) {
23453
23469
  const limits = objectValue3(bundle.project.value.limits);
23454
23470
  const maxConcurrentRuns = typeof limits?.maxConcurrentRuns === "number" && Number.isInteger(limits.maxConcurrentRuns) && limits.maxConcurrentRuns >= 1 ? limits.maxConcurrentRuns : 1;
23471
+ const declared = limits?.agentStepTimeoutMs;
23472
+ const agentStepTimeoutMs = typeof declared === "number" && Number.isInteger(declared) && declared >= KXM_MIN_AGENT_STEP_TIMEOUT_MS ? declared : KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
23455
23473
  return {
23456
23474
  maxConcurrentRuns,
23457
23475
  ...typeof limits?.maxRunDurationMs === "number" ? { maxRunDurationMs: limits.maxRunDurationMs } : {},
23458
- ...typeof limits?.maxAgentTimeMs === "number" ? { maxAgentTimeMs: limits.maxAgentTimeMs } : {}
23476
+ ...typeof limits?.maxAgentTimeMs === "number" ? { maxAgentTimeMs: limits.maxAgentTimeMs } : {},
23477
+ agentStepTimeoutMs
23459
23478
  };
23460
23479
  }
23461
23480
  var closedRuntimeContexts = /* @__PURE__ */ new WeakSet();
@@ -23841,15 +23860,13 @@ function assertKxmConfigError(error) {
23841
23860
  // plugins/kxm/src/runtime-supervisor.ts
23842
23861
  import { spawn as spawn3 } from "node:child_process";
23843
23862
  import { createHash as createHash15, createHmac, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
23844
- import { chmodSync as chmodSync2, existsSync as existsSync16, lstatSync as lstatSync5, mkdirSync as mkdirSync9, readFileSync as readFileSync12, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "node:fs";
23863
+ import { chmodSync as chmodSync2, existsSync as existsSync16, lstatSync as lstatSync6, mkdirSync as mkdirSync9, readFileSync as readFileSync13, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "node:fs";
23845
23864
  import { createServer } from "node:http";
23846
- import { dirname as dirname11, isAbsolute as isAbsolute7, join as join19 } from "node:path";
23847
-
23848
- // plugins/kxm/src/oneshot-producer.ts
23849
- import { join as join16 } from "node:path";
23865
+ import { dirname as dirname11, isAbsolute as isAbsolute7, join as join18 } from "node:path";
23850
23866
 
23851
23867
  // plugins/kxm/src/oneshot-evidence.ts
23852
23868
  import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
23869
+ import { lstatSync as lstatSync4, readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
23853
23870
  import { lstat, mkdir, open, rename } from "node:fs/promises";
23854
23871
  import { join as join8 } from "node:path";
23855
23872
  var ONESHOT_EVIDENCE_SCHEMA = "kxm.oneshot-evidence.v2";
@@ -23874,6 +23891,37 @@ function parseOneShotEvidenceRecord(bytes) {
23874
23891
  if (schema !== ONESHOT_EVIDENCE_SCHEMA) throw new Error("oneshot_evidence_schema_unknown");
23875
23892
  return parsed;
23876
23893
  }
23894
+ function oneShotEvidenceRoot() {
23895
+ return join8(kxmUserStateRoot(), "runtime", "oneshot-evidence");
23896
+ }
23897
+ function readOneShotObservedChildExit(runId, attemptId, root = oneShotEvidenceRoot()) {
23898
+ let names3;
23899
+ try {
23900
+ names3 = readdirSync4(root);
23901
+ } catch {
23902
+ return void 0;
23903
+ }
23904
+ let seenTrue = false;
23905
+ let seenFalse = false;
23906
+ const capped = names3.slice(0, 4096);
23907
+ for (const name of capped) {
23908
+ if (!name.startsWith("evd_")) continue;
23909
+ const dir = join8(root, name);
23910
+ try {
23911
+ const info = lstatSync4(dir);
23912
+ if (!info.isDirectory() || info.isSymbolicLink()) continue;
23913
+ const intent = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "intent.json"), "utf8"));
23914
+ if (intent.runId !== runId || intent.attemptId !== attemptId) continue;
23915
+ const result = parseOneShotEvidenceRecord(readFileSync5(join8(dir, "result.json"), "utf8"));
23916
+ if (result.observedChildExit === true) seenTrue = true;
23917
+ else if (result.observedChildExit === false) seenFalse = true;
23918
+ } catch {
23919
+ }
23920
+ }
23921
+ if (seenFalse) return false;
23922
+ if (seenTrue) return true;
23923
+ return void 0;
23924
+ }
23877
23925
  async function beginOneShotEvidence(root, intent, sensitive) {
23878
23926
  await mkdir(root, { recursive: true, mode: 448 });
23879
23927
  const stat = await lstat(root);
@@ -23932,6 +23980,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
23932
23980
  harness: intent.harness,
23933
23981
  provider: intent.provider,
23934
23982
  requestedModel: intent.model,
23983
+ ...intent.timeoutMs !== void 0 ? { timeoutMs: intent.timeoutMs } : {},
23935
23984
  cwd: intent.cwd,
23936
23985
  command: redact(intent.command),
23937
23986
  argv: bounded(JSON.stringify(intent.args), ARGV_LIMIT),
@@ -23968,7 +24017,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
23968
24017
  // plugins/kxm/src/prices.ts
23969
24018
  var import_yaml3 = __toESM(require_dist(), 1);
23970
24019
  import { createHash as createHash10 } from "node:crypto";
23971
- import { existsSync as existsSync8, readFileSync as readFileSync5, statSync, writeFileSync as writeFileSync3 } from "node:fs";
24020
+ import { existsSync as existsSync8, readFileSync as readFileSync6, statSync, writeFileSync as writeFileSync3 } from "node:fs";
23972
24021
  import { join as join9 } from "node:path";
23973
24022
 
23974
24023
  // plugins/kxm/src/price-calc.ts
@@ -24125,7 +24174,7 @@ function loadPriceCatalog(rootOrPath) {
24125
24174
  if (!candidatePath || !existsSync8(candidatePath)) {
24126
24175
  return void 0;
24127
24176
  }
24128
- const content = readFileSync5(candidatePath, "utf8");
24177
+ const content = readFileSync6(candidatePath, "utf8");
24129
24178
  return parsePriceCatalog(content);
24130
24179
  }
24131
24180
  function loadPriceCatalogForEstimate(options) {
@@ -24144,12 +24193,12 @@ function loadPriceCatalogForEstimate(options) {
24144
24193
  // plugins/kxm/src/engine.ts
24145
24194
  var import_yaml7 = __toESM(require_dist(), 1);
24146
24195
  import { createHash as createHash14, randomBytes as randomBytes2, timingSafeEqual } from "node:crypto";
24147
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
24196
+ import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
24148
24197
  import { join as join15 } from "node:path";
24149
24198
 
24150
24199
  // plugins/kxm/src/routes.ts
24151
24200
  var import_yaml4 = __toESM(require_dist(), 1);
24152
- import { existsSync as existsSync9, readFileSync as readFileSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync4 } from "node:fs";
24201
+ import { existsSync as existsSync9, readFileSync as readFileSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync5 } from "node:fs";
24153
24202
  import { join as join10 } from "node:path";
24154
24203
  var RETIRED_POLICY = ".kxm/producers.yaml";
24155
24204
  var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [], roles: {} });
@@ -24157,7 +24206,7 @@ function loadRoutePolicy(root) {
24157
24206
  if (existsSync9(join10(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
24158
24207
  const path = join10(root, ".kxm", "routes.yaml");
24159
24208
  if (!existsSync9(path)) return empty();
24160
- const value = (0, import_yaml4.parse)(readFileSync6(path, "utf8"));
24209
+ const value = (0, import_yaml4.parse)(readFileSync7(path, "utf8"));
24161
24210
  if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
24162
24211
  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") : [], roles: value.roles && typeof value.roles === "object" ? Object.fromEntries(Object.entries(value.roles).filter(([, v]) => Array.isArray(v)).map(([k, v]) => [k, v.filter((x) => typeof x === "string")])) : {} };
24163
24212
  }
@@ -24165,9 +24214,9 @@ function listRoleBindings(root) {
24165
24214
  const dir = join10(root, ".kxm", "roles");
24166
24215
  const result = {};
24167
24216
  if (!existsSync9(dir)) return result;
24168
- for (const file of readdirSync4(dir).filter((name) => name.endsWith(".yaml"))) {
24217
+ for (const file of readdirSync5(dir).filter((name) => name.endsWith(".yaml"))) {
24169
24218
  const role = file.slice(0, -5);
24170
- const value = (0, import_yaml4.parse)(readFileSync6(join10(dir, file), "utf8"));
24219
+ const value = (0, import_yaml4.parse)(readFileSync7(join10(dir, file), "utf8"));
24171
24220
  result[role] = (value.roster ?? []).map((entry) => entry.model).filter((model) => typeof model === "string");
24172
24221
  }
24173
24222
  return result;
@@ -24494,7 +24543,7 @@ function pruneContextPacket(packet, tokenBudget) {
24494
24543
 
24495
24544
  // plugins/kxm/src/dispatch-context.ts
24496
24545
  import { spawnSync as spawnSync4 } from "node:child_process";
24497
- import { readdirSync as readdirSync7 } from "node:fs";
24546
+ import { readdirSync as readdirSync8 } from "node:fs";
24498
24547
  import { extname as extname3, join as join13 } from "node:path";
24499
24548
 
24500
24549
  // plugins/kxm/src/protocol.ts
@@ -25127,7 +25176,7 @@ function memoryRecordToContextItem(record2, project) {
25127
25176
 
25128
25177
  // plugins/kxm/src/memory.ts
25129
25178
  var import_yaml5 = __toESM(require_dist(), 1);
25130
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
25179
+ import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
25131
25180
  import { extname as extname2, join as join11, resolve as resolve7 } from "node:path";
25132
25181
  var MEMORY_SCHEMA = "kxm.memory.v1";
25133
25182
  var VALID_SCOPES = /* @__PURE__ */ new Set(["agent", "project", "run", "operator"]);
@@ -25235,12 +25284,12 @@ function loadAuthoredMemory(repoRoot) {
25235
25284
  const { memoryDir } = memoryDirectories(repoRoot);
25236
25285
  if (!existsSync10(memoryDir)) return [];
25237
25286
  const records = [];
25238
- const entries = readdirSync5(memoryDir, { withFileTypes: true });
25287
+ const entries = readdirSync6(memoryDir, { withFileTypes: true });
25239
25288
  for (const entry of entries) {
25240
25289
  if (entry.isFile() && extname2(entry.name) === ".md") {
25241
25290
  const fullPath = join11(memoryDir, entry.name);
25242
25291
  try {
25243
- const text = readFileSync7(fullPath, "utf8");
25292
+ const text = readFileSync8(fullPath, "utf8");
25244
25293
  const record2 = parseMemoryRecord(text, entry.name);
25245
25294
  if (record2.lifecycle === "active") {
25246
25295
  records.push(record2);
@@ -25256,7 +25305,7 @@ function loadAuthoredMemory(repoRoot) {
25256
25305
  // plugins/kxm/src/skills.ts
25257
25306
  var import_yaml6 = __toESM(require_dist(), 1);
25258
25307
  import { createHash as createHash11 } from "node:crypto";
25259
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as readdirSync6, readFileSync as readFileSync8, renameSync, rmSync, statSync as statSync2, writeFileSync as writeFileSync6 } from "node:fs";
25308
+ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as readdirSync7, readFileSync as readFileSync9, renameSync, rmSync, statSync as statSync2, writeFileSync as writeFileSync6 } from "node:fs";
25260
25309
  import { dirname as dirname7, join as join12 } from "node:path";
25261
25310
  var SKILL_CANDIDATE_SCHEMA = "kxm.skill-candidate.v1";
25262
25311
  var SKILL_EVALUATION_SCHEMA = "kxm.skill-evaluation.v1";
@@ -25376,7 +25425,7 @@ var SkillLifecycle = class {
25376
25425
  const line = `${JSON.stringify(record2)}
25377
25426
  `;
25378
25427
  if (existsSync11(this.historyFile(id))) {
25379
- const existing = readFileSync8(this.historyFile(id), "utf8");
25428
+ const existing = readFileSync9(this.historyFile(id), "utf8");
25380
25429
  const lines = existing.split("\n").filter((entry) => entry.trim());
25381
25430
  this.write(this.historyFile(id), [...lines.slice(-499), line.trim()].join("\n") + "\n");
25382
25431
  } else {
@@ -25386,14 +25435,14 @@ var SkillLifecycle = class {
25386
25435
  history(id) {
25387
25436
  const file = this.historyFile(id);
25388
25437
  if (!existsSync11(file)) return [];
25389
- return readFileSync8(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
25438
+ return readFileSync9(file, "utf8").split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
25390
25439
  }
25391
25440
  readMetadata(state, id) {
25392
25441
  const { metadata } = this.paths(state, id);
25393
25442
  if (!existsSync11(metadata)) {
25394
25443
  throw new SkillLifecycleError("skill_not_found", `skill ${id} not found in ${state}`);
25395
25444
  }
25396
- return JSON.parse(readFileSync8(metadata, "utf8"));
25445
+ return JSON.parse(readFileSync9(metadata, "utf8"));
25397
25446
  }
25398
25447
  move(from, to, id) {
25399
25448
  const fromDir = join12(this.dir(from), id);
@@ -25558,8 +25607,8 @@ var SkillLifecycle = class {
25558
25607
  };
25559
25608
  const candidatePaths = this.paths("candidate", candidateId);
25560
25609
  const promotedPaths = this.paths("promoted", candidateId);
25561
- const skillContent = readFileSync8(candidatePaths.skill, "utf8");
25562
- const metadataContent = readFileSync8(candidatePaths.metadata, "utf8");
25610
+ const skillContent = readFileSync9(candidatePaths.skill, "utf8");
25611
+ const metadataContent = readFileSync9(candidatePaths.metadata, "utf8");
25563
25612
  this.write(promotedPaths.skill, skillContent);
25564
25613
  this.write(promotedPaths.metadata, metadataContent);
25565
25614
  const patchPath = join12(this.root, "patches", `${candidateId}.patch`);
@@ -25590,7 +25639,7 @@ var SkillLifecycle = class {
25590
25639
  verify(state, id) {
25591
25640
  const metadata = this.readMetadata(state, id);
25592
25641
  const { skill } = this.paths(state, id);
25593
- const content = readFileSync8(skill, "utf8");
25642
+ const content = readFileSync9(skill, "utf8");
25594
25643
  if (skillContentSha256(content) !== metadata.contentSha256) {
25595
25644
  throw new SkillLifecycleError(
25596
25645
  "skill_integrity_violation",
@@ -25621,7 +25670,7 @@ var SkillLifecycle = class {
25621
25670
  read(state, id) {
25622
25671
  const metadata = this.readMetadata(state, id);
25623
25672
  const { skill } = this.paths(state, id);
25624
- return { metadata, content: readFileSync8(skill, "utf8") };
25673
+ return { metadata, content: readFileSync9(skill, "utf8") };
25625
25674
  }
25626
25675
  };
25627
25676
  function boundedList(value, field) {
@@ -25636,7 +25685,7 @@ function boundedList(value, field) {
25636
25685
  return [...new Set(refs)];
25637
25686
  }
25638
25687
  function readdirSorted(dir) {
25639
- return readdirSync6(dir).filter((entry) => statSync2(join12(dir, entry)).isDirectory()).sort();
25688
+ return readdirSync7(dir).filter((entry) => statSync2(join12(dir, entry)).isDirectory()).sort();
25640
25689
  }
25641
25690
 
25642
25691
  // plugins/kxm/src/dispatch-context.ts
@@ -25681,14 +25730,14 @@ function dispatchContextPresent(projectRoot) {
25681
25730
  }
25682
25731
  function hasTopLevelMarkdown(dir) {
25683
25732
  try {
25684
- return readdirSync7(dir, { withFileTypes: true }).some((entry) => entry.isFile() && extname3(entry.name) === ".md");
25733
+ return readdirSync8(dir, { withFileTypes: true }).some((entry) => entry.isFile() && extname3(entry.name) === ".md");
25685
25734
  } catch {
25686
25735
  return false;
25687
25736
  }
25688
25737
  }
25689
25738
  function hasAnyEntry(dir) {
25690
25739
  try {
25691
- return readdirSync7(dir).length > 0;
25740
+ return readdirSync8(dir).length > 0;
25692
25741
  } catch {
25693
25742
  return false;
25694
25743
  }
@@ -25839,7 +25888,7 @@ function assembleDispatchContext(sources, input) {
25839
25888
  import { join as join14 } from "node:path";
25840
25889
 
25841
25890
  // plugins/kxm/src/artifacts-exist.ts
25842
- import { lstatSync as lstatSync4, realpathSync as realpathSync3, statSync as statSync3 } from "node:fs";
25891
+ import { lstatSync as lstatSync5, realpathSync as realpathSync3, statSync as statSync3 } from "node:fs";
25843
25892
  import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve8 } from "node:path";
25844
25893
  function staysUnder(root, candidate) {
25845
25894
  const child = relative4(root, candidate);
@@ -25867,7 +25916,7 @@ function verifyArtifactExists(rootInput, pathInput) {
25867
25916
  return { ok: false, error: "artifact_outside_workspace_assets", path: lexicalPath };
25868
25917
  }
25869
25918
  try {
25870
- const link = lstatSync4(lexicalPath);
25919
+ const link = lstatSync5(lexicalPath);
25871
25920
  if (link.isSymbolicLink()) {
25872
25921
  return { ok: false, error: "artifact_outside_workspace_assets", path: lexicalPath };
25873
25922
  }
@@ -27130,6 +27179,10 @@ async function driveAdmitted(context, runId, producer, token, options = {}) {
27130
27179
  if (started.handoff || isTerminalRunStatus(started.state.status)) return started;
27131
27180
  }
27132
27181
  let latest = { state: foldStoredKxmRun(context, requireRun(context, runId)) };
27182
+ if (latest.state.status === "cancelling") {
27183
+ latest = await stepLocked(context, runId, producer, token);
27184
+ if (latest.handoff || isTerminalRunStatus(latest.state.status)) return latest;
27185
+ }
27133
27186
  while (latest.state.status === "running") {
27134
27187
  const overBudget = cancelRunDurationIfExceeded(context, runId);
27135
27188
  if (overBudget) return overBudget;
@@ -27158,7 +27211,8 @@ function receiptHandoff(handoff) {
27158
27211
  reason: handoff.reason,
27159
27212
  detail: handoff.detail,
27160
27213
  ...handoff.field !== void 0 ? { field: handoff.field } : {},
27161
- ...handoff.stepId !== void 0 ? { stepId: handoff.stepId } : {}
27214
+ ...handoff.stepId !== void 0 ? { stepId: handoff.stepId } : {},
27215
+ ...handoff.attemptId !== void 0 ? { attemptId: handoff.attemptId } : {}
27162
27216
  };
27163
27217
  }
27164
27218
  function appendDriveOpened(context, runId, driveId, mode) {
@@ -27216,6 +27270,9 @@ function recordDriveReceipt(context, session, closeInfo) {
27216
27270
  producer: { id: closeInfo.producerId, closed: closeInfo.producerClosed }
27217
27271
  };
27218
27272
  context.eventStore.insertDriveReceipt(receipt);
27273
+ if (closeInfo.kind === "handoff") {
27274
+ releaseKxmRun(context.eventStore.path, session.runId, session.token);
27275
+ }
27219
27276
  } catch {
27220
27277
  }
27221
27278
  }
@@ -27357,7 +27414,7 @@ var KxmRunScheduler = class _KxmRunScheduler {
27357
27414
  }
27358
27415
  try {
27359
27416
  const run = requireRun(this.context, runId);
27360
- if (isTerminalRunStatus(run.status) || run.status === "cancelling") {
27417
+ if (isTerminalRunStatus(run.status)) {
27361
27418
  return Promise.reject(runtimeError("run_busy", runId, `run ${runId} is already ${run.status}`));
27362
27419
  }
27363
27420
  } catch (error) {
@@ -27775,7 +27832,7 @@ function resolveProducerRoute(projectRoot, step, agentId) {
27775
27832
  const agentFile = join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`);
27776
27833
  if (existsSync12(agentFile)) {
27777
27834
  try {
27778
- const parsed = (0, import_yaml7.parse)(readFileSync9(agentFile, "utf8"));
27835
+ const parsed = (0, import_yaml7.parse)(readFileSync10(agentFile, "utf8"));
27779
27836
  if (typeof parsed?.model === "string") {
27780
27837
  agentModel = parsed.model;
27781
27838
  } else if (parsed?.model && typeof parsed.model === "object" && !Array.isArray(parsed.model)) {
@@ -27847,6 +27904,63 @@ function resolveProducerRoute(projectRoot, step, agentId) {
27847
27904
  const model = selector.slice(slash + 1);
27848
27905
  return { provider, model, selector };
27849
27906
  }
27907
+ function projectAgentStepTimeoutMs(context, run) {
27908
+ return loadKxmRunPlanEnvelope(context.eventStore, run).projectLimits.agentStepTimeoutMs ?? KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
27909
+ }
27910
+ function unsupportedAgentStepTimeout(step, limitMs) {
27911
+ if (step.kind !== "agent" && step.kind !== "moa") return void 0;
27912
+ if (step.timeoutMs === void 0 || step.timeoutMs <= limitMs) return void 0;
27913
+ return {
27914
+ reason: "step_unsupported",
27915
+ field: "timeoutMs",
27916
+ detail: "step timeoutMs is wider than project limits.agentStepTimeoutMs"
27917
+ };
27918
+ }
27919
+ function executingSingletonAttempt(plan, state) {
27920
+ const current = state.currentStep;
27921
+ if (!current || current.panel.order.length !== 1) return void 0;
27922
+ const step = plan.steps[current.stepId];
27923
+ if (!step || step.kind !== "agent" && step.kind !== "moa" || step.assignments.maximum > 1) return void 0;
27924
+ const attemptId = unreconciledPanelAttemptId(state);
27925
+ if (!attemptId) return void 0;
27926
+ const located = kxmFoldPanelAttempt(current, attemptId);
27927
+ if (located?.attempt.status !== "executing") return void 0;
27928
+ return { stepId: current.stepId, assignmentId: located.assignmentId, attemptId };
27929
+ }
27930
+ function settleExitedExecutingAttempt(context, run, executing) {
27931
+ const now = (/* @__PURE__ */ new Date()).toISOString();
27932
+ let sequence = context.eventStore.nextSequence(run.runId);
27933
+ let mono = kxmMonotonicNs();
27934
+ const events = [];
27935
+ const push = (eventType, payload) => {
27936
+ events.push({
27937
+ ...kxmEventBase(context, run, now, mono),
27938
+ eventId: newKxmEventId(),
27939
+ eventType,
27940
+ sequence: sequence++,
27941
+ payload
27942
+ });
27943
+ mono = kxmIncrementMonotonicNs(mono);
27944
+ };
27945
+ push("attempt.status_changed", { attemptId: executing.attemptId, status: "settling" });
27946
+ push("assignment.result_recorded", {
27947
+ assignmentId: executing.assignmentId,
27948
+ resultClass: "producer_rejected",
27949
+ status: "result_recorded",
27950
+ producerError: "executing_unrecorded",
27951
+ reason: "executing_unrecorded"
27952
+ });
27953
+ push("attempt.status_changed", { attemptId: executing.attemptId, status: "terminal" });
27954
+ push("assignment.terminal", { assignmentId: executing.assignmentId, outcome: "failed", status: "terminal" });
27955
+ push("step.status_changed", { stepId: executing.stepId, status: "cancelled", previousStatus: "running" });
27956
+ push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
27957
+ for (const event of events) context.eventStore.appendEvent(event);
27958
+ context.eventStore.settleCapability(executing.attemptId, "settled");
27959
+ const next = foldStoredKxmRun(context, run);
27960
+ persistKxmRunState(context, run.runId, next, events[events.length - 1].sequence);
27961
+ context.eventStore.updateRunStatus(run.runId, "cancelled", now);
27962
+ return next;
27963
+ }
27850
27964
  function prepareDispatch(context, runId, producerId, dispatchSources) {
27851
27965
  const run = requireRun(context, runId);
27852
27966
  const plan = rehydrateKxmCompiledPlanFromStore(context.eventStore, run);
@@ -27855,6 +27969,23 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
27855
27969
  return { kind: "return", state };
27856
27970
  }
27857
27971
  if (state.status === "cancelling" && kxmAttemptControllers(context.eventStore.path, runId).length === 0) {
27972
+ const executing = executingSingletonAttempt(plan, state);
27973
+ if (executing) {
27974
+ const exited = readOneShotObservedChildExit(runId, executing.attemptId);
27975
+ if (exited === true) {
27976
+ return { kind: "return", state: settleExitedExecutingAttempt(context, run, executing) };
27977
+ }
27978
+ return {
27979
+ kind: "return",
27980
+ state,
27981
+ handoff: {
27982
+ reason: "attempt_unreconciled",
27983
+ stepId: executing.stepId,
27984
+ attemptId: executing.attemptId,
27985
+ detail: "issued attempt is not held by this process"
27986
+ }
27987
+ };
27988
+ }
27858
27989
  return {
27859
27990
  kind: "return",
27860
27991
  state,
@@ -27975,6 +28106,8 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
27975
28106
  }
27976
28107
  const unsupported = unsupportedStep(plan, step, producerId);
27977
28108
  if (unsupported) return { kind: "return", state, handoff: { ...unsupported, stepId } };
28109
+ const wideTimeout = unsupportedAgentStepTimeout(step, projectAgentStepTimeoutMs(context, run));
28110
+ if (wideTimeout) return { kind: "return", state, handoff: { ...wideTimeout, stepId } };
27978
28111
  let resolvedRoute;
27979
28112
  if (producerId !== "driver-simulated") {
27980
28113
  const allowed = step.assignments.allowedAgents;
@@ -28201,6 +28334,7 @@ function birthMember(context, input) {
28201
28334
  ${generatedPrompt}` : generatedPrompt,
28202
28335
  thinking: input.stepAttempt <= 1 ? "low" : "medium",
28203
28336
  permission: Object.values(input.step.repositories).some((access) => access === "write") ? "edit" : "read-only",
28337
+ ...(input.step.kind === "agent" || input.step.kind === "moa") && input.step.timeoutMs !== void 0 ? { timeoutMs: input.step.timeoutMs } : {},
28204
28338
  contextPacket,
28205
28339
  ...resolvedRoute ? { provider: resolvedRoute.provider, model: resolvedRoute.model } : {}
28206
28340
  },
@@ -28981,7 +29115,7 @@ function unsupportedStep(plan, step, producerId) {
28981
29115
  function readYamlRecord(path) {
28982
29116
  if (!existsSync12(path)) return void 0;
28983
29117
  try {
28984
- const parsed = (0, import_yaml7.parse)(readFileSync9(path, "utf8"));
29118
+ const parsed = (0, import_yaml7.parse)(readFileSync10(path, "utf8"));
28985
29119
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
28986
29120
  } catch {
28987
29121
  return void 0;
@@ -29664,7 +29798,8 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
29664
29798
  }
29665
29799
  const spawnFn = options.spawnProcess ?? defaultSpawn;
29666
29800
  const cwd = options.projectRoot ?? process.cwd();
29667
- const evidence = await beginOneShotEvidence(options.evidenceRoot ?? join16(kxmUserStateRoot(), "runtime", "oneshot-evidence"), {
29801
+ const timeoutMs = request.timeoutMs ?? options.timeoutMs;
29802
+ const evidence = await beginOneShotEvidence(options.evidenceRoot ?? oneShotEvidenceRoot(), {
29668
29803
  runId: request.runId,
29669
29804
  stepId: request.stepId,
29670
29805
  attemptId: request.attemptId,
@@ -29675,11 +29810,12 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
29675
29810
  cwd,
29676
29811
  command,
29677
29812
  args,
29678
- input
29813
+ input,
29814
+ timeoutMs: timeoutMs ?? 12e4
29679
29815
  }, [request.capability, ...Object.entries(env).filter(([key]) => /TOKEN|KEY|SECRET|PASSWORD|COOKIE|AUTH/i.test(key)).map(([, value]) => value ?? "")]);
29680
29816
  let procResult;
29681
29817
  try {
29682
- procResult = request.signal.aborted ? { stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") } : await spawnFn(command, args, { cwd, env, input, timeoutMs: options.timeoutMs ?? 12e4, signal: request.signal });
29818
+ procResult = request.signal.aborted ? { stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") } : await spawnFn(command, args, { cwd, env, input, timeoutMs, signal: request.signal });
29683
29819
  } catch (error) {
29684
29820
  procResult = { stdout: "", stderr: "", code: null, observedChildExit: false, error: error instanceof Error ? error : new Error("process_adapter_error") };
29685
29821
  }
@@ -29902,9 +30038,9 @@ var RuntimeHubClient = class {
29902
30038
  };
29903
30039
 
29904
30040
  // plugins/kxm/src/hub-binding.ts
29905
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync10, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
30041
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
29906
30042
  import { homedir as homedir2 } from "node:os";
29907
- import { dirname as dirname8, isAbsolute as isAbsolute5, join as join17, resolve as resolve9 } from "node:path";
30043
+ import { dirname as dirname8, isAbsolute as isAbsolute5, join as join16, resolve as resolve9 } from "node:path";
29908
30044
  var HUB_BINDING_SCHEMA = "kxm.hub-binding.v1";
29909
30045
  var HubBindingError = class extends Error {
29910
30046
  constructor(message) {
@@ -29920,16 +30056,16 @@ function resolveUserStateRoot(env) {
29920
30056
  }
29921
30057
  if (process.platform === "win32") {
29922
30058
  const localAppData = env.LOCALAPPDATA?.trim();
29923
- const base2 = localAppData && isAbsolute5(localAppData) ? localAppData : join17(homedir2(), "AppData", "Local");
30059
+ const base2 = localAppData && isAbsolute5(localAppData) ? localAppData : join16(homedir2(), "AppData", "Local");
29924
30060
  return resolve9(base2, "KXM");
29925
30061
  }
29926
30062
  if (process.platform === "darwin") return resolve9(homedir2(), "Library", "Application Support", "KXM");
29927
30063
  const xdgState = env.XDG_STATE_HOME?.trim();
29928
- const base = xdgState && isAbsolute5(xdgState) ? xdgState : join17(homedir2(), ".local", "state");
30064
+ const base = xdgState && isAbsolute5(xdgState) ? xdgState : join16(homedir2(), ".local", "state");
29929
30065
  return resolve9(base, "kxm");
29930
30066
  }
29931
30067
  function hubBindingFile(env = process.env) {
29932
- return join17(resolveUserStateRoot(env), "hub-binding.json");
30068
+ return join16(resolveUserStateRoot(env), "hub-binding.json");
29933
30069
  }
29934
30070
  function validateHubUrl(raw) {
29935
30071
  let parsed;
@@ -29952,7 +30088,7 @@ function readHubBinding(env = process.env) {
29952
30088
  if (!existsSync13(file)) return void 0;
29953
30089
  let parsed;
29954
30090
  try {
29955
- parsed = JSON.parse(readFileSync10(file, "utf8"));
30091
+ parsed = JSON.parse(readFileSync11(file, "utf8"));
29956
30092
  } catch {
29957
30093
  throw new HubBindingError(`malformed hub binding at ${file}`);
29958
30094
  }
@@ -29974,9 +30110,9 @@ function readHubBinding(env = process.env) {
29974
30110
  }
29975
30111
 
29976
30112
  // plugins/kxm/src/hub-env.ts
29977
- import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync11, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
30113
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync12, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
29978
30114
  import { homedir as homedir3 } from "node:os";
29979
- import { dirname as dirname9, isAbsolute as isAbsolute6, join as join18, resolve as resolve10 } from "node:path";
30115
+ import { dirname as dirname9, isAbsolute as isAbsolute6, join as join17, resolve as resolve10 } from "node:path";
29980
30116
  var HUB_ENV_SCHEMA = "kxm.hub-env.v1";
29981
30117
  var HubEnvError = class extends Error {
29982
30118
  constructor(message) {
@@ -29992,23 +30128,23 @@ function resolveUserStateRoot2(env) {
29992
30128
  }
29993
30129
  if (process.platform === "win32") {
29994
30130
  const localAppData = env.LOCALAPPDATA?.trim();
29995
- const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join18(homedir3(), "AppData", "Local");
30131
+ const base2 = localAppData && isAbsolute6(localAppData) ? localAppData : join17(homedir3(), "AppData", "Local");
29996
30132
  return resolve10(base2, "KXM");
29997
30133
  }
29998
30134
  if (process.platform === "darwin") return resolve10(homedir3(), "Library", "Application Support", "KXM");
29999
30135
  const xdgState = env.XDG_STATE_HOME?.trim();
30000
- const base = xdgState && isAbsolute6(xdgState) ? xdgState : join18(homedir3(), ".local", "state");
30136
+ const base = xdgState && isAbsolute6(xdgState) ? xdgState : join17(homedir3(), ".local", "state");
30001
30137
  return resolve10(base, "kxm");
30002
30138
  }
30003
30139
  function hubEnvFile(env = process.env) {
30004
- return join18(resolveUserStateRoot2(env), "hub-env.json");
30140
+ return join17(resolveUserStateRoot2(env), "hub-env.json");
30005
30141
  }
30006
30142
  function readHubEnvRecord(env = process.env) {
30007
30143
  const file = hubEnvFile(env);
30008
30144
  if (!existsSync14(file)) return void 0;
30009
30145
  let parsed;
30010
30146
  try {
30011
- parsed = JSON.parse(readFileSync11(file, "utf8"));
30147
+ parsed = JSON.parse(readFileSync12(file, "utf8"));
30012
30148
  } catch (error) {
30013
30149
  throw new HubEnvError(`hub env file is malformed at ${file}: ${error instanceof Error ? error.message : String(error)}`);
30014
30150
  }
@@ -30198,7 +30334,7 @@ function createLogger(options) {
30198
30334
 
30199
30335
  // plugins/kxm/src/runtime-supervisor.ts
30200
30336
  function kxmSupervisorTokenFile(paths) {
30201
- return join19(paths.runtimeDir, "supervisor.token");
30337
+ return join18(paths.runtimeDir, "supervisor.token");
30202
30338
  }
30203
30339
  function publishKxmSupervisorToken(paths, token) {
30204
30340
  const file = kxmSupervisorTokenFile(paths);
@@ -30221,12 +30357,12 @@ function hashKxmSupervisorToken(token) {
30221
30357
  }
30222
30358
  function readKxmSupervisorToken(paths) {
30223
30359
  const file = kxmSupervisorTokenFile(paths);
30224
- const stat = lstatSync5(file, { throwIfNoEntry: false });
30360
+ const stat = lstatSync6(file, { throwIfNoEntry: false });
30225
30361
  if (!stat) return void 0;
30226
30362
  if (stat.isSymbolicLink() || !stat.isFile()) {
30227
30363
  throw runtimeError("runtime_path_invalid", file, "supervisor token file must be a regular file, not a link");
30228
30364
  }
30229
- const token = readFileSync12(file, "utf8").trim();
30365
+ const token = readFileSync13(file, "utf8").trim();
30230
30366
  return token.length >= 32 ? token : void 0;
30231
30367
  }
30232
30368
  function processAlive(pid) {
@@ -30240,7 +30376,7 @@ function processAlive(pid) {
30240
30376
  var HEARTBEAT_STALE_MS = 15e3;
30241
30377
  var SUPERVISOR_ERROR_MAX_AGE_MS = 3e4;
30242
30378
  function supervisorErrorFile(paths) {
30243
- return join19(paths.runtimeDir, "supervisor.error");
30379
+ return join18(paths.runtimeDir, "supervisor.error");
30244
30380
  }
30245
30381
  function clearSupervisorError(paths) {
30246
30382
  const file = supervisorErrorFile(paths);
@@ -30256,12 +30392,12 @@ function recordSupervisorError(paths, message) {
30256
30392
  }
30257
30393
  function readRecentSupervisorError(paths) {
30258
30394
  const file = supervisorErrorFile(paths);
30259
- const stat = lstatSync5(file, { throwIfNoEntry: false });
30395
+ const stat = lstatSync6(file, { throwIfNoEntry: false });
30260
30396
  if (!stat) return void 0;
30261
30397
  const ageMs = Date.now() - stat.mtimeMs;
30262
30398
  if (ageMs > SUPERVISOR_ERROR_MAX_AGE_MS) return void 0;
30263
30399
  try {
30264
- return readFileSync12(file, "utf8").trim();
30400
+ return readFileSync13(file, "utf8").trim();
30265
30401
  } catch {
30266
30402
  return void 0;
30267
30403
  }
@@ -30348,7 +30484,7 @@ async function ensureKxmSupervisor(options = {}) {
30348
30484
  throw runtimeError("runtime_supervisor_unreachable", paths.registryDb, `runtime supervisor pid ${status.pid} is registered as running but cannot be probed`);
30349
30485
  }
30350
30486
  clearSupervisorError(paths);
30351
- const scriptPath = join19(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
30487
+ const scriptPath = join18(findKxmRepoRoot(import.meta.url), "scripts", "kxm-runtime-supervisor.mjs");
30352
30488
  const spawnImpl = options.spawnImpl ?? ((script, env) => {
30353
30489
  const child = spawn3(process.execPath, [script], {
30354
30490
  detached: true,
@@ -30571,7 +30707,7 @@ function syncFailureText(error) {
30571
30707
  return `${code ? `${code}: ` : ""}${message}`.replace(/(kxm_[A-Za-z0-9_]+|[A-Za-z0-9._-]{40,})/g, "[redacted]").slice(0, 300);
30572
30708
  }
30573
30709
  function runtimeSupervisorLogFile(paths) {
30574
- return join19(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
30710
+ return join18(paths.runtimeDir, "logs", "kxm-runtime.jsonl");
30575
30711
  }
30576
30712
  async function startKxmRuntimeSupervisor(options = {}) {
30577
30713
  const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
@@ -30733,6 +30869,7 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
30733
30869
  const delayMs = typeof body.delayMs === "number" && body.delayMs > 0 ? body.delayMs : 0;
30734
30870
  const createProducer = () => body.mode === "live" ? createKxmOneShotProducer({
30735
30871
  projectRoot,
30872
+ timeoutMs: kxmProjectAdmissionLimits(bundle).agentStepTimeoutMs,
30736
30873
  defaultHarness: String(bundle.project.value.defaultHarness ?? "pi"),
30737
30874
  resolveHarness: (agentId) => {
30738
30875
  const agent = bundle.agents.get(agentId);
@@ -31170,7 +31307,7 @@ function handoffSuffix(handoff) {
31170
31307
 
31171
31308
  // plugins/kxm/src/pi-producer.ts
31172
31309
  import { spawn as spawn4 } from "node:child_process";
31173
- import { join as join20 } from "node:path";
31310
+ import { join as join19 } from "node:path";
31174
31311
  import { StringDecoder } from "node:string_decoder";
31175
31312
  function formatPiSessionKey(params) {
31176
31313
  if (params.agentId === "coordinator") {
@@ -31544,7 +31681,7 @@ function createKxmPiProducer(options = {}) {
31544
31681
  const args = ["--mode", "rpc", "--name", displayName];
31545
31682
  if (options.sessionDir) {
31546
31683
  const safeDirName = key.replace(/[^a-zA-Z0-9_-]/g, "_");
31547
- args.push("--session-dir", join20(options.sessionDir, request.runId, safeDirName));
31684
+ args.push("--session-dir", join19(options.sessionDir, request.runId, safeDirName));
31548
31685
  }
31549
31686
  if (model) {
31550
31687
  args.push("--model", model);
@@ -31674,7 +31811,7 @@ function createKxmPiProducer(options = {}) {
31674
31811
  // plugins/kxm/src/improve.ts
31675
31812
  import { createHash as createHash16 } from "node:crypto";
31676
31813
  import { existsSync as existsSync17, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "node:fs";
31677
- import { join as join21, relative as relative5, resolve as resolve11 } from "node:path";
31814
+ import { join as join20, relative as relative5, resolve as resolve11 } from "node:path";
31678
31815
  var CANDIDATE_SCHEMA = "kxm.candidate.v1";
31679
31816
  var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
31680
31817
  var IMPROVEMENT_REPORT_V1_SCHEMA = "kxm.improvement-report.v1";
@@ -31931,7 +32068,7 @@ function groupRoutingRecords(records, options = {}) {
31931
32068
  }
31932
32069
  function buildImprovementReport(records, options = {}) {
31933
32070
  const projectRoot = options.projectRoot ? resolve11(options.projectRoot) : process.cwd();
31934
- const candidatesDir = options.candidatesDir ? resolve11(options.candidatesDir) : join21(projectRoot, ".kxm", "candidates");
32071
+ const candidatesDir = options.candidatesDir ? resolve11(options.candidatesDir) : join20(projectRoot, ".kxm", "candidates");
31935
32072
  const promotionPolicy = options.promotionPolicy ?? "manual_pr";
31936
32073
  const groups = groupRoutingRecords(records, options);
31937
32074
  const candidates = [];
@@ -31945,7 +32082,7 @@ function buildImprovementReport(records, options = {}) {
31945
32082
  group.workflowId
31946
32083
  );
31947
32084
  const diffFileName = `${group.candidateId}.diff`;
31948
- const diffFilePath = join21(candidatesDir, diffFileName);
32085
+ const diffFilePath = join20(candidatesDir, diffFileName);
31949
32086
  const relDiffPath = relative5(projectRoot, diffFilePath).replace(/\\/g, "/");
31950
32087
  const candidate = {
31951
32088
  schema: CANDIDATE_SCHEMA,
@@ -31971,7 +32108,7 @@ function buildImprovementReport(records, options = {}) {
31971
32108
  mkdirSync10(candidatesDir, { recursive: true });
31972
32109
  }
31973
32110
  writeFileSync10(diffFilePath, diff, "utf8");
31974
- const jsonFilePath = join21(candidatesDir, `${group.candidateId}.json`);
32111
+ const jsonFilePath = join20(candidatesDir, `${group.candidateId}.json`);
31975
32112
  writeFileSync10(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
31976
32113
  }
31977
32114
  candidates.push(candidate);
@@ -32000,7 +32137,7 @@ function buildImprovementReport(records, options = {}) {
32000
32137
  }
32001
32138
  function writeImprovementReport(improvementsDir, report, dryRun = false) {
32002
32139
  const stamp = report.createdAt.replace(/[:.]/g, "-");
32003
- const path = join21(improvementsDir, `${stamp}.json`);
32140
+ const path = join20(improvementsDir, `${stamp}.json`);
32004
32141
  if (!dryRun) {
32005
32142
  mkdirSync10(improvementsDir, { recursive: true });
32006
32143
  writeFileSync10(path, `${JSON.stringify(report, null, 2)}
@@ -32503,8 +32640,8 @@ Instructions for Operator:
32503
32640
 
32504
32641
  // plugins/kxm/src/modes.ts
32505
32642
  var import_yaml8 = __toESM(require_dist(), 1);
32506
- import { existsSync as existsSync18, readFileSync as readFileSync14 } from "node:fs";
32507
- import { join as join22 } from "node:path";
32643
+ import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
32644
+ import { join as join21 } from "node:path";
32508
32645
  var DEFAULT_MODES_CONFIG = Object.freeze({
32509
32646
  schema: "kxm.modes.v1",
32510
32647
  majorModes: {
@@ -32567,12 +32704,12 @@ function loadModesConfig(projectRoot) {
32567
32704
  if (!projectRoot) {
32568
32705
  return DEFAULT_MODES_CONFIG;
32569
32706
  }
32570
- const modesPath = join22(projectRoot, ".kxm", "modes.yaml");
32707
+ const modesPath = join21(projectRoot, ".kxm", "modes.yaml");
32571
32708
  if (!existsSync18(modesPath)) {
32572
32709
  return DEFAULT_MODES_CONFIG;
32573
32710
  }
32574
32711
  try {
32575
- const raw = readFileSync14(modesPath, "utf8");
32712
+ const raw = readFileSync15(modesPath, "utf8");
32576
32713
  const parsed = (0, import_yaml8.parse)(raw);
32577
32714
  if (parsed && parsed.schema === "kxm.modes.v1" && parsed.majorModes) {
32578
32715
  return {
@@ -32658,11 +32795,11 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
32658
32795
  estimatedTokens: estimateTokens(baseSystemPromptChars)
32659
32796
  });
32660
32797
  for (const relPath of resolved.contextFiles) {
32661
- const fullPath = join22(projectRoot, relPath);
32798
+ const fullPath = join21(projectRoot, relPath);
32662
32799
  let chars = 0;
32663
32800
  if (existsSync18(fullPath)) {
32664
32801
  try {
32665
- chars = readFileSync14(fullPath, "utf8").length;
32802
+ chars = readFileSync15(fullPath, "utf8").length;
32666
32803
  } catch {
32667
32804
  chars = 0;
32668
32805
  }
@@ -32794,9 +32931,9 @@ ${divider}
32794
32931
 
32795
32932
  // plugins/kxm/src/ssh-remote.ts
32796
32933
  import { spawnSync as spawnSync5 } from "node:child_process";
32797
- import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync15, readdirSync as readdirSync8, rmSync as rmSync5, statSync as statSync5 } from "node:fs";
32934
+ import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync16, readdirSync as readdirSync9, rmSync as rmSync5, statSync as statSync5 } from "node:fs";
32798
32935
  import { homedir as homedir4 } from "node:os";
32799
- import { join as join23, resolve as resolve12 } from "node:path";
32936
+ import { join as join22, resolve as resolve12 } from "node:path";
32800
32937
  var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
32801
32938
  var MAX_SSH_OUTPUT_LINES = 2e3;
32802
32939
  var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
@@ -32822,12 +32959,12 @@ function truncateSshOutput(raw) {
32822
32959
  return { text, truncated };
32823
32960
  }
32824
32961
  function parseSshConfig(configPath) {
32825
- const targetPath = configPath ?? join23(homedir4(), ".ssh", "config");
32962
+ const targetPath = configPath ?? join22(homedir4(), ".ssh", "config");
32826
32963
  if (!existsSync19(targetPath)) {
32827
32964
  return [];
32828
32965
  }
32829
32966
  try {
32830
- const content = readFileSync15(targetPath, "utf-8");
32967
+ const content = readFileSync16(targetPath, "utf-8");
32831
32968
  const lines = content.split("\n");
32832
32969
  const hosts = [];
32833
32970
  let currentHosts = [];
@@ -32912,7 +33049,7 @@ function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
32912
33049
  }
32913
33050
  function buildSshArgs(options) {
32914
33051
  const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
32915
- const controlPath = join23(socketDir, "%C");
33052
+ const controlPath = join22(socketDir, "%C");
32916
33053
  const persist2 = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
32917
33054
  const args = [
32918
33055
  "-o",
@@ -32937,7 +33074,7 @@ function buildSshArgs(options) {
32937
33074
  }
32938
33075
  function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync5) {
32939
33076
  const resolvedDir = ensureSocketDir(socketDir);
32940
- const controlPath = join23(resolvedDir, "%C");
33077
+ const controlPath = join22(resolvedDir, "%C");
32941
33078
  try {
32942
33079
  const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
32943
33080
  encoding: "utf-8"
@@ -32949,7 +33086,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
32949
33086
  }
32950
33087
  function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync5) {
32951
33088
  const resolvedDir = ensureSocketDir(socketDir);
32952
- const controlPath = join23(resolvedDir, "%C");
33089
+ const controlPath = join22(resolvedDir, "%C");
32953
33090
  try {
32954
33091
  const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
32955
33092
  encoding: "utf-8"
@@ -32963,9 +33100,9 @@ function pruneSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
32963
33100
  const resolvedDir = ensureSocketDir(socketDir);
32964
33101
  let removed = 0;
32965
33102
  try {
32966
- const entries = readdirSync8(resolvedDir);
33103
+ const entries = readdirSync9(resolvedDir);
32967
33104
  for (const entry of entries) {
32968
- const fullPath = join23(resolvedDir, entry);
33105
+ const fullPath = join22(resolvedDir, entry);
32969
33106
  try {
32970
33107
  const stat = statSync5(fullPath);
32971
33108
  if (stat.isSocket()) {
@@ -33401,9 +33538,11 @@ export {
33401
33538
  IMPROVEMENT_REPORT_V1_SCHEMA,
33402
33539
  KXM_ABSENT_MEMORY_REVISION,
33403
33540
  KXM_BACKUP_CEILINGS,
33541
+ KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS,
33404
33542
  KXM_DRIVE_RECEIPT_SCHEMA,
33405
33543
  KXM_EVENT_STORE_SCHEMA_VERSION,
33406
33544
  KXM_EVENT_STORE_TABLE_NAMES,
33545
+ KXM_MIN_AGENT_STEP_TIMEOUT_MS,
33407
33546
  KXM_REGISTRY_SCHEMA_VERSION,
33408
33547
  KXM_RUN_EVENT_SCHEMA,
33409
33548
  KxmRunEventStore,