@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.kxm/workflows/implement-only.yaml +20 -0
- package/.kxm/workflows/review-arch-only.yaml +20 -0
- package/.kxm/workflows/review-cli-only.yaml +20 -0
- package/CHANGELOG.md +31 -3
- package/docs/architecture/access-schema.yaml +60 -0
- package/docs/architecture/access.md +33 -0
- package/docs/architecture/agent-path.md +36 -0
- package/docs/architecture/authentication.md +29 -0
- package/docs/architecture/hosted-direction.md +59 -0
- package/docs/architecture/index.md +19 -0
- package/docs/architecture/inventory.md +38 -0
- package/docs/architecture/platform.md +48 -0
- package/docs/assets/logo.png +0 -0
- package/docs/contributing/assignment-runner.md +15 -4
- package/docs/index.md +56 -0
- package/docs/javascripts/mermaid-init.js +83 -0
- package/docs/javascripts/mermaid.min.js +4376 -0
- package/docs/reference/cli-reference.md +57 -4
- package/docs/reference/config-reference.md +2 -1
- package/docs/reference/workflow-catalog.md +10 -0
- package/docs/reference/workflow-definitions.md +1 -1
- package/docs/robots.txt +44 -0
- package/docs/stylesheets/extra.css +100 -0
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +265 -165
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime-supervisor.js +209 -72
- package/plugins/kxm/dist/runtime.js +233 -94
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +1 -2
- package/plugins/kxm/skills/kxm-runs/SKILL.md +7 -0
- package/plugins/kxm/src/cli/docs.ts +78 -0
- package/plugins/kxm/src/cli/project.ts +14 -2
- package/plugins/kxm/src/cli.ts +14 -0
- package/plugins/kxm/src/engine-fold.ts +15 -7
- package/plugins/kxm/src/engine-plan.ts +10 -1
- package/plugins/kxm/src/engine.ts +105 -2
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/oneshot-evidence.ts +44 -0
- package/plugins/kxm/src/oneshot-producer.ts +5 -5
- package/plugins/kxm/src/runtime-service.ts +10 -0
- package/plugins/kxm/src/runtime-store.ts +1 -0
- package/plugins/kxm/src/runtime-supervisor.ts +2 -0
- package/schemas/drive-receipt.schema.json +1 -0
- package/schemas/project.schema.json +2 -1
- package/schemas/roadmap-state.schema.json +147 -0
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -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
|
|
18564
|
-
const minimumPassed =
|
|
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
|
|
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:
|
|
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
|
|
20945
|
-
if (!
|
|
20946
|
-
const declared = stringValue2(
|
|
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(
|
|
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
|
|
20952
|
+
...typeof join56.cancelRemaining === "boolean" ? { cancelRemaining: join56.cancelRemaining } : {}
|
|
20953
20953
|
};
|
|
20954
20954
|
return compiled;
|
|
20955
20955
|
}
|
|
@@ -21375,13 +21375,16 @@ function objectValue3(value) {
|
|
|
21375
21375
|
function kxmProjectAdmissionLimits(bundle) {
|
|
21376
21376
|
const limits = objectValue3(bundle.project.value.limits);
|
|
21377
21377
|
const maxConcurrentRuns = typeof limits?.maxConcurrentRuns === "number" && Number.isInteger(limits.maxConcurrentRuns) && limits.maxConcurrentRuns >= 1 ? limits.maxConcurrentRuns : 1;
|
|
21378
|
+
const declared = limits?.agentStepTimeoutMs;
|
|
21379
|
+
const agentStepTimeoutMs = typeof declared === "number" && Number.isInteger(declared) && declared >= KXM_MIN_AGENT_STEP_TIMEOUT_MS ? declared : KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
|
|
21378
21380
|
return {
|
|
21379
21381
|
maxConcurrentRuns,
|
|
21380
21382
|
...typeof limits?.maxRunDurationMs === "number" ? { maxRunDurationMs: limits.maxRunDurationMs } : {},
|
|
21381
|
-
...typeof limits?.maxAgentTimeMs === "number" ? { maxAgentTimeMs: limits.maxAgentTimeMs } : {}
|
|
21383
|
+
...typeof limits?.maxAgentTimeMs === "number" ? { maxAgentTimeMs: limits.maxAgentTimeMs } : {},
|
|
21384
|
+
agentStepTimeoutMs
|
|
21382
21385
|
};
|
|
21383
21386
|
}
|
|
21384
|
-
var RUNTIME_EPOCH_NS;
|
|
21387
|
+
var KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS, KXM_MIN_AGENT_STEP_TIMEOUT_MS, RUNTIME_EPOCH_NS;
|
|
21385
21388
|
var init_runtime_service = __esm({
|
|
21386
21389
|
"plugins/kxm/src/runtime-service.ts"() {
|
|
21387
21390
|
"use strict";
|
|
@@ -21391,6 +21394,8 @@ var init_runtime_service = __esm({
|
|
|
21391
21394
|
init_engine_plan();
|
|
21392
21395
|
init_runtime_owner();
|
|
21393
21396
|
init_runtime_store();
|
|
21397
|
+
KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS = 36e5;
|
|
21398
|
+
KXM_MIN_AGENT_STEP_TIMEOUT_MS = 6e4;
|
|
21394
21399
|
RUNTIME_EPOCH_NS = process.hrtime.bigint();
|
|
21395
21400
|
}
|
|
21396
21401
|
});
|
|
@@ -21400,6 +21405,7 @@ var TEXT_LIMIT, ARGV_LIMIT, RECORD_LIMIT;
|
|
|
21400
21405
|
var init_oneshot_evidence = __esm({
|
|
21401
21406
|
"plugins/kxm/src/oneshot-evidence.ts"() {
|
|
21402
21407
|
"use strict";
|
|
21408
|
+
init_bindings();
|
|
21403
21409
|
TEXT_LIMIT = 4 * 1024 * 1024;
|
|
21404
21410
|
ARGV_LIMIT = 64 * 1024;
|
|
21405
21411
|
RECORD_LIMIT = 16 * 1024 * 1024;
|
|
@@ -23195,6 +23201,15 @@ function resolveProducerRoute(projectRoot, step, agentId) {
|
|
|
23195
23201
|
const model = selector.slice(slash + 1);
|
|
23196
23202
|
return { provider, model, selector };
|
|
23197
23203
|
}
|
|
23204
|
+
function unsupportedAgentStepTimeout(step, limitMs) {
|
|
23205
|
+
if (step.kind !== "agent" && step.kind !== "moa") return void 0;
|
|
23206
|
+
if (step.timeoutMs === void 0 || step.timeoutMs <= limitMs) return void 0;
|
|
23207
|
+
return {
|
|
23208
|
+
reason: "step_unsupported",
|
|
23209
|
+
field: "timeoutMs",
|
|
23210
|
+
detail: "step timeoutMs is wider than project limits.agentStepTimeoutMs"
|
|
23211
|
+
};
|
|
23212
|
+
}
|
|
23198
23213
|
function kxmLiveRunPrerequisites(bundle, workflowId, projectRoot) {
|
|
23199
23214
|
const workflow = bundle.workflows.get(workflowId);
|
|
23200
23215
|
if (!workflow) throw runtimeError("run_workflow_unknown", workflowId, `workflow ${workflowId} does not exist in this project`);
|
|
@@ -23213,7 +23228,8 @@ function kxmLiveRunPrerequisites(bundle, workflowId, projectRoot) {
|
|
|
23213
23228
|
for (const transition2 of Object.values(step.transitions)) {
|
|
23214
23229
|
if (transition2.to === "step") pending.push(transition2.target);
|
|
23215
23230
|
}
|
|
23216
|
-
const
|
|
23231
|
+
const limitMs = envelope.projectLimits.agentStepTimeoutMs ?? KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
|
|
23232
|
+
const unsupported = step.kind === "gate" ? unsupportedGateStep(plan, step, envelope, { projectRoot }) ?? starterGatePrerequisite(step, envelope.gates, projectRoot) : unsupportedAgentStepTimeout(step, limitMs) ?? unsupportedStep(plan, step, "oneshot");
|
|
23217
23233
|
if (unsupported) {
|
|
23218
23234
|
prerequisites.push({ ...unsupported, stepId });
|
|
23219
23235
|
continue;
|
|
@@ -23533,6 +23549,7 @@ var init_engine = __esm({
|
|
|
23533
23549
|
init_context_packet();
|
|
23534
23550
|
init_engine_compile();
|
|
23535
23551
|
init_harness();
|
|
23552
|
+
init_oneshot_evidence();
|
|
23536
23553
|
init_engine_fold();
|
|
23537
23554
|
init_engine_plan();
|
|
23538
23555
|
init_dispatch_context();
|
|
@@ -23556,7 +23573,6 @@ var init_oneshot_producer = __esm({
|
|
|
23556
23573
|
"plugins/kxm/src/oneshot-producer.ts"() {
|
|
23557
23574
|
"use strict";
|
|
23558
23575
|
init_oneshot_evidence();
|
|
23559
|
-
init_bindings();
|
|
23560
23576
|
init_oneshot_process();
|
|
23561
23577
|
init_oneshot_process();
|
|
23562
23578
|
init_harness();
|
|
@@ -26990,7 +27006,10 @@ function formatDriveStatusLine(runStatus, drive) {
|
|
|
26990
27006
|
}
|
|
26991
27007
|
function formatRunStatusLine(run, drive) {
|
|
26992
27008
|
const reason = typeof drive?.receipt?.settlement?.reason === "string" ? drive.receipt.settlement.reason : "";
|
|
26993
|
-
const
|
|
27009
|
+
const handoff = drive?.receipt?.settlement?.handoff;
|
|
27010
|
+
const attemptId = typeof handoff?.attemptId === "string" ? handoff.attemptId : "";
|
|
27011
|
+
const handoffReason = typeof handoff?.reason === "string" ? handoff.reason : "";
|
|
27012
|
+
const statusLabel = run.status === "cancelled" ? formatCancelledStatus(reason) : run.status === "cancelling" && attemptId.length > 0 && handoffReason.length > 0 ? `cancelling (attempt ${attemptId}, ${handoffReason})` : run.status;
|
|
26994
27013
|
return `run ${run.runId}: ${statusLabel} (workflow ${run.workflowId}, updated ${run.updatedAt})`;
|
|
26995
27014
|
}
|
|
26996
27015
|
async function cmdKxmRunStatus(runtime, runId) {
|
|
@@ -36612,19 +36631,90 @@ async function cmdPluginInstall(runtime, options) {
|
|
|
36612
36631
|
return ok ? 0 : 1;
|
|
36613
36632
|
}
|
|
36614
36633
|
|
|
36634
|
+
// plugins/kxm/src/cli/docs.ts
|
|
36635
|
+
init_project_config();
|
|
36636
|
+
init_types();
|
|
36637
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
36638
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
36639
|
+
import { join as join35 } from "node:path";
|
|
36640
|
+
var GENERATOR = "plans/kxm-roadmap/update-dashboard.mjs";
|
|
36641
|
+
var SERVER = "ops/docs-site/serve.py";
|
|
36642
|
+
function requireProject(runtime, command) {
|
|
36643
|
+
const root = discoverKxmProjectRoot(runtime.cwd);
|
|
36644
|
+
if (!root) {
|
|
36645
|
+
print(
|
|
36646
|
+
runtime.io,
|
|
36647
|
+
runtime.json,
|
|
36648
|
+
{ ok: false, command, error: "project_required" },
|
|
36649
|
+
`kxm ${command} requires a KXM project (run kxm init first)`
|
|
36650
|
+
);
|
|
36651
|
+
return 1;
|
|
36652
|
+
}
|
|
36653
|
+
return root;
|
|
36654
|
+
}
|
|
36655
|
+
function requireFile(runtime, command, root, relative8, error) {
|
|
36656
|
+
const file = join35(root, relative8);
|
|
36657
|
+
if (existsSync29(file)) return file;
|
|
36658
|
+
print(
|
|
36659
|
+
runtime.io,
|
|
36660
|
+
runtime.json,
|
|
36661
|
+
{ ok: false, command, error, path: relative8 },
|
|
36662
|
+
`kxm ${command} requires ${relative8}`
|
|
36663
|
+
);
|
|
36664
|
+
return 1;
|
|
36665
|
+
}
|
|
36666
|
+
function printCommand(runtime, command, line) {
|
|
36667
|
+
print(
|
|
36668
|
+
runtime.io,
|
|
36669
|
+
runtime.json,
|
|
36670
|
+
{ ok: true, command, dryRun: true, detail: line },
|
|
36671
|
+
line
|
|
36672
|
+
);
|
|
36673
|
+
return 0;
|
|
36674
|
+
}
|
|
36675
|
+
function runInherited(command, args, cwd) {
|
|
36676
|
+
return new Promise((resolveExit) => {
|
|
36677
|
+
const child = spawn4(command, [...args], { cwd, stdio: "inherit" });
|
|
36678
|
+
child.once("error", () => resolveExit(1));
|
|
36679
|
+
child.once("exit", (code) => resolveExit(code ?? 1));
|
|
36680
|
+
});
|
|
36681
|
+
}
|
|
36682
|
+
async function cmdDocsBuild(runtime) {
|
|
36683
|
+
const command = "docs build";
|
|
36684
|
+
const root = requireProject(runtime, command);
|
|
36685
|
+
if (typeof root === "number") return root;
|
|
36686
|
+
const file = requireFile(runtime, command, root, GENERATOR, "docs_generator_missing");
|
|
36687
|
+
if (typeof file === "number") return file;
|
|
36688
|
+
const line = `node ${GENERATOR}`;
|
|
36689
|
+
if (runtime.dryRun) return printCommand(runtime, command, line);
|
|
36690
|
+
return runInherited(process.execPath, [file], root);
|
|
36691
|
+
}
|
|
36692
|
+
async function cmdDocsServe(runtime, options = {}) {
|
|
36693
|
+
const command = "docs serve";
|
|
36694
|
+
const root = requireProject(runtime, command);
|
|
36695
|
+
if (typeof root === "number") return root;
|
|
36696
|
+
const file = requireFile(runtime, command, root, SERVER, "docs_server_missing");
|
|
36697
|
+
if (typeof file === "number") return file;
|
|
36698
|
+
const args = [file];
|
|
36699
|
+
if (options.port !== void 0 && options.port !== "") args.push("--port", options.port);
|
|
36700
|
+
const line = ["python3", SERVER, ...args.slice(1)].join(" ");
|
|
36701
|
+
if (runtime.dryRun) return printCommand(runtime, command, line);
|
|
36702
|
+
return runInherited("python3", args, root);
|
|
36703
|
+
}
|
|
36704
|
+
|
|
36615
36705
|
// plugins/kxm/src/cli/lanes.ts
|
|
36616
36706
|
init_project_config();
|
|
36617
36707
|
init_runtime_supervisor();
|
|
36618
36708
|
init_types();
|
|
36619
36709
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
36620
|
-
import { chmodSync as chmodSync6, existsSync as
|
|
36621
|
-
import { basename as basename8, dirname as dirname18, join as
|
|
36710
|
+
import { chmodSync as chmodSync6, existsSync as existsSync30, mkdirSync as mkdirSync24, readFileSync as readFileSync29, writeFileSync as writeFileSync22 } from "node:fs";
|
|
36711
|
+
import { basename as basename8, dirname as dirname18, join as join36, resolve as resolve25 } from "node:path";
|
|
36622
36712
|
var LANE_SCHEMA = "kxm.lanes.v1";
|
|
36623
36713
|
var SHA_RE = /^[a-f0-9]{40,64}$/;
|
|
36624
36714
|
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
36715
|
var SETTLED_RUN = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
36626
36716
|
function lanesFile(runtime) {
|
|
36627
|
-
return
|
|
36717
|
+
return join36(runtime.dirs.state, "lanes.json");
|
|
36628
36718
|
}
|
|
36629
36719
|
function gitEnv() {
|
|
36630
36720
|
return Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith("GIT_")));
|
|
@@ -36672,7 +36762,7 @@ function isLaneFile(value) {
|
|
|
36672
36762
|
}
|
|
36673
36763
|
function loadLanes(runtime, command) {
|
|
36674
36764
|
const file = lanesFile(runtime);
|
|
36675
|
-
if (!
|
|
36765
|
+
if (!existsSync30(file)) return { schema: LANE_SCHEMA, lanes: {} };
|
|
36676
36766
|
try {
|
|
36677
36767
|
const parsed = JSON.parse(readFileSync29(file, "utf8"));
|
|
36678
36768
|
if (!isLaneFile(parsed)) return refuse(runtime, command, "lanes_unreadable", `lane record ${file} is malformed`);
|
|
@@ -36731,7 +36821,7 @@ function withLaneCwd(runtime, unit, command = "lane") {
|
|
|
36731
36821
|
const loaded = loadLanes(runtime, command);
|
|
36732
36822
|
if (typeof loaded === "number") return loaded;
|
|
36733
36823
|
const lane = loaded.lanes[unit];
|
|
36734
|
-
if (!lane || !
|
|
36824
|
+
if (!lane || !existsSync30(lane.path)) {
|
|
36735
36825
|
return refuse(runtime, command, "lane_missing", `lane ${unit} is not recorded or its worktree is absent`, { unit });
|
|
36736
36826
|
}
|
|
36737
36827
|
return {
|
|
@@ -36802,7 +36892,7 @@ function aheadBehind(path4, baseSha) {
|
|
|
36802
36892
|
return { behind: Number(match[1]), ahead: Number(match[2]) };
|
|
36803
36893
|
}
|
|
36804
36894
|
function laneView(unit, record) {
|
|
36805
|
-
const exists =
|
|
36895
|
+
const exists = existsSync30(record.path);
|
|
36806
36896
|
const counts = exists ? aheadBehind(record.path, record.baseSha) : { ahead: null, behind: null };
|
|
36807
36897
|
return {
|
|
36808
36898
|
unit,
|
|
@@ -36893,7 +36983,7 @@ async function cmdLaneCreate(runtime, unit, options = {}) {
|
|
|
36893
36983
|
const loaded = loadLanes(runtime, command);
|
|
36894
36984
|
if (typeof loaded === "number") return loaded;
|
|
36895
36985
|
const path4 = laneWorktreePath(root, unit);
|
|
36896
|
-
if (loaded.lanes[unit] ||
|
|
36986
|
+
if (loaded.lanes[unit] || existsSync30(path4) || branchExists(root, unit)) {
|
|
36897
36987
|
return refuse(runtime, command, "lane_exists", `lane ${unit} already exists`, { unit });
|
|
36898
36988
|
}
|
|
36899
36989
|
const baseSha = resolveBase(root, base);
|
|
@@ -36918,7 +37008,7 @@ async function cmdLaneCreate(runtime, unit, options = {}) {
|
|
|
36918
37008
|
return refuse(runtime, command, "lane_git_failed", `git worktree add failed: ${added.stderr.trim().slice(0, 300)}`, { unit });
|
|
36919
37009
|
}
|
|
36920
37010
|
const recordedPath = discoverKxmProjectRoot(path4) ?? path4;
|
|
36921
|
-
if (!
|
|
37011
|
+
if (!existsSync30(join36(recordedPath, ".kxm", "project.yaml"))) {
|
|
36922
37012
|
git2(root, ["worktree", "remove", "--force", path4]);
|
|
36923
37013
|
return refuse(runtime, command, "lane_not_project", `lane ${recordedPath} has no .kxm/project.yaml; the worktree was removed`, { unit, path: recordedPath });
|
|
36924
37014
|
}
|
|
@@ -36982,7 +37072,7 @@ async function cmdLaneDrop(runtime, unit, options = {}) {
|
|
|
36982
37072
|
if (!record) return refuse(runtime, command, "lane_missing", `lane ${unit} is not recorded`, { unit });
|
|
36983
37073
|
const force = options.force === true;
|
|
36984
37074
|
if (!force) {
|
|
36985
|
-
if (
|
|
37075
|
+
if (existsSync30(record.path)) {
|
|
36986
37076
|
const dirty = porcelainCount(record.path);
|
|
36987
37077
|
if (dirty === null) {
|
|
36988
37078
|
return refuse(runtime, command, "lane_git_failed", `lane ${unit} worktree status could not be read`, { unit });
|
|
@@ -37001,7 +37091,7 @@ async function cmdLaneDrop(runtime, unit, options = {}) {
|
|
|
37001
37091
|
], `drop lane ${unit}; branch ${record.branch} is not deleted`);
|
|
37002
37092
|
return 0;
|
|
37003
37093
|
}
|
|
37004
|
-
if (
|
|
37094
|
+
if (existsSync30(record.path)) {
|
|
37005
37095
|
const removed = git2(root, ["worktree", "remove", ...force ? ["--force"] : [], record.path]);
|
|
37006
37096
|
if (removed.status !== 0) {
|
|
37007
37097
|
return refuse(runtime, command, "lane_git_failed", `git worktree remove failed: ${removed.stderr.trim().slice(0, 300)}`, { unit });
|
|
@@ -37071,8 +37161,8 @@ async function cmdLaneRun(runtime, unit, options) {
|
|
|
37071
37161
|
init_project_config();
|
|
37072
37162
|
init_repo_root();
|
|
37073
37163
|
init_types();
|
|
37074
|
-
import { spawn as
|
|
37075
|
-
import { join as
|
|
37164
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
37165
|
+
import { join as join37 } from "node:path";
|
|
37076
37166
|
function childEnv() {
|
|
37077
37167
|
const env = {};
|
|
37078
37168
|
for (const [name, value] of Object.entries(process.env)) {
|
|
@@ -37091,7 +37181,7 @@ function cmdLand(runtime, options = {}) {
|
|
|
37091
37181
|
if (!root) {
|
|
37092
37182
|
return Promise.resolve(refuse2(runtime, "project_required", "land requires a KXM project (run kxm init first)"));
|
|
37093
37183
|
}
|
|
37094
|
-
const script =
|
|
37184
|
+
const script = join37(findKxmRepoRoot(import.meta.url), "scripts", "pr-land.mjs");
|
|
37095
37185
|
const args = [script];
|
|
37096
37186
|
if (options.pr) args.push("--pr", options.pr);
|
|
37097
37187
|
if (options.stage) args.push("--stage", options.stage);
|
|
@@ -37099,7 +37189,7 @@ function cmdLand(runtime, options = {}) {
|
|
|
37099
37189
|
if (runtime.json) args.push("--json");
|
|
37100
37190
|
if (runtime.dryRun) args.push("--dry-run");
|
|
37101
37191
|
return new Promise((resolveExit) => {
|
|
37102
|
-
const child =
|
|
37192
|
+
const child = spawn5(process.execPath, args, { cwd: root, env: childEnv(), windowsHide: true });
|
|
37103
37193
|
child.stdout.on("data", (chunk) => runtime.io.stdout(chunk.toString("utf8")));
|
|
37104
37194
|
child.stderr.on("data", (chunk) => runtime.io.stderr(chunk.toString("utf8")));
|
|
37105
37195
|
child.once("error", () => resolveExit(1));
|
|
@@ -37111,8 +37201,8 @@ function cmdLand(runtime, options = {}) {
|
|
|
37111
37201
|
init_project_config();
|
|
37112
37202
|
init_types();
|
|
37113
37203
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
37114
|
-
import { existsSync as
|
|
37115
|
-
import { join as
|
|
37204
|
+
import { existsSync as existsSync31 } from "node:fs";
|
|
37205
|
+
import { join as join38 } from "node:path";
|
|
37116
37206
|
var kxmAssignCliSeams = {};
|
|
37117
37207
|
var RUNNER_REL = "scripts/assignment-run.mjs";
|
|
37118
37208
|
function refuse3(runtime, command, error, text) {
|
|
@@ -37184,7 +37274,7 @@ async function cmdAssign(runtime, subcommand, args) {
|
|
|
37184
37274
|
const command = `assign ${subcommand}`;
|
|
37185
37275
|
const root = discoverKxmProjectRoot(runtime.cwd);
|
|
37186
37276
|
if (!root) return refuse3(runtime, command, "project_required", `${command} requires a KXM project (run kxm init first)`);
|
|
37187
|
-
if (!
|
|
37277
|
+
if (!existsSync31(join38(root, "scripts", "assignment-run.mjs"))) {
|
|
37188
37278
|
return refuse3(runtime, command, "assign_runner_missing", `${command} requires scripts/assignment-run.mjs in the project root`);
|
|
37189
37279
|
}
|
|
37190
37280
|
const argv = ["node", RUNNER_REL, ...runnerArgv(subcommand, args)];
|
|
@@ -37195,7 +37285,7 @@ async function cmdAssign(runtime, subcommand, args) {
|
|
|
37195
37285
|
`);
|
|
37196
37286
|
return 0;
|
|
37197
37287
|
}
|
|
37198
|
-
const
|
|
37288
|
+
const spawn6 = kxmAssignCliSeams.spawn ?? ((commandName, commandArgs, options) => {
|
|
37199
37289
|
const result2 = spawnSync7(commandName, commandArgs, {
|
|
37200
37290
|
cwd: options.cwd,
|
|
37201
37291
|
stdio: options.stdio,
|
|
@@ -37204,7 +37294,7 @@ async function cmdAssign(runtime, subcommand, args) {
|
|
|
37204
37294
|
});
|
|
37205
37295
|
return { status: result2.status, ...result2.error ? { error: result2.error } : {} };
|
|
37206
37296
|
});
|
|
37207
|
-
const result =
|
|
37297
|
+
const result = spawn6("node", argv.slice(1), { cwd: root, stdio: "inherit", env: runtime.env });
|
|
37208
37298
|
if (result.status === null) {
|
|
37209
37299
|
const detail = result.error?.message ?? "the assignment runner could not be started";
|
|
37210
37300
|
return refuse3(runtime, command, "assign_spawn_failed", detail);
|
|
@@ -37215,8 +37305,8 @@ async function cmdAssign(runtime, subcommand, args) {
|
|
|
37215
37305
|
// plugins/kxm/src/cli/hub.ts
|
|
37216
37306
|
init_redact();
|
|
37217
37307
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
37218
|
-
import { existsSync as
|
|
37219
|
-
import { join as
|
|
37308
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync28, readFileSync as readFileSync35, readdirSync as readdirSync12, rmSync as rmSync11, writeFileSync as writeFileSync25 } from "node:fs";
|
|
37309
|
+
import { join as join48, resolve as resolve28 } from "node:path";
|
|
37220
37310
|
init_hub_env();
|
|
37221
37311
|
init_envelope();
|
|
37222
37312
|
|
|
@@ -42914,7 +43004,7 @@ import * as path2 from "node:path";
|
|
|
42914
43004
|
|
|
42915
43005
|
// node_modules/@earendil-works/pi-tui/dist/native-module-path.js
|
|
42916
43006
|
import { createRequire as createRequire2 } from "node:module";
|
|
42917
|
-
import { dirname as dirname19, join as
|
|
43007
|
+
import { dirname as dirname19, join as join39 } from "node:path";
|
|
42918
43008
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
42919
43009
|
var moduleRequire = createRequire2(import.meta.url);
|
|
42920
43010
|
var TUI_PACKAGE_NAME = "@earendil-works/pi-tui";
|
|
@@ -42923,10 +43013,10 @@ function getNativeModuleCandidates(nativePath, options = {}) {
|
|
|
42923
43013
|
const candidates = [];
|
|
42924
43014
|
try {
|
|
42925
43015
|
const packageEntry = (options.resolvePackage ?? moduleRequire.resolve)(TUI_PACKAGE_NAME);
|
|
42926
|
-
candidates.push(
|
|
43016
|
+
candidates.push(join39(dirname19(packageEntry), "..", nativePath));
|
|
42927
43017
|
} catch {
|
|
42928
43018
|
}
|
|
42929
|
-
candidates.push(
|
|
43019
|
+
candidates.push(join39(moduleDir, "..", nativePath), join39(moduleDir, nativePath), join39(dirname19(options.execPath ?? process.execPath), nativePath));
|
|
42930
43020
|
return Array.from(new Set(candidates));
|
|
42931
43021
|
}
|
|
42932
43022
|
|
|
@@ -45657,7 +45747,7 @@ var MAX_RENDER_WRITE_CHARS = 1024 * 1024;
|
|
|
45657
45747
|
|
|
45658
45748
|
// plugins/kxm/src/tui.ts
|
|
45659
45749
|
import { mkdirSync as mkdirSync25 } from "node:fs";
|
|
45660
|
-
import { join as
|
|
45750
|
+
import { join as join43, resolve as resolve27, dirname as dirname20 } from "node:path";
|
|
45661
45751
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
45662
45752
|
|
|
45663
45753
|
// packages/core/tui/src/types/surface.ts
|
|
@@ -45801,9 +45891,9 @@ var SHARED_EFFECT_KINDS = Object.freeze([
|
|
|
45801
45891
|
// plugins/kxm/src/local-snapshot.ts
|
|
45802
45892
|
init_sqlite();
|
|
45803
45893
|
init_telemetry();
|
|
45804
|
-
import { existsSync as
|
|
45894
|
+
import { existsSync as existsSync32, readdirSync as readdirSync11, readFileSync as readFileSync30 } from "node:fs";
|
|
45805
45895
|
import { homedir as homedir6 } from "node:os";
|
|
45806
|
-
import { isAbsolute as isAbsolute9, join as
|
|
45896
|
+
import { isAbsolute as isAbsolute9, join as join42, resolve as resolve26 } from "node:path";
|
|
45807
45897
|
var DEFAULT_BUSY_TIMEOUT_MS = 5e3;
|
|
45808
45898
|
var RUNTIME_PROJECT_KEY = /^[A-Za-z0-9_-][A-Za-z0-9._-]*$/;
|
|
45809
45899
|
function processExists2(pid) {
|
|
@@ -45928,36 +46018,36 @@ function readOpenMessageMetadata(database, where = OPEN_MESSAGE_WHERE, params =
|
|
|
45928
46018
|
return messages;
|
|
45929
46019
|
}
|
|
45930
46020
|
function resolveKxmSnapshotPaths(cwd, env = process.env) {
|
|
45931
|
-
const stateDir = env.KXM_STATE_DIR?.trim() ||
|
|
46021
|
+
const stateDir = env.KXM_STATE_DIR?.trim() || join42(cwd, ".kxm", "state");
|
|
45932
46022
|
const configured = env.KXM_DATA_PATH?.trim();
|
|
45933
|
-
const dataPath = configured ? resolve26(cwd, configured) :
|
|
46023
|
+
const dataPath = configured ? resolve26(cwd, configured) : join42(stateDir, "kxm.db");
|
|
45934
46024
|
return { dataPath, stateDir };
|
|
45935
46025
|
}
|
|
45936
46026
|
function resolveKxmStateRoot(stateDir, options) {
|
|
45937
|
-
if (options?.kxmStateRoot &&
|
|
46027
|
+
if (options?.kxmStateRoot && existsSync32(options.kxmStateRoot)) {
|
|
45938
46028
|
return resolve26(options.kxmStateRoot);
|
|
45939
46029
|
}
|
|
45940
|
-
if (
|
|
46030
|
+
if (existsSync32(join42(stateDir, "runtime", "registry.db")) || existsSync32(join42(stateDir, "runtime", "projects"))) {
|
|
45941
46031
|
return stateDir;
|
|
45942
46032
|
}
|
|
45943
46033
|
const env = options?.env ?? process.env;
|
|
45944
46034
|
const explicit = env.KXM_STATE_HOME?.trim() || env.KXM_USER_STATE_DIR?.trim() || env.KXM_STATE_ROOT?.trim();
|
|
45945
|
-
if (explicit && isAbsolute9(explicit) &&
|
|
46035
|
+
if (explicit && isAbsolute9(explicit) && existsSync32(resolve26(explicit))) {
|
|
45946
46036
|
return resolve26(explicit);
|
|
45947
46037
|
}
|
|
45948
46038
|
let base;
|
|
45949
46039
|
if (process.platform === "win32") {
|
|
45950
46040
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
45951
|
-
base = localAppData && isAbsolute9(localAppData) ? localAppData :
|
|
46041
|
+
base = localAppData && isAbsolute9(localAppData) ? localAppData : join42(homedir6(), "AppData", "Local");
|
|
45952
46042
|
base = resolve26(base, "KXM");
|
|
45953
46043
|
} else if (process.platform === "darwin") {
|
|
45954
46044
|
base = resolve26(homedir6(), "Library", "Application Support", "KXM");
|
|
45955
46045
|
} else {
|
|
45956
46046
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
45957
|
-
base = xdgState && isAbsolute9(xdgState) ? xdgState :
|
|
46047
|
+
base = xdgState && isAbsolute9(xdgState) ? xdgState : join42(homedir6(), ".local", "state");
|
|
45958
46048
|
base = resolve26(base, "kxm");
|
|
45959
46049
|
}
|
|
45960
|
-
if (
|
|
46050
|
+
if (existsSync32(base)) return base;
|
|
45961
46051
|
return void 0;
|
|
45962
46052
|
}
|
|
45963
46053
|
function readRuntimeRuns(eventDb, projectId) {
|
|
@@ -45990,7 +46080,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
45990
46080
|
let legacyRuns = [];
|
|
45991
46081
|
let legacyRunTotal = 0;
|
|
45992
46082
|
let plans = [];
|
|
45993
|
-
if (
|
|
46083
|
+
if (existsSync32(dataPath)) {
|
|
45994
46084
|
hasLegacy = true;
|
|
45995
46085
|
const database = openReadOnlyDatabase(dataPath);
|
|
45996
46086
|
try {
|
|
@@ -46021,11 +46111,11 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
46021
46111
|
let kxmRunTotal = 0;
|
|
46022
46112
|
const kxmStateRoot = scope && !scope.runtimeProjectId ? void 0 : resolveKxmStateRoot(stateDir, options);
|
|
46023
46113
|
if (kxmStateRoot) {
|
|
46024
|
-
const runtimeDir =
|
|
46025
|
-
const registryDbPath =
|
|
46026
|
-
const projectsDir =
|
|
46114
|
+
const runtimeDir = join42(kxmStateRoot, "runtime");
|
|
46115
|
+
const registryDbPath = join42(runtimeDir, "registry.db");
|
|
46116
|
+
const projectsDir = join42(runtimeDir, "projects");
|
|
46027
46117
|
const projectKeys = /* @__PURE__ */ new Set();
|
|
46028
|
-
if (
|
|
46118
|
+
if (existsSync32(registryDbPath)) {
|
|
46029
46119
|
hasKxm = true;
|
|
46030
46120
|
try {
|
|
46031
46121
|
const regDb = openReadOnlyDatabase(registryDbPath);
|
|
@@ -46041,7 +46131,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
46041
46131
|
} catch {
|
|
46042
46132
|
}
|
|
46043
46133
|
}
|
|
46044
|
-
if (!scope &&
|
|
46134
|
+
if (!scope && existsSync32(projectsDir)) {
|
|
46045
46135
|
try {
|
|
46046
46136
|
for (const entry of readdirSync11(projectsDir, { withFileTypes: true })) {
|
|
46047
46137
|
if (entry.isDirectory()) {
|
|
@@ -46053,8 +46143,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
46053
46143
|
}
|
|
46054
46144
|
for (const key of projectKeys) {
|
|
46055
46145
|
if (scope && !RUNTIME_PROJECT_KEY.test(key)) continue;
|
|
46056
|
-
const eventDbPath =
|
|
46057
|
-
if (
|
|
46146
|
+
const eventDbPath = join42(projectsDir, key, "run-events.db");
|
|
46147
|
+
if (existsSync32(eventDbPath)) {
|
|
46058
46148
|
hasKxm = true;
|
|
46059
46149
|
try {
|
|
46060
46150
|
const eventDb = openReadOnlyDatabase(eventDbPath);
|
|
@@ -46072,10 +46162,10 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
46072
46162
|
}
|
|
46073
46163
|
}
|
|
46074
46164
|
const pids = [];
|
|
46075
|
-
if (
|
|
46165
|
+
if (existsSync32(stateDir)) {
|
|
46076
46166
|
for (const file of readdirSync11(stateDir).filter((name) => name.endsWith(".pid"))) {
|
|
46077
46167
|
try {
|
|
46078
|
-
const record = JSON.parse(readFileSync30(
|
|
46168
|
+
const record = JSON.parse(readFileSync30(join42(stateDir, file), "utf8"));
|
|
46079
46169
|
pids.push({
|
|
46080
46170
|
file,
|
|
46081
46171
|
...record.role ? { role: record.role } : {},
|
|
@@ -46114,8 +46204,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
46114
46204
|
} else {
|
|
46115
46205
|
source = "legacy";
|
|
46116
46206
|
}
|
|
46117
|
-
const telemetryFile =
|
|
46118
|
-
const spend =
|
|
46207
|
+
const telemetryFile = join42(stateDir, "telemetry.jsonl");
|
|
46208
|
+
const spend = existsSync32(telemetryFile) ? readRoutingRecords(telemetryFile) : [];
|
|
46119
46209
|
return {
|
|
46120
46210
|
source,
|
|
46121
46211
|
agents: agents.sort((a, b2) => Number(b2.online) - Number(a.online) || a.name.localeCompare(b2.name)),
|
|
@@ -46249,7 +46339,7 @@ function spawnDegradeWorktree(repoRoot, runId, options) {
|
|
|
46249
46339
|
const cleanRunId = runId.replace(/^run_/, "");
|
|
46250
46340
|
const desc = options?.description ? slugifyBranchPart(options.description, 30) : "degrade";
|
|
46251
46341
|
const branchName = `kxm/run-${cleanRunId}-${desc}`;
|
|
46252
|
-
const relativeWtPath =
|
|
46342
|
+
const relativeWtPath = join43(".kxm", "worktrees", `run-${cleanRunId}-${desc}`);
|
|
46253
46343
|
const absoluteWtPath = resolve27(repoRoot, relativeWtPath);
|
|
46254
46344
|
const jumpCommand = `cd "${absoluteWtPath}"`;
|
|
46255
46345
|
try {
|
|
@@ -47018,8 +47108,8 @@ async function runMeshTui(input) {
|
|
|
47018
47108
|
// plugins/kxm/src/session-work.ts
|
|
47019
47109
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
47020
47110
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
47021
|
-
import { existsSync as
|
|
47022
|
-
import { join as
|
|
47111
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync26, readFileSync as readFileSync31, renameSync as renameSync8, writeFileSync as writeFileSync23 } from "node:fs";
|
|
47112
|
+
import { join as join44 } from "node:path";
|
|
47023
47113
|
init_hub_binding();
|
|
47024
47114
|
init_telemetry();
|
|
47025
47115
|
var MAX_SESSION_BRIEF_TASKS = 5;
|
|
@@ -47178,9 +47268,9 @@ function buildSessionBrief(snapshot, current, hub, ship, updateLatest, cost, ses
|
|
|
47178
47268
|
};
|
|
47179
47269
|
}
|
|
47180
47270
|
function readCachedSessionBrief(stateDir) {
|
|
47181
|
-
const file =
|
|
47271
|
+
const file = join44(stateDir, "session-brief.json");
|
|
47182
47272
|
try {
|
|
47183
|
-
if (!
|
|
47273
|
+
if (!existsSync33(file)) return void 0;
|
|
47184
47274
|
const raw = readFileSync31(file, "utf8");
|
|
47185
47275
|
const parsed = JSON.parse(raw);
|
|
47186
47276
|
if (parsed && parsed.schema === "kxm.session-brief.v1" && typeof parsed.generatedAt === "string") {
|
|
@@ -47197,7 +47287,7 @@ function readCachedSessionBrief(stateDir) {
|
|
|
47197
47287
|
function writeCachedSessionBrief(stateDir, brief) {
|
|
47198
47288
|
try {
|
|
47199
47289
|
mkdirSync26(stateDir, { recursive: true, mode: 448 });
|
|
47200
|
-
const file =
|
|
47290
|
+
const file = join44(stateDir, "session-brief.json");
|
|
47201
47291
|
const tmp = `${file}.tmp.${randomUUID12().slice(0, 8)}`;
|
|
47202
47292
|
writeFileSync23(tmp, JSON.stringify(brief, null, 2), { encoding: "utf8", mode: 384 });
|
|
47203
47293
|
renameSync8(tmp, file);
|
|
@@ -47206,8 +47296,8 @@ function writeCachedSessionBrief(stateDir, brief) {
|
|
|
47206
47296
|
}
|
|
47207
47297
|
function estimateSessionCost(stateDir) {
|
|
47208
47298
|
try {
|
|
47209
|
-
const telemetryFile =
|
|
47210
|
-
if (!
|
|
47299
|
+
const telemetryFile = join44(stateDir, "telemetry.jsonl");
|
|
47300
|
+
if (!existsSync33(telemetryFile)) return void 0;
|
|
47211
47301
|
const records = readRoutingRecords(telemetryFile);
|
|
47212
47302
|
if (records.length === 0) return void 0;
|
|
47213
47303
|
let totalCost = 0;
|
|
@@ -47379,11 +47469,11 @@ init_hub_binding();
|
|
|
47379
47469
|
|
|
47380
47470
|
// plugins/kxm/src/kxm-install-kind.ts
|
|
47381
47471
|
init_bindings();
|
|
47382
|
-
import { existsSync as
|
|
47383
|
-
import { dirname as dirname21, join as
|
|
47472
|
+
import { existsSync as existsSync34, readFileSync as readFileSync32 } from "node:fs";
|
|
47473
|
+
import { dirname as dirname21, join as join45 } from "node:path";
|
|
47384
47474
|
function packageIsKxm(root) {
|
|
47385
47475
|
try {
|
|
47386
|
-
const pkg = JSON.parse(readFileSync32(
|
|
47476
|
+
const pkg = JSON.parse(readFileSync32(join45(root, "package.json"), "utf8"));
|
|
47387
47477
|
return pkg.name === "@kontextmind/kxm";
|
|
47388
47478
|
} catch {
|
|
47389
47479
|
return false;
|
|
@@ -47432,12 +47522,12 @@ function report(kind, root) {
|
|
|
47432
47522
|
return { kind, root, instruction: installKindInstruction(kind, root) };
|
|
47433
47523
|
}
|
|
47434
47524
|
function classifyInstallRoot(probe) {
|
|
47435
|
-
const piGitRoot =
|
|
47525
|
+
const piGitRoot = join45(probe.homeDir, ".pi", "agent", "git");
|
|
47436
47526
|
if (isUnder(probe.repoRoot, piGitRoot, probe.platform)) return report("pi-git", probe.repoRoot);
|
|
47437
|
-
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() ||
|
|
47438
|
-
const pluginsRoot =
|
|
47527
|
+
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() || join45(probe.homeDir, ".claude");
|
|
47528
|
+
const pluginsRoot = join45(claudeHome, "plugins");
|
|
47439
47529
|
if (isUnder(probe.moduleDir, pluginsRoot, probe.platform)) return report("claude-marketplace", probe.moduleDir);
|
|
47440
|
-
const hasGit =
|
|
47530
|
+
const hasGit = existsSync34(join45(probe.repoRoot, ".git"));
|
|
47441
47531
|
if (hasGit && packageIsKxm(probe.repoRoot)) return report("source", probe.repoRoot);
|
|
47442
47532
|
if (isNpmPackageLayout(probe.repoRoot, probe.platform) && packageIsKxm(probe.repoRoot) && !hasGit) {
|
|
47443
47533
|
return report("npm-package", probe.repoRoot);
|
|
@@ -47461,12 +47551,12 @@ init_bindings();
|
|
|
47461
47551
|
|
|
47462
47552
|
// plugins/kxm/src/kxm-update-config.ts
|
|
47463
47553
|
var import_yaml16 = __toESM(require_dist(), 1);
|
|
47464
|
-
import { existsSync as
|
|
47465
|
-
import { join as
|
|
47554
|
+
import { existsSync as existsSync35, readFileSync as readFileSync33 } from "node:fs";
|
|
47555
|
+
import { join as join46 } from "node:path";
|
|
47466
47556
|
init_bindings();
|
|
47467
47557
|
function loadKxmUpdateConfig(env = process.env) {
|
|
47468
|
-
const path4 =
|
|
47469
|
-
if (!
|
|
47558
|
+
const path4 = join46(kxmUserStateRoot({ env }), "update.yaml");
|
|
47559
|
+
if (!existsSync35(path4)) return { schema: KXM_UPDATE_SCHEMA, auto: false, source: "github" };
|
|
47470
47560
|
let parsed;
|
|
47471
47561
|
try {
|
|
47472
47562
|
parsed = (0, import_yaml16.parse)(readFileSync33(path4, "utf8"));
|
|
@@ -47497,8 +47587,8 @@ function loadKxmUpdateConfig(env = process.env) {
|
|
|
47497
47587
|
// plugins/kxm/src/session.ts
|
|
47498
47588
|
init_protocol();
|
|
47499
47589
|
init_envelope();
|
|
47500
|
-
import { existsSync as
|
|
47501
|
-
import { join as
|
|
47590
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync27, readFileSync as readFileSync34, writeFileSync as writeFileSync24 } from "node:fs";
|
|
47591
|
+
import { join as join47 } from "node:path";
|
|
47502
47592
|
var SESSION_SCHEMA = "kxm.session.v1";
|
|
47503
47593
|
var SessionConfigError = class extends Error {
|
|
47504
47594
|
code = "session_config_invalid";
|
|
@@ -47508,12 +47598,12 @@ var SessionConfigError = class extends Error {
|
|
|
47508
47598
|
}
|
|
47509
47599
|
};
|
|
47510
47600
|
function workflowAssetDirs(assetsDir, workflowId) {
|
|
47511
|
-
const root =
|
|
47512
|
-
return [root,
|
|
47601
|
+
const root = join47(assetsDir, "workflows", workflowId);
|
|
47602
|
+
return [root, join47(root, "inputs"), join47(root, "outputs"), join47(root, "generated")];
|
|
47513
47603
|
}
|
|
47514
47604
|
function sessionAssetDirs(assetsDir, sessionId) {
|
|
47515
|
-
const root =
|
|
47516
|
-
return [root,
|
|
47605
|
+
const root = join47(assetsDir, "sessions", sessionId);
|
|
47606
|
+
return [root, join47(root, "inputs"), join47(root, "outputs")];
|
|
47517
47607
|
}
|
|
47518
47608
|
function rosterNames(configDir) {
|
|
47519
47609
|
return [...loadRosterMap(configDir).values()].map((row) => String(row.name));
|
|
@@ -47563,7 +47653,7 @@ function workerFromRosterRow(name, row, project) {
|
|
|
47563
47653
|
function loadRosterMap(configDir) {
|
|
47564
47654
|
const byName = /* @__PURE__ */ new Map();
|
|
47565
47655
|
for (const [file, key] of [["agents.json", "agents"], ["gates.json", "gates"]]) {
|
|
47566
|
-
const path4 =
|
|
47656
|
+
const path4 = join47(configDir, file);
|
|
47567
47657
|
for (const row of loadRoster(path4, key)) {
|
|
47568
47658
|
const name = String(row.name).trim();
|
|
47569
47659
|
const lowered = name.toLowerCase();
|
|
@@ -47577,7 +47667,7 @@ function loadRosterMap(configDir) {
|
|
|
47577
47667
|
return byName;
|
|
47578
47668
|
}
|
|
47579
47669
|
function loadRoster(path4, key) {
|
|
47580
|
-
if (!
|
|
47670
|
+
if (!existsSync36(path4)) return [];
|
|
47581
47671
|
let parsed;
|
|
47582
47672
|
try {
|
|
47583
47673
|
parsed = JSON.parse(readFileSync34(path4, "utf8"));
|
|
@@ -47605,7 +47695,7 @@ function loadRoster(path4, key) {
|
|
|
47605
47695
|
});
|
|
47606
47696
|
}
|
|
47607
47697
|
function createSession(input) {
|
|
47608
|
-
const assetDir = input.mode === "workflow" && input.workflowId ?
|
|
47698
|
+
const assetDir = input.mode === "workflow" && input.workflowId ? join47("assets", "workflows", input.workflowId) : join47("assets", "sessions", input.id);
|
|
47609
47699
|
return {
|
|
47610
47700
|
schema: SESSION_SCHEMA,
|
|
47611
47701
|
id: input.id,
|
|
@@ -47618,8 +47708,8 @@ function createSession(input) {
|
|
|
47618
47708
|
};
|
|
47619
47709
|
}
|
|
47620
47710
|
function writeSession(assetsDir, session, dryRun = false) {
|
|
47621
|
-
const dir =
|
|
47622
|
-
const path4 =
|
|
47711
|
+
const dir = join47(assetsDir, "sessions", session.id);
|
|
47712
|
+
const path4 = join47(dir, "session.json");
|
|
47623
47713
|
if (!dryRun) {
|
|
47624
47714
|
mkdirSync27(dir, { recursive: true });
|
|
47625
47715
|
writeFileSync24(path4, `${JSON.stringify(session, null, 2)}
|
|
@@ -47675,9 +47765,9 @@ function moduleInstallRoot() {
|
|
|
47675
47765
|
}
|
|
47676
47766
|
}
|
|
47677
47767
|
function warnIgnoredProjectUpdateYaml(runtime) {
|
|
47678
|
-
const projectFile =
|
|
47679
|
-
if (!
|
|
47680
|
-
const userFile =
|
|
47768
|
+
const projectFile = join48(runtime.dirs.workspace, "update.yaml");
|
|
47769
|
+
if (!existsSync37(projectFile)) return;
|
|
47770
|
+
const userFile = join48(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
47681
47771
|
runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}
|
|
47682
47772
|
`);
|
|
47683
47773
|
}
|
|
@@ -47725,7 +47815,7 @@ async function cmdDash(runtime, options = {}) {
|
|
|
47725
47815
|
return 2;
|
|
47726
47816
|
}
|
|
47727
47817
|
const screen = requested;
|
|
47728
|
-
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
47818
|
+
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join48(runtime.dirs.state, "kxm.db"));
|
|
47729
47819
|
if (runtime.dryRun) {
|
|
47730
47820
|
print(runtime.io, runtime.json, {
|
|
47731
47821
|
ok: true,
|
|
@@ -47771,7 +47861,7 @@ async function cmdHub(runtime) {
|
|
|
47771
47861
|
config = loadKxmUpdateConfig(runtime.env);
|
|
47772
47862
|
} catch (error) {
|
|
47773
47863
|
if (error instanceof KxmUpdateConfigError) {
|
|
47774
|
-
const yamlPath =
|
|
47864
|
+
const yamlPath = join48(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
47775
47865
|
runtime.io.stderr(`kxm: ${error.message}; update check skipped; fix or remove ${yamlPath}
|
|
47776
47866
|
`);
|
|
47777
47867
|
} else {
|
|
@@ -47958,7 +48048,7 @@ async function cmdWorker(runtime, options) {
|
|
|
47958
48048
|
return await (runtime.io.spawnWorker ?? ((launchEnv) => spawnScript("kxm-worker.mjs", launchEnv)))(extraEnv);
|
|
47959
48049
|
}
|
|
47960
48050
|
async function cmdStop(runtime, waitMsFlag) {
|
|
47961
|
-
const pids =
|
|
48051
|
+
const pids = existsSync37(runtime.dirs.state) ? readdirSync12(runtime.dirs.state).filter((name) => name.endsWith(".pid")) : [];
|
|
47962
48052
|
if (runtime.dryRun) {
|
|
47963
48053
|
print(runtime.io, runtime.json, { ok: true, command: "stop", dryRun: true, pidFiles: pids }, "would signal pid files");
|
|
47964
48054
|
return 0;
|
|
@@ -47973,7 +48063,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47973
48063
|
const orphans = [];
|
|
47974
48064
|
for (const file of pids) {
|
|
47975
48065
|
try {
|
|
47976
|
-
const record = JSON.parse(readFileSync35(
|
|
48066
|
+
const record = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
|
|
47977
48067
|
const expectedControl = file === "hub.pid" ? "hub.stop" : file.startsWith("worker-") ? `${file.slice(0, -4)}.stop` : void 0;
|
|
47978
48068
|
const expectedRole = file === "hub.pid" ? "hub" : file.startsWith("worker-") ? "worker" : void 0;
|
|
47979
48069
|
if (record.version !== 1 || !Number.isInteger(record.pid) || record.pid <= 0 || !record.startedAt || !expectedControl || record.controlFile !== expectedControl || record.role !== expectedRole) {
|
|
@@ -47993,7 +48083,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47993
48083
|
ignored.push(file);
|
|
47994
48084
|
continue;
|
|
47995
48085
|
}
|
|
47996
|
-
writeFileSync25(
|
|
48086
|
+
writeFileSync25(join48(runtime.dirs.state, record.controlFile), `${JSON.stringify({ startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {}, requestedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
47997
48087
|
`, { encoding: "utf8", mode: 384 });
|
|
47998
48088
|
requested.push(file);
|
|
47999
48089
|
records.set(file, { pid: record.pid, startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {} });
|
|
@@ -48011,7 +48101,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
48011
48101
|
while (Date.now() <= deadline && stopped.size < requested.length) {
|
|
48012
48102
|
for (const [file, record] of records) {
|
|
48013
48103
|
try {
|
|
48014
|
-
const current = JSON.parse(readFileSync35(
|
|
48104
|
+
const current = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
|
|
48015
48105
|
if (current.pid !== record.pid || current.startedAt !== record.startedAt || current.generation !== record.generation || !processExists(record.pid)) stopped.add(file);
|
|
48016
48106
|
} catch {
|
|
48017
48107
|
stopped.add(file);
|
|
@@ -48024,7 +48114,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
48024
48114
|
for (const file of orphans) {
|
|
48025
48115
|
while (Date.now() <= deadlineOrphans) {
|
|
48026
48116
|
try {
|
|
48027
|
-
const current = JSON.parse(readFileSync35(
|
|
48117
|
+
const current = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
|
|
48028
48118
|
if (!Number.isInteger(current.serverPid) || !processExists(current.serverPid)) break;
|
|
48029
48119
|
} catch {
|
|
48030
48120
|
break;
|
|
@@ -48032,14 +48122,14 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
48032
48122
|
await (runtime.io.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))))(100);
|
|
48033
48123
|
}
|
|
48034
48124
|
try {
|
|
48035
|
-
const current = JSON.parse(readFileSync35(
|
|
48125
|
+
const current = JSON.parse(readFileSync35(join48(runtime.dirs.state, file), "utf8"));
|
|
48036
48126
|
if (Number.isInteger(current.serverPid) && processExists(current.serverPid)) {
|
|
48037
48127
|
try {
|
|
48038
48128
|
process.kill(current.serverPid, "SIGKILL");
|
|
48039
48129
|
} catch {
|
|
48040
48130
|
}
|
|
48041
48131
|
}
|
|
48042
|
-
rmSync11(
|
|
48132
|
+
rmSync11(join48(runtime.dirs.state, file), { force: true });
|
|
48043
48133
|
} catch {
|
|
48044
48134
|
}
|
|
48045
48135
|
stopped.add(file);
|
|
@@ -48050,11 +48140,11 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
48050
48140
|
}
|
|
48051
48141
|
async function cmdSessionStatus(runtime) {
|
|
48052
48142
|
const stateDir = runtime.dirs.state;
|
|
48053
|
-
const names3 =
|
|
48143
|
+
const names3 = existsSync37(stateDir) ? readdirSync12(stateDir) : [];
|
|
48054
48144
|
const claims = [];
|
|
48055
48145
|
for (const file of names3.filter((name) => name.endsWith(".pid"))) {
|
|
48056
48146
|
try {
|
|
48057
|
-
const record = JSON.parse(readFileSync35(
|
|
48147
|
+
const record = JSON.parse(readFileSync35(join48(stateDir, file), "utf8"));
|
|
48058
48148
|
claims.push({
|
|
48059
48149
|
file,
|
|
48060
48150
|
role: record.role,
|
|
@@ -48069,7 +48159,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
48069
48159
|
const recoveries = [];
|
|
48070
48160
|
for (const file of names3.filter((name) => name.startsWith("worker-recovery-") && name.endsWith(".json"))) {
|
|
48071
48161
|
try {
|
|
48072
|
-
const envelope = JSON.parse(readFileSync35(
|
|
48162
|
+
const envelope = JSON.parse(readFileSync35(join48(stateDir, file), "utf8"));
|
|
48073
48163
|
recoveries.push({
|
|
48074
48164
|
file,
|
|
48075
48165
|
reason: envelope.reason,
|
|
@@ -48095,7 +48185,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
48095
48185
|
async function cmdAuthToken(runtime, options = {}) {
|
|
48096
48186
|
const tokenFile = sessionTokenPath(runtime.env.KXM_USER_CONFIG_DIR);
|
|
48097
48187
|
if (options.clear && runtime.dryRun) {
|
|
48098
|
-
const present =
|
|
48188
|
+
const present = existsSync37(tokenFile);
|
|
48099
48189
|
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");
|
|
48100
48190
|
return 0;
|
|
48101
48191
|
}
|
|
@@ -48184,7 +48274,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
48184
48274
|
print(runtime.io, runtime.json, { ok: true, command: "session brief", sessionToken }, sessionToken);
|
|
48185
48275
|
return 0;
|
|
48186
48276
|
}
|
|
48187
|
-
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
48277
|
+
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join48(runtime.dirs.state, "kxm.db"));
|
|
48188
48278
|
const env = {
|
|
48189
48279
|
...runtime.env,
|
|
48190
48280
|
KXM_STATE_DIR: runtime.dirs.state,
|
|
@@ -48210,7 +48300,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
48210
48300
|
writeCache: !runtime.dryRun
|
|
48211
48301
|
});
|
|
48212
48302
|
if (runtime.dryRun) {
|
|
48213
|
-
if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target:
|
|
48303
|
+
if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target: join48(runtime.dirs.state, "session-brief.json") });
|
|
48214
48304
|
print(runtime.io, runtime.json, { ...brief, dryRun: true, planned }, [
|
|
48215
48305
|
options.status ? brief.statusLine : formatSessionBriefText(brief),
|
|
48216
48306
|
...planned.map((change) => `dry run: would ${change.action} ${change.target}`)
|
|
@@ -48294,9 +48384,9 @@ init_routing();
|
|
|
48294
48384
|
init_prices();
|
|
48295
48385
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
48296
48386
|
import { createHash as createHash17 } from "node:crypto";
|
|
48297
|
-
import { existsSync as
|
|
48387
|
+
import { existsSync as existsSync44, mkdtempSync as mkdtempSync3, readFileSync as readFileSync40, rmSync as rmSync13 } from "node:fs";
|
|
48298
48388
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
48299
|
-
import { basename as basename11, extname as extname3, join as
|
|
48389
|
+
import { basename as basename11, extname as extname3, join as join54, resolve as resolve33 } from "node:path";
|
|
48300
48390
|
import { createInterface as createInterface3 } from "node:readline";
|
|
48301
48391
|
|
|
48302
48392
|
// plugins/kxm/src/improve.ts
|
|
@@ -48304,8 +48394,8 @@ init_routing();
|
|
|
48304
48394
|
init_protocol();
|
|
48305
48395
|
init_relevance();
|
|
48306
48396
|
import { createHash as createHash16 } from "node:crypto";
|
|
48307
|
-
import { existsSync as
|
|
48308
|
-
import { join as
|
|
48397
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync29, writeFileSync as writeFileSync26 } from "node:fs";
|
|
48398
|
+
import { join as join49, relative as relative7, resolve as resolve29 } from "node:path";
|
|
48309
48399
|
var CANDIDATE_SCHEMA = "kxm.candidate.v1";
|
|
48310
48400
|
var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
|
|
48311
48401
|
function classifyCandidateKind(stepId, agentRole) {
|
|
@@ -48561,7 +48651,7 @@ function groupRoutingRecords(records, options = {}) {
|
|
|
48561
48651
|
}
|
|
48562
48652
|
function buildImprovementReport(records, options = {}) {
|
|
48563
48653
|
const projectRoot = options.projectRoot ? resolve29(options.projectRoot) : process.cwd();
|
|
48564
|
-
const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) :
|
|
48654
|
+
const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) : join49(projectRoot, ".kxm", "candidates");
|
|
48565
48655
|
const promotionPolicy = options.promotionPolicy ?? "manual_pr";
|
|
48566
48656
|
const groups = groupRoutingRecords(records, options);
|
|
48567
48657
|
const candidates = [];
|
|
@@ -48575,7 +48665,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
48575
48665
|
group.workflowId
|
|
48576
48666
|
);
|
|
48577
48667
|
const diffFileName = `${group.candidateId}.diff`;
|
|
48578
|
-
const diffFilePath =
|
|
48668
|
+
const diffFilePath = join49(candidatesDir, diffFileName);
|
|
48579
48669
|
const relDiffPath = relative7(projectRoot, diffFilePath).replace(/\\/g, "/");
|
|
48580
48670
|
const candidate = {
|
|
48581
48671
|
schema: CANDIDATE_SCHEMA,
|
|
@@ -48597,11 +48687,11 @@ function buildImprovementReport(records, options = {}) {
|
|
|
48597
48687
|
createdAt: nowIso()
|
|
48598
48688
|
};
|
|
48599
48689
|
if (!options.dryRun) {
|
|
48600
|
-
if (!
|
|
48690
|
+
if (!existsSync38(candidatesDir)) {
|
|
48601
48691
|
mkdirSync29(candidatesDir, { recursive: true });
|
|
48602
48692
|
}
|
|
48603
48693
|
writeFileSync26(diffFilePath, diff, "utf8");
|
|
48604
|
-
const jsonFilePath =
|
|
48694
|
+
const jsonFilePath = join49(candidatesDir, `${group.candidateId}.json`);
|
|
48605
48695
|
writeFileSync26(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
|
|
48606
48696
|
}
|
|
48607
48697
|
candidates.push(candidate);
|
|
@@ -48630,7 +48720,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
48630
48720
|
}
|
|
48631
48721
|
function writeImprovementReport(improvementsDir, report2, dryRun = false) {
|
|
48632
48722
|
const stamp = report2.createdAt.replace(/[:.]/g, "-");
|
|
48633
|
-
const path4 =
|
|
48723
|
+
const path4 = join49(improvementsDir, `${stamp}.json`);
|
|
48634
48724
|
if (!dryRun) {
|
|
48635
48725
|
mkdirSync29(improvementsDir, { recursive: true });
|
|
48636
48726
|
writeFileSync26(path4, `${JSON.stringify(report2, null, 2)}
|
|
@@ -48714,7 +48804,7 @@ init_project_config();
|
|
|
48714
48804
|
init_runtime_store();
|
|
48715
48805
|
init_routing();
|
|
48716
48806
|
init_telemetry();
|
|
48717
|
-
import { existsSync as
|
|
48807
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
48718
48808
|
import { resolve as resolve30 } from "node:path";
|
|
48719
48809
|
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";
|
|
48720
48810
|
var SIMULATED_HARNESS = "driver-simulated";
|
|
@@ -48737,7 +48827,7 @@ function readEngineRoutingRecords(path4) {
|
|
|
48737
48827
|
undecided: 0,
|
|
48738
48828
|
duplicatesDropped: 0
|
|
48739
48829
|
};
|
|
48740
|
-
if (!
|
|
48830
|
+
if (!existsSync39(path4)) return { records: [], source };
|
|
48741
48831
|
source.exists = true;
|
|
48742
48832
|
let rows;
|
|
48743
48833
|
let database;
|
|
@@ -48813,7 +48903,7 @@ function readEngineRoutingRecords(path4) {
|
|
|
48813
48903
|
};
|
|
48814
48904
|
}
|
|
48815
48905
|
function readJsonlSource(kind, path4) {
|
|
48816
|
-
const exists =
|
|
48906
|
+
const exists = existsSync39(path4);
|
|
48817
48907
|
const records = exists ? readRoutingRecords(path4).map((entry) => entry.routing) : [];
|
|
48818
48908
|
return { records, source: { kind, path: path4, exists, records: records.length, duplicatesDropped: 0 } };
|
|
48819
48909
|
}
|
|
@@ -48858,8 +48948,8 @@ function loadRoutingSources(options) {
|
|
|
48858
48948
|
// plugins/kxm/src/modes.ts
|
|
48859
48949
|
var import_yaml17 = __toESM(require_dist(), 1);
|
|
48860
48950
|
init_prices();
|
|
48861
|
-
import { existsSync as
|
|
48862
|
-
import { join as
|
|
48951
|
+
import { existsSync as existsSync40, readFileSync as readFileSync37 } from "node:fs";
|
|
48952
|
+
import { join as join50 } from "node:path";
|
|
48863
48953
|
var DEFAULT_MODES_CONFIG = Object.freeze({
|
|
48864
48954
|
schema: "kxm.modes.v1",
|
|
48865
48955
|
majorModes: {
|
|
@@ -48922,8 +49012,8 @@ function loadModesConfig(projectRoot) {
|
|
|
48922
49012
|
if (!projectRoot) {
|
|
48923
49013
|
return DEFAULT_MODES_CONFIG;
|
|
48924
49014
|
}
|
|
48925
|
-
const modesPath =
|
|
48926
|
-
if (!
|
|
49015
|
+
const modesPath = join50(projectRoot, ".kxm", "modes.yaml");
|
|
49016
|
+
if (!existsSync40(modesPath)) {
|
|
48927
49017
|
return DEFAULT_MODES_CONFIG;
|
|
48928
49018
|
}
|
|
48929
49019
|
try {
|
|
@@ -49013,9 +49103,9 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
|
|
|
49013
49103
|
estimatedTokens: estimateTokens(baseSystemPromptChars)
|
|
49014
49104
|
});
|
|
49015
49105
|
for (const relPath of resolved.contextFiles) {
|
|
49016
|
-
const fullPath =
|
|
49106
|
+
const fullPath = join50(projectRoot, relPath);
|
|
49017
49107
|
let chars = 0;
|
|
49018
|
-
if (
|
|
49108
|
+
if (existsSync40(fullPath)) {
|
|
49019
49109
|
try {
|
|
49020
49110
|
chars = readFileSync37(fullPath, "utf8").length;
|
|
49021
49111
|
} catch {
|
|
@@ -49150,9 +49240,9 @@ ${divider}
|
|
|
49150
49240
|
// plugins/kxm/src/ssh-remote.ts
|
|
49151
49241
|
init_safety_integrity();
|
|
49152
49242
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
49153
|
-
import { existsSync as
|
|
49243
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync30, readFileSync as readFileSync38, readdirSync as readdirSync13, rmSync as rmSync12, statSync as statSync5 } from "node:fs";
|
|
49154
49244
|
import { homedir as homedir8 } from "node:os";
|
|
49155
|
-
import { join as
|
|
49245
|
+
import { join as join51, resolve as resolve31 } from "node:path";
|
|
49156
49246
|
var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
|
|
49157
49247
|
var MAX_SSH_OUTPUT_LINES = 2e3;
|
|
49158
49248
|
var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
|
|
@@ -49178,8 +49268,8 @@ function truncateSshOutput(raw) {
|
|
|
49178
49268
|
return { text, truncated };
|
|
49179
49269
|
}
|
|
49180
49270
|
function parseSshConfig(configPath) {
|
|
49181
|
-
const targetPath = configPath ??
|
|
49182
|
-
if (!
|
|
49271
|
+
const targetPath = configPath ?? join51(homedir8(), ".ssh", "config");
|
|
49272
|
+
if (!existsSync41(targetPath)) {
|
|
49183
49273
|
return [];
|
|
49184
49274
|
}
|
|
49185
49275
|
try {
|
|
@@ -49261,14 +49351,14 @@ function resolveSshHostG(host, execFn = spawnSync10) {
|
|
|
49261
49351
|
}
|
|
49262
49352
|
function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
|
|
49263
49353
|
const resolved = resolve31(socketDir);
|
|
49264
|
-
if (!
|
|
49354
|
+
if (!existsSync41(resolved)) {
|
|
49265
49355
|
mkdirSync30(resolved, { recursive: true, mode: 448 });
|
|
49266
49356
|
}
|
|
49267
49357
|
return resolved;
|
|
49268
49358
|
}
|
|
49269
49359
|
function buildSshArgs(options) {
|
|
49270
49360
|
const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
|
|
49271
|
-
const controlPath =
|
|
49361
|
+
const controlPath = join51(socketDir, "%C");
|
|
49272
49362
|
const persist = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
|
|
49273
49363
|
const args = [
|
|
49274
49364
|
"-o",
|
|
@@ -49293,7 +49383,7 @@ function buildSshArgs(options) {
|
|
|
49293
49383
|
}
|
|
49294
49384
|
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync10) {
|
|
49295
49385
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
49296
|
-
const controlPath =
|
|
49386
|
+
const controlPath = join51(resolvedDir, "%C");
|
|
49297
49387
|
try {
|
|
49298
49388
|
const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
|
|
49299
49389
|
encoding: "utf-8"
|
|
@@ -49305,7 +49395,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
49305
49395
|
}
|
|
49306
49396
|
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync10) {
|
|
49307
49397
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
49308
|
-
const controlPath =
|
|
49398
|
+
const controlPath = join51(resolvedDir, "%C");
|
|
49309
49399
|
try {
|
|
49310
49400
|
const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
|
|
49311
49401
|
encoding: "utf-8"
|
|
@@ -49753,9 +49843,9 @@ complete -c kxm -n "__fish_seen_subcommand_from goal" -a "create list get"
|
|
|
49753
49843
|
}
|
|
49754
49844
|
|
|
49755
49845
|
// plugins/kxm/src/completion-install.ts
|
|
49756
|
-
import { existsSync as
|
|
49846
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync31, readFileSync as readFileSync39, writeFileSync as writeFileSync27 } from "node:fs";
|
|
49757
49847
|
import { homedir as homedir9 } from "node:os";
|
|
49758
|
-
import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as isAbsolute10, join as
|
|
49848
|
+
import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as isAbsolute10, join as join52, resolve as resolve32 } from "node:path";
|
|
49759
49849
|
var COMPLETION_MARKER = "# kxm completion";
|
|
49760
49850
|
var PATH_MARKER = "# kxm path";
|
|
49761
49851
|
function detectShell(env = process.env, platform = process.platform) {
|
|
@@ -49777,25 +49867,25 @@ function completionScriptPath(shell, options = {}) {
|
|
|
49777
49867
|
const env = options.env ?? process.env;
|
|
49778
49868
|
const explicit = options.configDir ?? env.KXM_USER_CONFIG_DIR?.trim();
|
|
49779
49869
|
const base = explicit && explicit.length > 0 ? resolve32(explicit) : resolve32(effectiveHome(options), ".config", "kxm");
|
|
49780
|
-
return
|
|
49870
|
+
return join52(base, "completions", `kxm.${shell}`);
|
|
49781
49871
|
}
|
|
49782
49872
|
function bashRcCandidate(options) {
|
|
49783
49873
|
const home = effectiveHome(options);
|
|
49784
|
-
const candidates = [
|
|
49785
|
-
const existing = candidates.find((candidate) =>
|
|
49874
|
+
const candidates = [join52(home, ".bashrc"), join52(home, ".bash_profile")];
|
|
49875
|
+
const existing = candidates.find((candidate) => existsSync42(candidate));
|
|
49786
49876
|
return existing ?? candidates[0];
|
|
49787
49877
|
}
|
|
49788
49878
|
function zshRcCandidate(options) {
|
|
49789
49879
|
const env = options.env ?? process.env;
|
|
49790
49880
|
const home = effectiveHome(options);
|
|
49791
|
-
if (env.ZDOTDIR?.trim()) return
|
|
49792
|
-
return
|
|
49881
|
+
if (env.ZDOTDIR?.trim()) return join52(resolve32(env.ZDOTDIR.trim()), ".zshrc");
|
|
49882
|
+
return join52(home, ".zshrc");
|
|
49793
49883
|
}
|
|
49794
49884
|
function fishCompletionTarget(shell, options) {
|
|
49795
49885
|
const env = options.env ?? process.env;
|
|
49796
49886
|
const home = effectiveHome(options);
|
|
49797
|
-
if (env.XDG_CONFIG_HOME?.trim()) return
|
|
49798
|
-
return
|
|
49887
|
+
if (env.XDG_CONFIG_HOME?.trim()) return join52(resolve32(env.XDG_CONFIG_HOME.trim()), "fish", "completions", "kxm.fish");
|
|
49888
|
+
return join52(home, ".config", "fish", "completions", "kxm.fish");
|
|
49799
49889
|
}
|
|
49800
49890
|
function completionRcTarget(shell, options = {}) {
|
|
49801
49891
|
if (shell === "fish") {
|
|
@@ -49827,13 +49917,13 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
49827
49917
|
const scriptPath = completionScriptPath(shell, options);
|
|
49828
49918
|
const { rcFile } = completionRcTarget(shell, options);
|
|
49829
49919
|
const script = generateShellCompletion(shell);
|
|
49830
|
-
const existingScript =
|
|
49920
|
+
const existingScript = existsSync42(scriptPath);
|
|
49831
49921
|
const existingScriptMatches = existingScript && readFileSync39(scriptPath, "utf8") === script;
|
|
49832
49922
|
let rcModified = false;
|
|
49833
49923
|
let alreadyInstalled = false;
|
|
49834
49924
|
if (shell === "fish") {
|
|
49835
49925
|
const fishTarget = fishCompletionTarget(shell, options);
|
|
49836
|
-
const fishInstalled =
|
|
49926
|
+
const fishInstalled = existsSync42(fishTarget) && readFileSync39(fishTarget, "utf8") === script;
|
|
49837
49927
|
alreadyInstalled = fishInstalled;
|
|
49838
49928
|
if (!options.dryRun && (!fishInstalled || options.overwrite)) {
|
|
49839
49929
|
mkdirSync31(resolve32(fishTarget, ".."), { recursive: true });
|
|
@@ -49850,7 +49940,7 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
49850
49940
|
}
|
|
49851
49941
|
if (rcFile) {
|
|
49852
49942
|
const line = sourceLine(shell, scriptPath);
|
|
49853
|
-
const rcContent =
|
|
49943
|
+
const rcContent = existsSync42(rcFile) ? readFileSync39(rcFile, "utf8") : "";
|
|
49854
49944
|
alreadyInstalled = rcContent.includes(line) || rcContent.includes(`${COMPLETION_MARKER}`);
|
|
49855
49945
|
}
|
|
49856
49946
|
if (!options.dryRun) {
|
|
@@ -49866,7 +49956,7 @@ ${marker}
|
|
|
49866
49956
|
${line}
|
|
49867
49957
|
`;
|
|
49868
49958
|
mkdirSync31(resolve32(rcFile, ".."), { recursive: true });
|
|
49869
|
-
writeFileSync27(rcFile, (
|
|
49959
|
+
writeFileSync27(rcFile, (existsSync42(rcFile) ? readFileSync39(rcFile, "utf8") : "") + stanza, { encoding: "utf8" });
|
|
49870
49960
|
rcModified = true;
|
|
49871
49961
|
}
|
|
49872
49962
|
}
|
|
@@ -49883,13 +49973,13 @@ function kxmBinDir(env = process.env) {
|
|
|
49883
49973
|
const argv1 = env.KXM_ENTRY ?? process.argv[1];
|
|
49884
49974
|
if (argv1 && isAbsolute10(argv1)) {
|
|
49885
49975
|
const dir = dirname24(argv1);
|
|
49886
|
-
if (
|
|
49976
|
+
if (existsSync42(join52(dir, process.platform === "win32" ? "kxm.cmd" : "kxm"))) return dir;
|
|
49887
49977
|
}
|
|
49888
49978
|
const pathEnv = env.PATH ?? "";
|
|
49889
49979
|
for (const part of pathEnv.split(delimiter)) {
|
|
49890
49980
|
if (!part) continue;
|
|
49891
49981
|
const candidate = resolve32(part, process.platform === "win32" ? "kxm.cmd" : "kxm");
|
|
49892
|
-
if (
|
|
49982
|
+
if (existsSync42(candidate)) return resolve32(part);
|
|
49893
49983
|
}
|
|
49894
49984
|
return void 0;
|
|
49895
49985
|
}
|
|
@@ -49907,7 +49997,7 @@ function installPathEntry(shellInput, options = {}) {
|
|
|
49907
49997
|
}
|
|
49908
49998
|
const { rcFile } = completionRcTarget(shell, options);
|
|
49909
49999
|
const line = pathLine(binDir);
|
|
49910
|
-
const rcContent =
|
|
50000
|
+
const rcContent = existsSync42(rcFile ?? "") ? readFileSync39(rcFile, "utf8") : "";
|
|
49911
50001
|
const alreadyInstalled = rcContent.includes(binDir) || (options.env?.PATH ?? process.env.PATH ?? "").split(delimiter).includes(binDir);
|
|
49912
50002
|
if (!options.dryRun && rcFile && !alreadyInstalled) {
|
|
49913
50003
|
mkdirSync31(dirname24(rcFile), { recursive: true });
|
|
@@ -49922,8 +50012,8 @@ ${line}
|
|
|
49922
50012
|
// plugins/kxm/src/init-guide-setup.ts
|
|
49923
50013
|
var import_yaml18 = __toESM(require_dist(), 1);
|
|
49924
50014
|
init_routes();
|
|
49925
|
-
import { existsSync as
|
|
49926
|
-
import { dirname as dirname25, join as
|
|
50015
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync32, writeFileSync as writeFileSync28 } from "node:fs";
|
|
50016
|
+
import { dirname as dirname25, join as join53 } from "node:path";
|
|
49927
50017
|
var ADMITTED_GUIDE_BINDINGS = Object.freeze({
|
|
49928
50018
|
"anthropic/claude-fable-5.1": { harness: "claude", provider: "anthropic", model: "fable" },
|
|
49929
50019
|
"anthropic/fable": { harness: "claude", provider: "anthropic", model: "fable" },
|
|
@@ -50314,13 +50404,13 @@ function renderGuideSetupFiles(projectRoot, plan) {
|
|
|
50314
50404
|
const stage = roleStages.get(role);
|
|
50315
50405
|
if (!stage) continue;
|
|
50316
50406
|
files.push({
|
|
50317
|
-
path:
|
|
50407
|
+
path: join53(projectRoot, ".kxm", "agents", `${role}.yaml`),
|
|
50318
50408
|
content: (0, import_yaml18.stringify)(agentDocument(role, stage, binding))
|
|
50319
50409
|
});
|
|
50320
50410
|
}
|
|
50321
50411
|
for (const workflow of plan.workflows) {
|
|
50322
50412
|
files.push({
|
|
50323
|
-
path:
|
|
50413
|
+
path: join53(projectRoot, ".kxm", "workflows", `${workflow.slug}.yaml`),
|
|
50324
50414
|
content: (0, import_yaml18.stringify)(workflowDocument(workflow))
|
|
50325
50415
|
});
|
|
50326
50416
|
}
|
|
@@ -50337,7 +50427,7 @@ function mergeGuideRouteAdmission(projectRoot, plan) {
|
|
|
50337
50427
|
}
|
|
50338
50428
|
if (added.length === 0) return added;
|
|
50339
50429
|
policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
50340
|
-
const path4 =
|
|
50430
|
+
const path4 = join53(projectRoot, ".kxm", "routes.yaml");
|
|
50341
50431
|
mkdirSync32(dirname25(path4), { recursive: true });
|
|
50342
50432
|
writeFileSync28(path4, (0, import_yaml18.stringify)(policy), "utf8");
|
|
50343
50433
|
return added;
|
|
@@ -50346,7 +50436,7 @@ function writeGuideSetupFiles(files) {
|
|
|
50346
50436
|
const written = [];
|
|
50347
50437
|
const existed = [];
|
|
50348
50438
|
for (const file of files) {
|
|
50349
|
-
if (
|
|
50439
|
+
if (existsSync43(file.path)) {
|
|
50350
50440
|
existed.push(file.path);
|
|
50351
50441
|
continue;
|
|
50352
50442
|
}
|
|
@@ -50417,7 +50507,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
50417
50507
|
detail: `release v${notice.latest} has no sha256 digest for ${name}; refusing to install`
|
|
50418
50508
|
};
|
|
50419
50509
|
}
|
|
50420
|
-
const releaseDir = mkdtempSync3(
|
|
50510
|
+
const releaseDir = mkdtempSync3(join54(tmpdir2(), "kxm-pkg-update-"));
|
|
50421
50511
|
try {
|
|
50422
50512
|
const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset);
|
|
50423
50513
|
if (runtime.dryRun) {
|
|
@@ -50426,7 +50516,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
50426
50516
|
for (const step of planned) {
|
|
50427
50517
|
if (step.kind === "verify") {
|
|
50428
50518
|
if (!verifyReleaseAssetDigest(step.path, step.sha256)) {
|
|
50429
|
-
const actual =
|
|
50519
|
+
const actual = existsSync44(step.path) ? createHash17("sha256").update(readFileSync40(step.path)).digest("hex") : "missing";
|
|
50430
50520
|
return {
|
|
50431
50521
|
ok: false,
|
|
50432
50522
|
error: "release_digest_mismatch",
|
|
@@ -50704,7 +50794,7 @@ async function cmdValidate(runtime, fileFlag) {
|
|
|
50704
50794
|
}
|
|
50705
50795
|
const selectedFile = explicitFile || configuredFile;
|
|
50706
50796
|
const file = selectedFile ? resolve33(runtime.cwd, selectedFile) : void 0;
|
|
50707
|
-
if (file && !
|
|
50797
|
+
if (file && !existsSync44(file)) {
|
|
50708
50798
|
printWorker(runtime, worker, { ok: false, command: "validate", error: "file_not_found", file }, `workflow file not found: ${file}`);
|
|
50709
50799
|
return 1;
|
|
50710
50800
|
}
|
|
@@ -50804,7 +50894,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
50804
50894
|
print(runtime.io, runtime.json, { ok: false, command: "improve", error: "config_invalid", detail: message }, `config_invalid: ${message}`);
|
|
50805
50895
|
return 1;
|
|
50806
50896
|
}
|
|
50807
|
-
const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) :
|
|
50897
|
+
const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) : join54(root, ".kxm", "candidates");
|
|
50808
50898
|
const report2 = buildImprovementReport(loaded.records, {
|
|
50809
50899
|
candidatesDir,
|
|
50810
50900
|
projectRoot: root,
|
|
@@ -50813,7 +50903,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
50813
50903
|
autoThreshold: config.improvement.autoThreshold,
|
|
50814
50904
|
halfLifeDays: config.improvement.telemetryHalfLifeDays
|
|
50815
50905
|
});
|
|
50816
|
-
const reportDir =
|
|
50906
|
+
const reportDir = join54(runtime.dirs.assets, "improvements");
|
|
50817
50907
|
const reportPath = writeImprovementReport(reportDir, report2, runtime.dryRun);
|
|
50818
50908
|
const text = [
|
|
50819
50909
|
"Sources:",
|
|
@@ -50957,7 +51047,7 @@ async function maybeOfferCompletionInstall(runtime) {
|
|
|
50957
51047
|
if (!pathNeeded) {
|
|
50958
51048
|
const scriptPath = completionScriptPath(shell, { env: runtime.env, configDir: runtime.env.KXM_USER_CONFIG_DIR });
|
|
50959
51049
|
const { rcFile } = completionRcTarget(shell, { env: runtime.env });
|
|
50960
|
-
if (rcFile &&
|
|
51050
|
+
if (rcFile && existsSync44(rcFile)) {
|
|
50961
51051
|
try {
|
|
50962
51052
|
if (readFileSync40(rcFile, "utf8").includes(scriptPath)) return;
|
|
50963
51053
|
} catch {
|
|
@@ -51122,7 +51212,7 @@ async function cmdRoutingReport(runtime, options) {
|
|
|
51122
51212
|
let catalog;
|
|
51123
51213
|
if (includeEquivalentListCost) {
|
|
51124
51214
|
try {
|
|
51125
|
-
const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) :
|
|
51215
|
+
const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) : join54(runtime.dirs.workspace, "prices.yaml");
|
|
51126
51216
|
catalog = loadPriceCatalog(pricesPath);
|
|
51127
51217
|
} catch {
|
|
51128
51218
|
}
|
|
@@ -51343,7 +51433,9 @@ var DRY_RUN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
51343
51433
|
"task run",
|
|
51344
51434
|
"task sync",
|
|
51345
51435
|
"studio layout",
|
|
51346
|
-
"studio serve"
|
|
51436
|
+
"studio serve",
|
|
51437
|
+
"docs build",
|
|
51438
|
+
"docs serve"
|
|
51347
51439
|
]);
|
|
51348
51440
|
var DryRunRefused = class extends Error {
|
|
51349
51441
|
code;
|
|
@@ -51623,6 +51715,14 @@ function createProgram(ctx, result) {
|
|
|
51623
51715
|
addGlobalOptions(runCmd.command("list").description("List recent runs for the current project")).action(async function runListAction() {
|
|
51624
51716
|
result.code = await cmdKxmRunList(runtimeFrom(ctx, this));
|
|
51625
51717
|
});
|
|
51718
|
+
const docsCmd = addGlobalOptions(program2.command("docs").description("Build and serve the tailnet docs site"));
|
|
51719
|
+
docsCmd.helpCommand("help", "Show docs help");
|
|
51720
|
+
addGlobalOptions(docsCmd.command("build").description("Regenerate the docs site from the roadmap state")).action(async function docsBuildAction() {
|
|
51721
|
+
result.code = await cmdDocsBuild(runtimeFrom(ctx, this));
|
|
51722
|
+
});
|
|
51723
|
+
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) {
|
|
51724
|
+
result.code = await cmdDocsServe(runtimeFrom(ctx, this), options);
|
|
51725
|
+
});
|
|
51626
51726
|
const tenantCmd = addGlobalOptions(program2.command("tenant").description("Composed tenant reads for machine clients (portal)"));
|
|
51627
51727
|
tenantCmd.helpCommand("help", "Show tenant help");
|
|
51628
51728
|
addGlobalOptions(tenantCmd.command("status").description("Read hub metadata and authoritative Runtime run state as one labeled view")).action(async function tenantStatusAction() {
|