@kontextmind/kxm 0.7.121 → 0.7.122
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/CHANGELOG.md +7 -0
- package/docs/contributing/assignment-runner.md +25 -22
- package/docs/guides/agent-skills.md +1 -1
- package/docs/reference/cli-reference.md +93 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +322 -169
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +1 -0
- package/plugins/kxm/skills/kxm-runs/SKILL.md +9 -1
- package/plugins/kxm/src/cli/assign.ts +144 -0
- package/plugins/kxm/src/cli.ts +71 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
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 join55 = objectValue(step.join);
|
|
18564
|
+
const minimumPassed = join55 && typeof join55.minimumPassed === "number" ? join55.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 join55 = 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: join55
|
|
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 join55 = objectValue2(step.join);
|
|
20945
|
+
if (!join55) return { strategy: "all" };
|
|
20946
|
+
const declared = stringValue2(join55.strategy);
|
|
20947
20947
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
20948
|
-
const minimumPassed = compileOptionalCount(
|
|
20948
|
+
const minimumPassed = compileOptionalCount(join55.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
20949
20949
|
const compiled = {
|
|
20950
20950
|
strategy,
|
|
20951
20951
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
20952
|
-
...typeof
|
|
20952
|
+
...typeof join55.cancelRemaining === "boolean" ? { cancelRemaining: join55.cancelRemaining } : {}
|
|
20953
20953
|
};
|
|
20954
20954
|
return compiled;
|
|
20955
20955
|
}
|
|
@@ -30324,10 +30324,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
30324
30324
|
* @param {string} flag
|
|
30325
30325
|
* @private
|
|
30326
30326
|
*/
|
|
30327
|
-
unknownOption(
|
|
30327
|
+
unknownOption(flag2) {
|
|
30328
30328
|
if (this._allowUnknownOption) return;
|
|
30329
30329
|
let suggestion = "";
|
|
30330
|
-
if (
|
|
30330
|
+
if (flag2.startsWith("--") && this._showSuggestionAfterError) {
|
|
30331
30331
|
let candidateFlags = [];
|
|
30332
30332
|
let command = this;
|
|
30333
30333
|
do {
|
|
@@ -30335,9 +30335,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
30335
30335
|
candidateFlags = candidateFlags.concat(moreFlags);
|
|
30336
30336
|
command = command.parent;
|
|
30337
30337
|
} while (command && !command._enablePositionalOptions);
|
|
30338
|
-
suggestion = suggestSimilar(
|
|
30338
|
+
suggestion = suggestSimilar(flag2, candidateFlags);
|
|
30339
30339
|
}
|
|
30340
|
-
const message = `error: unknown option '${
|
|
30340
|
+
const message = `error: unknown option '${flag2}'${suggestion}`;
|
|
30341
30341
|
this.error(message, { code: "commander.unknownOption" });
|
|
30342
30342
|
}
|
|
30343
30343
|
/**
|
|
@@ -34136,7 +34136,7 @@ async function cmdWorkflowDefinitions(runtime, options) {
|
|
|
34136
34136
|
}
|
|
34137
34137
|
async function cmdWorkflowAdd(runtime, workflowId, options) {
|
|
34138
34138
|
const scope = options.scope ?? "local";
|
|
34139
|
-
const
|
|
34139
|
+
const refuse4 = (error, message, code = 2) => {
|
|
34140
34140
|
print(runtime.io, runtime.json, { ok: false, command: "workflow add", error, message }, `workflow add failed: ${message}`);
|
|
34141
34141
|
return code;
|
|
34142
34142
|
};
|
|
@@ -34144,12 +34144,12 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
|
|
|
34144
34144
|
let content;
|
|
34145
34145
|
if (options.template !== void 0) {
|
|
34146
34146
|
if (options.file !== void 0 || options.pick !== void 0) {
|
|
34147
|
-
return
|
|
34147
|
+
return refuse4("workflow_add_conflict", "--template cannot be combined with --file or --pick");
|
|
34148
34148
|
}
|
|
34149
|
-
if (!workflowId) return
|
|
34149
|
+
if (!workflowId) return refuse4("workflow_id_required", "usage: kxm workflow add <workflowId> --template <name>");
|
|
34150
34150
|
const template = Object.hasOwn(WORKFLOW_TEMPLATES, options.template) ? WORKFLOW_TEMPLATES[options.template] : void 0;
|
|
34151
34151
|
if (!template) {
|
|
34152
|
-
return
|
|
34152
|
+
return refuse4("workflow_template_unknown", `unknown template ${options.template}; choose ${Object.keys(WORKFLOW_TEMPLATES).join(", ")}`);
|
|
34153
34153
|
}
|
|
34154
34154
|
content = { ...template, ...options.description !== void 0 ? { description: options.description } : {} };
|
|
34155
34155
|
} else if (!workflowId || options.pick) {
|
|
@@ -34169,7 +34169,7 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
|
|
|
34169
34169
|
}
|
|
34170
34170
|
const picked = await resolvePickItem(runtime.io, `Select a workflow template to add (${scope})`, candidates, options.pick, runtime.env);
|
|
34171
34171
|
if (!picked) {
|
|
34172
|
-
return
|
|
34172
|
+
return refuse4("workflow_id_required", "provide a workflowId or select an available workflow with --pick <id>", 1);
|
|
34173
34173
|
}
|
|
34174
34174
|
workflowId ??= picked.id;
|
|
34175
34175
|
if (options.file === void 0) {
|
|
@@ -34191,7 +34191,7 @@ async function cmdWorkflowAdd(runtime, workflowId, options) {
|
|
|
34191
34191
|
if (scope === "local") {
|
|
34192
34192
|
const projectRoot = discoverKxmProjectRoot(runtime.cwd);
|
|
34193
34193
|
if (!projectRoot) {
|
|
34194
|
-
return
|
|
34194
|
+
return refuse4("project_not_found", "local workflows belong to a KXM project; run kxm init at the repository root, or pass --scope global");
|
|
34195
34195
|
}
|
|
34196
34196
|
const issues = kxmWorkflowWriteIssues(projectRoot, workflowId, document);
|
|
34197
34197
|
if (issues.length > 0) {
|
|
@@ -34226,7 +34226,7 @@ ${issues.map((entry) => ` ${entry.file}: ${entry.code}: ${entry.message}`).join
|
|
|
34226
34226
|
);
|
|
34227
34227
|
return 0;
|
|
34228
34228
|
} catch (err) {
|
|
34229
|
-
return
|
|
34229
|
+
return refuse4("workflow_add_failed", err instanceof Error ? err.message : String(err), 1);
|
|
34230
34230
|
}
|
|
34231
34231
|
}
|
|
34232
34232
|
async function cmdWorkflowRemove(runtime, workflowId, options) {
|
|
@@ -37107,11 +37107,116 @@ function cmdLand(runtime, options = {}) {
|
|
|
37107
37107
|
});
|
|
37108
37108
|
}
|
|
37109
37109
|
|
|
37110
|
+
// plugins/kxm/src/cli/assign.ts
|
|
37111
|
+
init_project_config();
|
|
37112
|
+
init_types();
|
|
37113
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
37114
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
37115
|
+
import { join as join37 } from "node:path";
|
|
37116
|
+
var kxmAssignCliSeams = {};
|
|
37117
|
+
var RUNNER_REL = "scripts/assignment-run.mjs";
|
|
37118
|
+
function refuse3(runtime, command, error, text) {
|
|
37119
|
+
print(runtime.io, runtime.json, { ok: false, command, error }, text);
|
|
37120
|
+
return 1;
|
|
37121
|
+
}
|
|
37122
|
+
function flag(value) {
|
|
37123
|
+
if (value === void 0) throw new Error("assign invocation missing a parsed flag");
|
|
37124
|
+
return value;
|
|
37125
|
+
}
|
|
37126
|
+
function runnerArgv(subcommand, args) {
|
|
37127
|
+
switch (subcommand) {
|
|
37128
|
+
case "run":
|
|
37129
|
+
return ["run", "--manifest", flag(args.manifest)];
|
|
37130
|
+
case "witness":
|
|
37131
|
+
return ["witness", "--record-dir", flag(args.recordDir)];
|
|
37132
|
+
case "plan-current":
|
|
37133
|
+
return [
|
|
37134
|
+
"plan-current",
|
|
37135
|
+
"--task-dir",
|
|
37136
|
+
flag(args.taskDir),
|
|
37137
|
+
"--plan",
|
|
37138
|
+
flag(args.plan),
|
|
37139
|
+
"--sha256",
|
|
37140
|
+
flag(args.sha256),
|
|
37141
|
+
"--base-commit",
|
|
37142
|
+
flag(args.baseCommit),
|
|
37143
|
+
"--expected-generation",
|
|
37144
|
+
flag(args.expectedGeneration)
|
|
37145
|
+
];
|
|
37146
|
+
case "attribute":
|
|
37147
|
+
return [
|
|
37148
|
+
"attribute",
|
|
37149
|
+
"--task-dir",
|
|
37150
|
+
flag(args.taskDir),
|
|
37151
|
+
"--record-dir",
|
|
37152
|
+
flag(args.recordDir),
|
|
37153
|
+
"--class",
|
|
37154
|
+
flag(args.classification),
|
|
37155
|
+
"--explanation-file",
|
|
37156
|
+
flag(args.explanationFile)
|
|
37157
|
+
];
|
|
37158
|
+
case "observe-cost":
|
|
37159
|
+
return ["observe-cost", "--task-dir", flag(args.taskDir), "--input", flag(args.input)];
|
|
37160
|
+
case "accept": {
|
|
37161
|
+
const argv = [
|
|
37162
|
+
"accept",
|
|
37163
|
+
"--task-dir",
|
|
37164
|
+
flag(args.taskDir),
|
|
37165
|
+
"--commit",
|
|
37166
|
+
flag(args.commit),
|
|
37167
|
+
"--record-dir",
|
|
37168
|
+
flag(args.recordDir)
|
|
37169
|
+
];
|
|
37170
|
+
for (const critic of args.critics ?? []) argv.push("--critic", critic);
|
|
37171
|
+
if (args.observedPr !== void 0) argv.push("--observed-pr", args.observedPr);
|
|
37172
|
+
if (args.observedCi !== void 0) argv.push("--observed-ci", args.observedCi);
|
|
37173
|
+
return argv;
|
|
37174
|
+
}
|
|
37175
|
+
case "change-report":
|
|
37176
|
+
return ["change-report", "--task-dir", flag(args.taskDir)];
|
|
37177
|
+
default: {
|
|
37178
|
+
const unreachable = subcommand;
|
|
37179
|
+
throw new Error(`unknown assign verb ${String(unreachable)}`);
|
|
37180
|
+
}
|
|
37181
|
+
}
|
|
37182
|
+
}
|
|
37183
|
+
async function cmdAssign(runtime, subcommand, args) {
|
|
37184
|
+
const command = `assign ${subcommand}`;
|
|
37185
|
+
const root = discoverKxmProjectRoot(runtime.cwd);
|
|
37186
|
+
if (!root) return refuse3(runtime, command, "project_required", `${command} requires a KXM project (run kxm init first)`);
|
|
37187
|
+
if (!existsSync30(join37(root, "scripts", "assignment-run.mjs"))) {
|
|
37188
|
+
return refuse3(runtime, command, "assign_runner_missing", `${command} requires scripts/assignment-run.mjs in the project root`);
|
|
37189
|
+
}
|
|
37190
|
+
const argv = ["node", RUNNER_REL, ...runnerArgv(subcommand, args)];
|
|
37191
|
+
if (runtime.dryRun) {
|
|
37192
|
+
const payload = { schema: CLI_RESULT_SCHEMA, ok: true, command, dryRun: true, argv };
|
|
37193
|
+
runtime.io.stdout(runtime.json ? `${JSON.stringify(payload)}
|
|
37194
|
+
` : `${argv.join(" ")}
|
|
37195
|
+
`);
|
|
37196
|
+
return 0;
|
|
37197
|
+
}
|
|
37198
|
+
const spawn5 = kxmAssignCliSeams.spawn ?? ((commandName, commandArgs, options) => {
|
|
37199
|
+
const result2 = spawnSync7(commandName, commandArgs, {
|
|
37200
|
+
cwd: options.cwd,
|
|
37201
|
+
stdio: options.stdio,
|
|
37202
|
+
env: options.env,
|
|
37203
|
+
windowsHide: true
|
|
37204
|
+
});
|
|
37205
|
+
return { status: result2.status, ...result2.error ? { error: result2.error } : {} };
|
|
37206
|
+
});
|
|
37207
|
+
const result = spawn5("node", argv.slice(1), { cwd: root, stdio: "inherit", env: runtime.env });
|
|
37208
|
+
if (result.status === null) {
|
|
37209
|
+
const detail = result.error?.message ?? "the assignment runner could not be started";
|
|
37210
|
+
return refuse3(runtime, command, "assign_spawn_failed", detail);
|
|
37211
|
+
}
|
|
37212
|
+
return result.status;
|
|
37213
|
+
}
|
|
37214
|
+
|
|
37110
37215
|
// plugins/kxm/src/cli/hub.ts
|
|
37111
37216
|
init_redact();
|
|
37112
37217
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
37113
|
-
import { existsSync as
|
|
37114
|
-
import { join as
|
|
37218
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync28, readFileSync as readFileSync35, readdirSync as readdirSync12, rmSync as rmSync11, writeFileSync as writeFileSync25 } from "node:fs";
|
|
37219
|
+
import { join as join47, resolve as resolve28 } from "node:path";
|
|
37115
37220
|
init_hub_env();
|
|
37116
37221
|
init_envelope();
|
|
37117
37222
|
|
|
@@ -42809,7 +42914,7 @@ import * as path2 from "node:path";
|
|
|
42809
42914
|
|
|
42810
42915
|
// node_modules/@earendil-works/pi-tui/dist/native-module-path.js
|
|
42811
42916
|
import { createRequire as createRequire2 } from "node:module";
|
|
42812
|
-
import { dirname as dirname19, join as
|
|
42917
|
+
import { dirname as dirname19, join as join38 } from "node:path";
|
|
42813
42918
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
42814
42919
|
var moduleRequire = createRequire2(import.meta.url);
|
|
42815
42920
|
var TUI_PACKAGE_NAME = "@earendil-works/pi-tui";
|
|
@@ -42818,10 +42923,10 @@ function getNativeModuleCandidates(nativePath, options = {}) {
|
|
|
42818
42923
|
const candidates = [];
|
|
42819
42924
|
try {
|
|
42820
42925
|
const packageEntry = (options.resolvePackage ?? moduleRequire.resolve)(TUI_PACKAGE_NAME);
|
|
42821
|
-
candidates.push(
|
|
42926
|
+
candidates.push(join38(dirname19(packageEntry), "..", nativePath));
|
|
42822
42927
|
} catch {
|
|
42823
42928
|
}
|
|
42824
|
-
candidates.push(
|
|
42929
|
+
candidates.push(join38(moduleDir, "..", nativePath), join38(moduleDir, nativePath), join38(dirname19(options.execPath ?? process.execPath), nativePath));
|
|
42825
42930
|
return Array.from(new Set(candidates));
|
|
42826
42931
|
}
|
|
42827
42932
|
|
|
@@ -45552,8 +45657,8 @@ var MAX_RENDER_WRITE_CHARS = 1024 * 1024;
|
|
|
45552
45657
|
|
|
45553
45658
|
// plugins/kxm/src/tui.ts
|
|
45554
45659
|
import { mkdirSync as mkdirSync25 } from "node:fs";
|
|
45555
|
-
import { join as
|
|
45556
|
-
import { spawnSync as
|
|
45660
|
+
import { join as join42, resolve as resolve27, dirname as dirname20 } from "node:path";
|
|
45661
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
45557
45662
|
|
|
45558
45663
|
// packages/core/tui/src/types/surface.ts
|
|
45559
45664
|
var KXM_TUI_LIMITS = Object.freeze({
|
|
@@ -45696,9 +45801,9 @@ var SHARED_EFFECT_KINDS = Object.freeze([
|
|
|
45696
45801
|
// plugins/kxm/src/local-snapshot.ts
|
|
45697
45802
|
init_sqlite();
|
|
45698
45803
|
init_telemetry();
|
|
45699
|
-
import { existsSync as
|
|
45804
|
+
import { existsSync as existsSync31, readdirSync as readdirSync11, readFileSync as readFileSync30 } from "node:fs";
|
|
45700
45805
|
import { homedir as homedir6 } from "node:os";
|
|
45701
|
-
import { isAbsolute as isAbsolute9, join as
|
|
45806
|
+
import { isAbsolute as isAbsolute9, join as join41, resolve as resolve26 } from "node:path";
|
|
45702
45807
|
var DEFAULT_BUSY_TIMEOUT_MS = 5e3;
|
|
45703
45808
|
var RUNTIME_PROJECT_KEY = /^[A-Za-z0-9_-][A-Za-z0-9._-]*$/;
|
|
45704
45809
|
function processExists2(pid) {
|
|
@@ -45823,36 +45928,36 @@ function readOpenMessageMetadata(database, where = OPEN_MESSAGE_WHERE, params =
|
|
|
45823
45928
|
return messages;
|
|
45824
45929
|
}
|
|
45825
45930
|
function resolveKxmSnapshotPaths(cwd, env = process.env) {
|
|
45826
|
-
const stateDir = env.KXM_STATE_DIR?.trim() ||
|
|
45931
|
+
const stateDir = env.KXM_STATE_DIR?.trim() || join41(cwd, ".kxm", "state");
|
|
45827
45932
|
const configured = env.KXM_DATA_PATH?.trim();
|
|
45828
|
-
const dataPath = configured ? resolve26(cwd, configured) :
|
|
45933
|
+
const dataPath = configured ? resolve26(cwd, configured) : join41(stateDir, "kxm.db");
|
|
45829
45934
|
return { dataPath, stateDir };
|
|
45830
45935
|
}
|
|
45831
45936
|
function resolveKxmStateRoot(stateDir, options) {
|
|
45832
|
-
if (options?.kxmStateRoot &&
|
|
45937
|
+
if (options?.kxmStateRoot && existsSync31(options.kxmStateRoot)) {
|
|
45833
45938
|
return resolve26(options.kxmStateRoot);
|
|
45834
45939
|
}
|
|
45835
|
-
if (
|
|
45940
|
+
if (existsSync31(join41(stateDir, "runtime", "registry.db")) || existsSync31(join41(stateDir, "runtime", "projects"))) {
|
|
45836
45941
|
return stateDir;
|
|
45837
45942
|
}
|
|
45838
45943
|
const env = options?.env ?? process.env;
|
|
45839
45944
|
const explicit = env.KXM_STATE_HOME?.trim() || env.KXM_USER_STATE_DIR?.trim() || env.KXM_STATE_ROOT?.trim();
|
|
45840
|
-
if (explicit && isAbsolute9(explicit) &&
|
|
45945
|
+
if (explicit && isAbsolute9(explicit) && existsSync31(resolve26(explicit))) {
|
|
45841
45946
|
return resolve26(explicit);
|
|
45842
45947
|
}
|
|
45843
45948
|
let base;
|
|
45844
45949
|
if (process.platform === "win32") {
|
|
45845
45950
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
45846
|
-
base = localAppData && isAbsolute9(localAppData) ? localAppData :
|
|
45951
|
+
base = localAppData && isAbsolute9(localAppData) ? localAppData : join41(homedir6(), "AppData", "Local");
|
|
45847
45952
|
base = resolve26(base, "KXM");
|
|
45848
45953
|
} else if (process.platform === "darwin") {
|
|
45849
45954
|
base = resolve26(homedir6(), "Library", "Application Support", "KXM");
|
|
45850
45955
|
} else {
|
|
45851
45956
|
const xdgState = env.XDG_STATE_HOME?.trim();
|
|
45852
|
-
base = xdgState && isAbsolute9(xdgState) ? xdgState :
|
|
45957
|
+
base = xdgState && isAbsolute9(xdgState) ? xdgState : join41(homedir6(), ".local", "state");
|
|
45853
45958
|
base = resolve26(base, "kxm");
|
|
45854
45959
|
}
|
|
45855
|
-
if (
|
|
45960
|
+
if (existsSync31(base)) return base;
|
|
45856
45961
|
return void 0;
|
|
45857
45962
|
}
|
|
45858
45963
|
function readRuntimeRuns(eventDb, projectId) {
|
|
@@ -45885,7 +45990,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
45885
45990
|
let legacyRuns = [];
|
|
45886
45991
|
let legacyRunTotal = 0;
|
|
45887
45992
|
let plans = [];
|
|
45888
|
-
if (
|
|
45993
|
+
if (existsSync31(dataPath)) {
|
|
45889
45994
|
hasLegacy = true;
|
|
45890
45995
|
const database = openReadOnlyDatabase(dataPath);
|
|
45891
45996
|
try {
|
|
@@ -45916,11 +46021,11 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
45916
46021
|
let kxmRunTotal = 0;
|
|
45917
46022
|
const kxmStateRoot = scope && !scope.runtimeProjectId ? void 0 : resolveKxmStateRoot(stateDir, options);
|
|
45918
46023
|
if (kxmStateRoot) {
|
|
45919
|
-
const runtimeDir =
|
|
45920
|
-
const registryDbPath =
|
|
45921
|
-
const projectsDir =
|
|
46024
|
+
const runtimeDir = join41(kxmStateRoot, "runtime");
|
|
46025
|
+
const registryDbPath = join41(runtimeDir, "registry.db");
|
|
46026
|
+
const projectsDir = join41(runtimeDir, "projects");
|
|
45922
46027
|
const projectKeys = /* @__PURE__ */ new Set();
|
|
45923
|
-
if (
|
|
46028
|
+
if (existsSync31(registryDbPath)) {
|
|
45924
46029
|
hasKxm = true;
|
|
45925
46030
|
try {
|
|
45926
46031
|
const regDb = openReadOnlyDatabase(registryDbPath);
|
|
@@ -45936,7 +46041,7 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
45936
46041
|
} catch {
|
|
45937
46042
|
}
|
|
45938
46043
|
}
|
|
45939
|
-
if (!scope &&
|
|
46044
|
+
if (!scope && existsSync31(projectsDir)) {
|
|
45940
46045
|
try {
|
|
45941
46046
|
for (const entry of readdirSync11(projectsDir, { withFileTypes: true })) {
|
|
45942
46047
|
if (entry.isDirectory()) {
|
|
@@ -45948,8 +46053,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
45948
46053
|
}
|
|
45949
46054
|
for (const key of projectKeys) {
|
|
45950
46055
|
if (scope && !RUNTIME_PROJECT_KEY.test(key)) continue;
|
|
45951
|
-
const eventDbPath =
|
|
45952
|
-
if (
|
|
46056
|
+
const eventDbPath = join41(projectsDir, key, "run-events.db");
|
|
46057
|
+
if (existsSync31(eventDbPath)) {
|
|
45953
46058
|
hasKxm = true;
|
|
45954
46059
|
try {
|
|
45955
46060
|
const eventDb = openReadOnlyDatabase(eventDbPath);
|
|
@@ -45967,10 +46072,10 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
45967
46072
|
}
|
|
45968
46073
|
}
|
|
45969
46074
|
const pids = [];
|
|
45970
|
-
if (
|
|
46075
|
+
if (existsSync31(stateDir)) {
|
|
45971
46076
|
for (const file of readdirSync11(stateDir).filter((name) => name.endsWith(".pid"))) {
|
|
45972
46077
|
try {
|
|
45973
|
-
const record = JSON.parse(readFileSync30(
|
|
46078
|
+
const record = JSON.parse(readFileSync30(join41(stateDir, file), "utf8"));
|
|
45974
46079
|
pids.push({
|
|
45975
46080
|
file,
|
|
45976
46081
|
...record.role ? { role: record.role } : {},
|
|
@@ -46009,8 +46114,8 @@ function loadLocalMeshSnapshot(dataPath, stateDir, options) {
|
|
|
46009
46114
|
} else {
|
|
46010
46115
|
source = "legacy";
|
|
46011
46116
|
}
|
|
46012
|
-
const telemetryFile =
|
|
46013
|
-
const spend =
|
|
46117
|
+
const telemetryFile = join41(stateDir, "telemetry.jsonl");
|
|
46118
|
+
const spend = existsSync31(telemetryFile) ? readRoutingRecords(telemetryFile) : [];
|
|
46014
46119
|
return {
|
|
46015
46120
|
source,
|
|
46016
46121
|
agents: agents.sort((a, b2) => Number(b2.online) - Number(a.online) || a.name.localeCompare(b2.name)),
|
|
@@ -46110,16 +46215,16 @@ function applyMeshTuiKey(view, key, itemCount = 0) {
|
|
|
46110
46215
|
function copyToClipboard(text) {
|
|
46111
46216
|
try {
|
|
46112
46217
|
if (process.platform === "darwin") {
|
|
46113
|
-
const proc =
|
|
46218
|
+
const proc = spawnSync8("pbcopy", { input: text, encoding: "utf8", windowsHide: true });
|
|
46114
46219
|
return proc.status === 0;
|
|
46115
46220
|
}
|
|
46116
46221
|
if (process.platform === "win32") {
|
|
46117
|
-
const proc =
|
|
46222
|
+
const proc = spawnSync8("clip", { input: text, encoding: "utf8", windowsHide: true });
|
|
46118
46223
|
return proc.status === 0;
|
|
46119
46224
|
}
|
|
46120
|
-
const wl =
|
|
46225
|
+
const wl = spawnSync8("wl-copy", [text], { encoding: "utf8", windowsHide: true });
|
|
46121
46226
|
if (wl.status === 0) return true;
|
|
46122
|
-
const xclip =
|
|
46227
|
+
const xclip = spawnSync8("xclip", ["-selection", "clipboard"], { input: text, encoding: "utf8", windowsHide: true });
|
|
46123
46228
|
return xclip.status === 0;
|
|
46124
46229
|
} catch {
|
|
46125
46230
|
return false;
|
|
@@ -46127,7 +46232,7 @@ function copyToClipboard(text) {
|
|
|
46127
46232
|
}
|
|
46128
46233
|
function spawnDegradeWorktree(repoRoot, runId, options) {
|
|
46129
46234
|
const runner = options?.execFn ?? ((cmd, args) => {
|
|
46130
|
-
const res =
|
|
46235
|
+
const res = spawnSync8(cmd, args, {
|
|
46131
46236
|
cwd: repoRoot,
|
|
46132
46237
|
encoding: "utf8",
|
|
46133
46238
|
windowsHide: true,
|
|
@@ -46144,7 +46249,7 @@ function spawnDegradeWorktree(repoRoot, runId, options) {
|
|
|
46144
46249
|
const cleanRunId = runId.replace(/^run_/, "");
|
|
46145
46250
|
const desc = options?.description ? slugifyBranchPart(options.description, 30) : "degrade";
|
|
46146
46251
|
const branchName = `kxm/run-${cleanRunId}-${desc}`;
|
|
46147
|
-
const relativeWtPath =
|
|
46252
|
+
const relativeWtPath = join42(".kxm", "worktrees", `run-${cleanRunId}-${desc}`);
|
|
46148
46253
|
const absoluteWtPath = resolve27(repoRoot, relativeWtPath);
|
|
46149
46254
|
const jumpCommand = `cd "${absoluteWtPath}"`;
|
|
46150
46255
|
try {
|
|
@@ -46911,10 +47016,10 @@ async function runMeshTui(input) {
|
|
|
46911
47016
|
}
|
|
46912
47017
|
|
|
46913
47018
|
// plugins/kxm/src/session-work.ts
|
|
46914
|
-
import { spawnSync as
|
|
47019
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
46915
47020
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
46916
|
-
import { existsSync as
|
|
46917
|
-
import { join as
|
|
47021
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync26, readFileSync as readFileSync31, renameSync as renameSync8, writeFileSync as writeFileSync23 } from "node:fs";
|
|
47022
|
+
import { join as join43 } from "node:path";
|
|
46918
47023
|
init_hub_binding();
|
|
46919
47024
|
init_telemetry();
|
|
46920
47025
|
var MAX_SESSION_BRIEF_TASKS = 5;
|
|
@@ -46972,10 +47077,10 @@ function formatShipLine(ship) {
|
|
|
46972
47077
|
}
|
|
46973
47078
|
function readGitShip(cwd) {
|
|
46974
47079
|
try {
|
|
46975
|
-
const dirty =
|
|
47080
|
+
const dirty = spawnSync9("git", ["-C", cwd, "status", "--porcelain"], { encoding: "utf8", windowsHide: true });
|
|
46976
47081
|
if (dirty.status !== 0) return void 0;
|
|
46977
47082
|
const isDirty = dirty.stdout.trim().length > 0;
|
|
46978
|
-
const upstream =
|
|
47083
|
+
const upstream = spawnSync9("git", ["-C", cwd, "rev-list", "--count", "@{u}..HEAD"], { encoding: "utf8", windowsHide: true });
|
|
46979
47084
|
if (upstream.status === 0) {
|
|
46980
47085
|
return {
|
|
46981
47086
|
dirty: isDirty,
|
|
@@ -46983,9 +47088,9 @@ function readGitShip(cwd) {
|
|
|
46983
47088
|
};
|
|
46984
47089
|
}
|
|
46985
47090
|
for (const baseRef of ["origin/HEAD", "main", "origin/main", "master", "origin/master"]) {
|
|
46986
|
-
const mb =
|
|
47091
|
+
const mb = spawnSync9("git", ["-C", cwd, "merge-base", baseRef, "HEAD"], { encoding: "utf8", windowsHide: true });
|
|
46987
47092
|
if (mb.status === 0 && mb.stdout.trim()) {
|
|
46988
|
-
const count =
|
|
47093
|
+
const count = spawnSync9("git", ["-C", cwd, "rev-list", "--count", `${mb.stdout.trim()}..HEAD`], { encoding: "utf8", windowsHide: true });
|
|
46989
47094
|
if (count.status === 0) {
|
|
46990
47095
|
return {
|
|
46991
47096
|
dirty: isDirty,
|
|
@@ -47073,9 +47178,9 @@ function buildSessionBrief(snapshot, current, hub, ship, updateLatest, cost, ses
|
|
|
47073
47178
|
};
|
|
47074
47179
|
}
|
|
47075
47180
|
function readCachedSessionBrief(stateDir) {
|
|
47076
|
-
const file =
|
|
47181
|
+
const file = join43(stateDir, "session-brief.json");
|
|
47077
47182
|
try {
|
|
47078
|
-
if (!
|
|
47183
|
+
if (!existsSync32(file)) return void 0;
|
|
47079
47184
|
const raw = readFileSync31(file, "utf8");
|
|
47080
47185
|
const parsed = JSON.parse(raw);
|
|
47081
47186
|
if (parsed && parsed.schema === "kxm.session-brief.v1" && typeof parsed.generatedAt === "string") {
|
|
@@ -47092,7 +47197,7 @@ function readCachedSessionBrief(stateDir) {
|
|
|
47092
47197
|
function writeCachedSessionBrief(stateDir, brief) {
|
|
47093
47198
|
try {
|
|
47094
47199
|
mkdirSync26(stateDir, { recursive: true, mode: 448 });
|
|
47095
|
-
const file =
|
|
47200
|
+
const file = join43(stateDir, "session-brief.json");
|
|
47096
47201
|
const tmp = `${file}.tmp.${randomUUID12().slice(0, 8)}`;
|
|
47097
47202
|
writeFileSync23(tmp, JSON.stringify(brief, null, 2), { encoding: "utf8", mode: 384 });
|
|
47098
47203
|
renameSync8(tmp, file);
|
|
@@ -47101,8 +47206,8 @@ function writeCachedSessionBrief(stateDir, brief) {
|
|
|
47101
47206
|
}
|
|
47102
47207
|
function estimateSessionCost(stateDir) {
|
|
47103
47208
|
try {
|
|
47104
|
-
const telemetryFile =
|
|
47105
|
-
if (!
|
|
47209
|
+
const telemetryFile = join43(stateDir, "telemetry.jsonl");
|
|
47210
|
+
if (!existsSync32(telemetryFile)) return void 0;
|
|
47106
47211
|
const records = readRoutingRecords(telemetryFile);
|
|
47107
47212
|
if (records.length === 0) return void 0;
|
|
47108
47213
|
let totalCost = 0;
|
|
@@ -47274,11 +47379,11 @@ init_hub_binding();
|
|
|
47274
47379
|
|
|
47275
47380
|
// plugins/kxm/src/kxm-install-kind.ts
|
|
47276
47381
|
init_bindings();
|
|
47277
|
-
import { existsSync as
|
|
47278
|
-
import { dirname as dirname21, join as
|
|
47382
|
+
import { existsSync as existsSync33, readFileSync as readFileSync32 } from "node:fs";
|
|
47383
|
+
import { dirname as dirname21, join as join44 } from "node:path";
|
|
47279
47384
|
function packageIsKxm(root) {
|
|
47280
47385
|
try {
|
|
47281
|
-
const pkg = JSON.parse(readFileSync32(
|
|
47386
|
+
const pkg = JSON.parse(readFileSync32(join44(root, "package.json"), "utf8"));
|
|
47282
47387
|
return pkg.name === "@kontextmind/kxm";
|
|
47283
47388
|
} catch {
|
|
47284
47389
|
return false;
|
|
@@ -47327,12 +47432,12 @@ function report(kind, root) {
|
|
|
47327
47432
|
return { kind, root, instruction: installKindInstruction(kind, root) };
|
|
47328
47433
|
}
|
|
47329
47434
|
function classifyInstallRoot(probe) {
|
|
47330
|
-
const piGitRoot =
|
|
47435
|
+
const piGitRoot = join44(probe.homeDir, ".pi", "agent", "git");
|
|
47331
47436
|
if (isUnder(probe.repoRoot, piGitRoot, probe.platform)) return report("pi-git", probe.repoRoot);
|
|
47332
|
-
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() ||
|
|
47333
|
-
const pluginsRoot =
|
|
47437
|
+
const claudeHome = probe.env.CLAUDE_CONFIG_DIR?.trim() || join44(probe.homeDir, ".claude");
|
|
47438
|
+
const pluginsRoot = join44(claudeHome, "plugins");
|
|
47334
47439
|
if (isUnder(probe.moduleDir, pluginsRoot, probe.platform)) return report("claude-marketplace", probe.moduleDir);
|
|
47335
|
-
const hasGit =
|
|
47440
|
+
const hasGit = existsSync33(join44(probe.repoRoot, ".git"));
|
|
47336
47441
|
if (hasGit && packageIsKxm(probe.repoRoot)) return report("source", probe.repoRoot);
|
|
47337
47442
|
if (isNpmPackageLayout(probe.repoRoot, probe.platform) && packageIsKxm(probe.repoRoot) && !hasGit) {
|
|
47338
47443
|
return report("npm-package", probe.repoRoot);
|
|
@@ -47356,12 +47461,12 @@ init_bindings();
|
|
|
47356
47461
|
|
|
47357
47462
|
// plugins/kxm/src/kxm-update-config.ts
|
|
47358
47463
|
var import_yaml16 = __toESM(require_dist(), 1);
|
|
47359
|
-
import { existsSync as
|
|
47360
|
-
import { join as
|
|
47464
|
+
import { existsSync as existsSync34, readFileSync as readFileSync33 } from "node:fs";
|
|
47465
|
+
import { join as join45 } from "node:path";
|
|
47361
47466
|
init_bindings();
|
|
47362
47467
|
function loadKxmUpdateConfig(env = process.env) {
|
|
47363
|
-
const path4 =
|
|
47364
|
-
if (!
|
|
47468
|
+
const path4 = join45(kxmUserStateRoot({ env }), "update.yaml");
|
|
47469
|
+
if (!existsSync34(path4)) return { schema: KXM_UPDATE_SCHEMA, auto: false, source: "github" };
|
|
47365
47470
|
let parsed;
|
|
47366
47471
|
try {
|
|
47367
47472
|
parsed = (0, import_yaml16.parse)(readFileSync33(path4, "utf8"));
|
|
@@ -47392,8 +47497,8 @@ function loadKxmUpdateConfig(env = process.env) {
|
|
|
47392
47497
|
// plugins/kxm/src/session.ts
|
|
47393
47498
|
init_protocol();
|
|
47394
47499
|
init_envelope();
|
|
47395
|
-
import { existsSync as
|
|
47396
|
-
import { join as
|
|
47500
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync27, readFileSync as readFileSync34, writeFileSync as writeFileSync24 } from "node:fs";
|
|
47501
|
+
import { join as join46 } from "node:path";
|
|
47397
47502
|
var SESSION_SCHEMA = "kxm.session.v1";
|
|
47398
47503
|
var SessionConfigError = class extends Error {
|
|
47399
47504
|
code = "session_config_invalid";
|
|
@@ -47403,12 +47508,12 @@ var SessionConfigError = class extends Error {
|
|
|
47403
47508
|
}
|
|
47404
47509
|
};
|
|
47405
47510
|
function workflowAssetDirs(assetsDir, workflowId) {
|
|
47406
|
-
const root =
|
|
47407
|
-
return [root,
|
|
47511
|
+
const root = join46(assetsDir, "workflows", workflowId);
|
|
47512
|
+
return [root, join46(root, "inputs"), join46(root, "outputs"), join46(root, "generated")];
|
|
47408
47513
|
}
|
|
47409
47514
|
function sessionAssetDirs(assetsDir, sessionId) {
|
|
47410
|
-
const root =
|
|
47411
|
-
return [root,
|
|
47515
|
+
const root = join46(assetsDir, "sessions", sessionId);
|
|
47516
|
+
return [root, join46(root, "inputs"), join46(root, "outputs")];
|
|
47412
47517
|
}
|
|
47413
47518
|
function rosterNames(configDir) {
|
|
47414
47519
|
return [...loadRosterMap(configDir).values()].map((row) => String(row.name));
|
|
@@ -47458,7 +47563,7 @@ function workerFromRosterRow(name, row, project) {
|
|
|
47458
47563
|
function loadRosterMap(configDir) {
|
|
47459
47564
|
const byName = /* @__PURE__ */ new Map();
|
|
47460
47565
|
for (const [file, key] of [["agents.json", "agents"], ["gates.json", "gates"]]) {
|
|
47461
|
-
const path4 =
|
|
47566
|
+
const path4 = join46(configDir, file);
|
|
47462
47567
|
for (const row of loadRoster(path4, key)) {
|
|
47463
47568
|
const name = String(row.name).trim();
|
|
47464
47569
|
const lowered = name.toLowerCase();
|
|
@@ -47472,7 +47577,7 @@ function loadRosterMap(configDir) {
|
|
|
47472
47577
|
return byName;
|
|
47473
47578
|
}
|
|
47474
47579
|
function loadRoster(path4, key) {
|
|
47475
|
-
if (!
|
|
47580
|
+
if (!existsSync35(path4)) return [];
|
|
47476
47581
|
let parsed;
|
|
47477
47582
|
try {
|
|
47478
47583
|
parsed = JSON.parse(readFileSync34(path4, "utf8"));
|
|
@@ -47500,7 +47605,7 @@ function loadRoster(path4, key) {
|
|
|
47500
47605
|
});
|
|
47501
47606
|
}
|
|
47502
47607
|
function createSession(input) {
|
|
47503
|
-
const assetDir = input.mode === "workflow" && input.workflowId ?
|
|
47608
|
+
const assetDir = input.mode === "workflow" && input.workflowId ? join46("assets", "workflows", input.workflowId) : join46("assets", "sessions", input.id);
|
|
47504
47609
|
return {
|
|
47505
47610
|
schema: SESSION_SCHEMA,
|
|
47506
47611
|
id: input.id,
|
|
@@ -47513,8 +47618,8 @@ function createSession(input) {
|
|
|
47513
47618
|
};
|
|
47514
47619
|
}
|
|
47515
47620
|
function writeSession(assetsDir, session, dryRun = false) {
|
|
47516
|
-
const dir =
|
|
47517
|
-
const path4 =
|
|
47621
|
+
const dir = join46(assetsDir, "sessions", session.id);
|
|
47622
|
+
const path4 = join46(dir, "session.json");
|
|
47518
47623
|
if (!dryRun) {
|
|
47519
47624
|
mkdirSync27(dir, { recursive: true });
|
|
47520
47625
|
writeFileSync24(path4, `${JSON.stringify(session, null, 2)}
|
|
@@ -47570,9 +47675,9 @@ function moduleInstallRoot() {
|
|
|
47570
47675
|
}
|
|
47571
47676
|
}
|
|
47572
47677
|
function warnIgnoredProjectUpdateYaml(runtime) {
|
|
47573
|
-
const projectFile =
|
|
47574
|
-
if (!
|
|
47575
|
-
const userFile =
|
|
47678
|
+
const projectFile = join47(runtime.dirs.workspace, "update.yaml");
|
|
47679
|
+
if (!existsSync36(projectFile)) return;
|
|
47680
|
+
const userFile = join47(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
47576
47681
|
runtime.io.stderr(`kxm: ignoring .kxm/update.yaml in ${runtime.dirs.workdir}; update settings are read only from ${userFile}
|
|
47577
47682
|
`);
|
|
47578
47683
|
}
|
|
@@ -47620,7 +47725,7 @@ async function cmdDash(runtime, options = {}) {
|
|
|
47620
47725
|
return 2;
|
|
47621
47726
|
}
|
|
47622
47727
|
const screen = requested;
|
|
47623
|
-
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
47728
|
+
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join47(runtime.dirs.state, "kxm.db"));
|
|
47624
47729
|
if (runtime.dryRun) {
|
|
47625
47730
|
print(runtime.io, runtime.json, {
|
|
47626
47731
|
ok: true,
|
|
@@ -47666,7 +47771,7 @@ async function cmdHub(runtime) {
|
|
|
47666
47771
|
config = loadKxmUpdateConfig(runtime.env);
|
|
47667
47772
|
} catch (error) {
|
|
47668
47773
|
if (error instanceof KxmUpdateConfigError) {
|
|
47669
|
-
const yamlPath =
|
|
47774
|
+
const yamlPath = join47(kxmUserStateRoot({ env: runtime.env }), "update.yaml");
|
|
47670
47775
|
runtime.io.stderr(`kxm: ${error.message}; update check skipped; fix or remove ${yamlPath}
|
|
47671
47776
|
`);
|
|
47672
47777
|
} else {
|
|
@@ -47853,7 +47958,7 @@ async function cmdWorker(runtime, options) {
|
|
|
47853
47958
|
return await (runtime.io.spawnWorker ?? ((launchEnv) => spawnScript("kxm-worker.mjs", launchEnv)))(extraEnv);
|
|
47854
47959
|
}
|
|
47855
47960
|
async function cmdStop(runtime, waitMsFlag) {
|
|
47856
|
-
const pids =
|
|
47961
|
+
const pids = existsSync36(runtime.dirs.state) ? readdirSync12(runtime.dirs.state).filter((name) => name.endsWith(".pid")) : [];
|
|
47857
47962
|
if (runtime.dryRun) {
|
|
47858
47963
|
print(runtime.io, runtime.json, { ok: true, command: "stop", dryRun: true, pidFiles: pids }, "would signal pid files");
|
|
47859
47964
|
return 0;
|
|
@@ -47868,7 +47973,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47868
47973
|
const orphans = [];
|
|
47869
47974
|
for (const file of pids) {
|
|
47870
47975
|
try {
|
|
47871
|
-
const record = JSON.parse(readFileSync35(
|
|
47976
|
+
const record = JSON.parse(readFileSync35(join47(runtime.dirs.state, file), "utf8"));
|
|
47872
47977
|
const expectedControl = file === "hub.pid" ? "hub.stop" : file.startsWith("worker-") ? `${file.slice(0, -4)}.stop` : void 0;
|
|
47873
47978
|
const expectedRole = file === "hub.pid" ? "hub" : file.startsWith("worker-") ? "worker" : void 0;
|
|
47874
47979
|
if (record.version !== 1 || !Number.isInteger(record.pid) || record.pid <= 0 || !record.startedAt || !expectedControl || record.controlFile !== expectedControl || record.role !== expectedRole) {
|
|
@@ -47888,7 +47993,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47888
47993
|
ignored.push(file);
|
|
47889
47994
|
continue;
|
|
47890
47995
|
}
|
|
47891
|
-
writeFileSync25(
|
|
47996
|
+
writeFileSync25(join47(runtime.dirs.state, record.controlFile), `${JSON.stringify({ startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {}, requestedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
47892
47997
|
`, { encoding: "utf8", mode: 384 });
|
|
47893
47998
|
requested.push(file);
|
|
47894
47999
|
records.set(file, { pid: record.pid, startedAt: record.startedAt, ...record.generation ? { generation: record.generation } : {} });
|
|
@@ -47906,7 +48011,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47906
48011
|
while (Date.now() <= deadline && stopped.size < requested.length) {
|
|
47907
48012
|
for (const [file, record] of records) {
|
|
47908
48013
|
try {
|
|
47909
|
-
const current = JSON.parse(readFileSync35(
|
|
48014
|
+
const current = JSON.parse(readFileSync35(join47(runtime.dirs.state, file), "utf8"));
|
|
47910
48015
|
if (current.pid !== record.pid || current.startedAt !== record.startedAt || current.generation !== record.generation || !processExists(record.pid)) stopped.add(file);
|
|
47911
48016
|
} catch {
|
|
47912
48017
|
stopped.add(file);
|
|
@@ -47919,7 +48024,7 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47919
48024
|
for (const file of orphans) {
|
|
47920
48025
|
while (Date.now() <= deadlineOrphans) {
|
|
47921
48026
|
try {
|
|
47922
|
-
const current = JSON.parse(readFileSync35(
|
|
48027
|
+
const current = JSON.parse(readFileSync35(join47(runtime.dirs.state, file), "utf8"));
|
|
47923
48028
|
if (!Number.isInteger(current.serverPid) || !processExists(current.serverPid)) break;
|
|
47924
48029
|
} catch {
|
|
47925
48030
|
break;
|
|
@@ -47927,14 +48032,14 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47927
48032
|
await (runtime.io.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))))(100);
|
|
47928
48033
|
}
|
|
47929
48034
|
try {
|
|
47930
|
-
const current = JSON.parse(readFileSync35(
|
|
48035
|
+
const current = JSON.parse(readFileSync35(join47(runtime.dirs.state, file), "utf8"));
|
|
47931
48036
|
if (Number.isInteger(current.serverPid) && processExists(current.serverPid)) {
|
|
47932
48037
|
try {
|
|
47933
48038
|
process.kill(current.serverPid, "SIGKILL");
|
|
47934
48039
|
} catch {
|
|
47935
48040
|
}
|
|
47936
48041
|
}
|
|
47937
|
-
rmSync11(
|
|
48042
|
+
rmSync11(join47(runtime.dirs.state, file), { force: true });
|
|
47938
48043
|
} catch {
|
|
47939
48044
|
}
|
|
47940
48045
|
stopped.add(file);
|
|
@@ -47945,11 +48050,11 @@ async function cmdStop(runtime, waitMsFlag) {
|
|
|
47945
48050
|
}
|
|
47946
48051
|
async function cmdSessionStatus(runtime) {
|
|
47947
48052
|
const stateDir = runtime.dirs.state;
|
|
47948
|
-
const names3 =
|
|
48053
|
+
const names3 = existsSync36(stateDir) ? readdirSync12(stateDir) : [];
|
|
47949
48054
|
const claims = [];
|
|
47950
48055
|
for (const file of names3.filter((name) => name.endsWith(".pid"))) {
|
|
47951
48056
|
try {
|
|
47952
|
-
const record = JSON.parse(readFileSync35(
|
|
48057
|
+
const record = JSON.parse(readFileSync35(join47(stateDir, file), "utf8"));
|
|
47953
48058
|
claims.push({
|
|
47954
48059
|
file,
|
|
47955
48060
|
role: record.role,
|
|
@@ -47964,7 +48069,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
47964
48069
|
const recoveries = [];
|
|
47965
48070
|
for (const file of names3.filter((name) => name.startsWith("worker-recovery-") && name.endsWith(".json"))) {
|
|
47966
48071
|
try {
|
|
47967
|
-
const envelope = JSON.parse(readFileSync35(
|
|
48072
|
+
const envelope = JSON.parse(readFileSync35(join47(stateDir, file), "utf8"));
|
|
47968
48073
|
recoveries.push({
|
|
47969
48074
|
file,
|
|
47970
48075
|
reason: envelope.reason,
|
|
@@ -47990,7 +48095,7 @@ async function cmdSessionStatus(runtime) {
|
|
|
47990
48095
|
async function cmdAuthToken(runtime, options = {}) {
|
|
47991
48096
|
const tokenFile = sessionTokenPath(runtime.env.KXM_USER_CONFIG_DIR);
|
|
47992
48097
|
if (options.clear && runtime.dryRun) {
|
|
47993
|
-
const present =
|
|
48098
|
+
const present = existsSync36(tokenFile);
|
|
47994
48099
|
printPlan(runtime, { command: "auth token", cleared: present }, present ? [{ action: "delete", target: tokenFile }] : [], present ? "clear the session token from disk" : "no session token file to clear");
|
|
47995
48100
|
return 0;
|
|
47996
48101
|
}
|
|
@@ -48079,7 +48184,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
48079
48184
|
print(runtime.io, runtime.json, { ok: true, command: "session brief", sessionToken }, sessionToken);
|
|
48080
48185
|
return 0;
|
|
48081
48186
|
}
|
|
48082
|
-
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() ||
|
|
48187
|
+
const dataPath = resolve28(runtime.dirs.workdir, runtime.env.KXM_DATA_PATH?.trim() || join47(runtime.dirs.state, "kxm.db"));
|
|
48083
48188
|
const env = {
|
|
48084
48189
|
...runtime.env,
|
|
48085
48190
|
KXM_STATE_DIR: runtime.dirs.state,
|
|
@@ -48105,7 +48210,7 @@ async function cmdSessionBrief(runtime, options = {}) {
|
|
|
48105
48210
|
writeCache: !runtime.dryRun
|
|
48106
48211
|
});
|
|
48107
48212
|
if (runtime.dryRun) {
|
|
48108
|
-
if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target:
|
|
48213
|
+
if (!readCachedSessionBrief(runtime.dirs.state)) planned.push({ action: "write", target: join47(runtime.dirs.state, "session-brief.json") });
|
|
48109
48214
|
print(runtime.io, runtime.json, { ...brief, dryRun: true, planned }, [
|
|
48110
48215
|
options.status ? brief.statusLine : formatSessionBriefText(brief),
|
|
48111
48216
|
...planned.map((change) => `dry run: would ${change.action} ${change.target}`)
|
|
@@ -48187,11 +48292,11 @@ init_redact();
|
|
|
48187
48292
|
init_telemetry();
|
|
48188
48293
|
init_routing();
|
|
48189
48294
|
init_prices();
|
|
48190
|
-
import { spawnSync as
|
|
48295
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
48191
48296
|
import { createHash as createHash17 } from "node:crypto";
|
|
48192
|
-
import { existsSync as
|
|
48297
|
+
import { existsSync as existsSync43, mkdtempSync as mkdtempSync3, readFileSync as readFileSync40, rmSync as rmSync13 } from "node:fs";
|
|
48193
48298
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
48194
|
-
import { basename as basename11, extname as extname3, join as
|
|
48299
|
+
import { basename as basename11, extname as extname3, join as join53, resolve as resolve33 } from "node:path";
|
|
48195
48300
|
import { createInterface as createInterface3 } from "node:readline";
|
|
48196
48301
|
|
|
48197
48302
|
// plugins/kxm/src/improve.ts
|
|
@@ -48199,8 +48304,8 @@ init_routing();
|
|
|
48199
48304
|
init_protocol();
|
|
48200
48305
|
init_relevance();
|
|
48201
48306
|
import { createHash as createHash16 } from "node:crypto";
|
|
48202
|
-
import { existsSync as
|
|
48203
|
-
import { join as
|
|
48307
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync29, writeFileSync as writeFileSync26 } from "node:fs";
|
|
48308
|
+
import { join as join48, relative as relative7, resolve as resolve29 } from "node:path";
|
|
48204
48309
|
var CANDIDATE_SCHEMA = "kxm.candidate.v1";
|
|
48205
48310
|
var IMPROVEMENT_REPORT_SCHEMA = "kxm.improvement-report.v2";
|
|
48206
48311
|
function classifyCandidateKind(stepId, agentRole) {
|
|
@@ -48456,7 +48561,7 @@ function groupRoutingRecords(records, options = {}) {
|
|
|
48456
48561
|
}
|
|
48457
48562
|
function buildImprovementReport(records, options = {}) {
|
|
48458
48563
|
const projectRoot = options.projectRoot ? resolve29(options.projectRoot) : process.cwd();
|
|
48459
|
-
const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) :
|
|
48564
|
+
const candidatesDir = options.candidatesDir ? resolve29(options.candidatesDir) : join48(projectRoot, ".kxm", "candidates");
|
|
48460
48565
|
const promotionPolicy = options.promotionPolicy ?? "manual_pr";
|
|
48461
48566
|
const groups = groupRoutingRecords(records, options);
|
|
48462
48567
|
const candidates = [];
|
|
@@ -48470,7 +48575,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
48470
48575
|
group.workflowId
|
|
48471
48576
|
);
|
|
48472
48577
|
const diffFileName = `${group.candidateId}.diff`;
|
|
48473
|
-
const diffFilePath =
|
|
48578
|
+
const diffFilePath = join48(candidatesDir, diffFileName);
|
|
48474
48579
|
const relDiffPath = relative7(projectRoot, diffFilePath).replace(/\\/g, "/");
|
|
48475
48580
|
const candidate = {
|
|
48476
48581
|
schema: CANDIDATE_SCHEMA,
|
|
@@ -48492,11 +48597,11 @@ function buildImprovementReport(records, options = {}) {
|
|
|
48492
48597
|
createdAt: nowIso()
|
|
48493
48598
|
};
|
|
48494
48599
|
if (!options.dryRun) {
|
|
48495
|
-
if (!
|
|
48600
|
+
if (!existsSync37(candidatesDir)) {
|
|
48496
48601
|
mkdirSync29(candidatesDir, { recursive: true });
|
|
48497
48602
|
}
|
|
48498
48603
|
writeFileSync26(diffFilePath, diff, "utf8");
|
|
48499
|
-
const jsonFilePath =
|
|
48604
|
+
const jsonFilePath = join48(candidatesDir, `${group.candidateId}.json`);
|
|
48500
48605
|
writeFileSync26(jsonFilePath, JSON.stringify(candidate, null, 2) + "\n", "utf8");
|
|
48501
48606
|
}
|
|
48502
48607
|
candidates.push(candidate);
|
|
@@ -48525,7 +48630,7 @@ function buildImprovementReport(records, options = {}) {
|
|
|
48525
48630
|
}
|
|
48526
48631
|
function writeImprovementReport(improvementsDir, report2, dryRun = false) {
|
|
48527
48632
|
const stamp = report2.createdAt.replace(/[:.]/g, "-");
|
|
48528
|
-
const path4 =
|
|
48633
|
+
const path4 = join48(improvementsDir, `${stamp}.json`);
|
|
48529
48634
|
if (!dryRun) {
|
|
48530
48635
|
mkdirSync29(improvementsDir, { recursive: true });
|
|
48531
48636
|
writeFileSync26(path4, `${JSON.stringify(report2, null, 2)}
|
|
@@ -48609,7 +48714,7 @@ init_project_config();
|
|
|
48609
48714
|
init_runtime_store();
|
|
48610
48715
|
init_routing();
|
|
48611
48716
|
init_telemetry();
|
|
48612
|
-
import { existsSync as
|
|
48717
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
48613
48718
|
import { resolve as resolve30 } from "node:path";
|
|
48614
48719
|
var ENGINE_EVENTS_SQL = "SELECT run_id, sequence, event_type, payload FROM events WHERE event_type IN ('routing.attempt.recorded','step.entered','run.status_changed') ORDER BY run_id, sequence";
|
|
48615
48720
|
var SIMULATED_HARNESS = "driver-simulated";
|
|
@@ -48632,7 +48737,7 @@ function readEngineRoutingRecords(path4) {
|
|
|
48632
48737
|
undecided: 0,
|
|
48633
48738
|
duplicatesDropped: 0
|
|
48634
48739
|
};
|
|
48635
|
-
if (!
|
|
48740
|
+
if (!existsSync38(path4)) return { records: [], source };
|
|
48636
48741
|
source.exists = true;
|
|
48637
48742
|
let rows;
|
|
48638
48743
|
let database;
|
|
@@ -48708,7 +48813,7 @@ function readEngineRoutingRecords(path4) {
|
|
|
48708
48813
|
};
|
|
48709
48814
|
}
|
|
48710
48815
|
function readJsonlSource(kind, path4) {
|
|
48711
|
-
const exists =
|
|
48816
|
+
const exists = existsSync38(path4);
|
|
48712
48817
|
const records = exists ? readRoutingRecords(path4).map((entry) => entry.routing) : [];
|
|
48713
48818
|
return { records, source: { kind, path: path4, exists, records: records.length, duplicatesDropped: 0 } };
|
|
48714
48819
|
}
|
|
@@ -48753,8 +48858,8 @@ function loadRoutingSources(options) {
|
|
|
48753
48858
|
// plugins/kxm/src/modes.ts
|
|
48754
48859
|
var import_yaml17 = __toESM(require_dist(), 1);
|
|
48755
48860
|
init_prices();
|
|
48756
|
-
import { existsSync as
|
|
48757
|
-
import { join as
|
|
48861
|
+
import { existsSync as existsSync39, readFileSync as readFileSync37 } from "node:fs";
|
|
48862
|
+
import { join as join49 } from "node:path";
|
|
48758
48863
|
var DEFAULT_MODES_CONFIG = Object.freeze({
|
|
48759
48864
|
schema: "kxm.modes.v1",
|
|
48760
48865
|
majorModes: {
|
|
@@ -48817,8 +48922,8 @@ function loadModesConfig(projectRoot) {
|
|
|
48817
48922
|
if (!projectRoot) {
|
|
48818
48923
|
return DEFAULT_MODES_CONFIG;
|
|
48819
48924
|
}
|
|
48820
|
-
const modesPath =
|
|
48821
|
-
if (!
|
|
48925
|
+
const modesPath = join49(projectRoot, ".kxm", "modes.yaml");
|
|
48926
|
+
if (!existsSync39(modesPath)) {
|
|
48822
48927
|
return DEFAULT_MODES_CONFIG;
|
|
48823
48928
|
}
|
|
48824
48929
|
try {
|
|
@@ -48908,9 +49013,9 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
|
|
|
48908
49013
|
estimatedTokens: estimateTokens(baseSystemPromptChars)
|
|
48909
49014
|
});
|
|
48910
49015
|
for (const relPath of resolved.contextFiles) {
|
|
48911
|
-
const fullPath =
|
|
49016
|
+
const fullPath = join49(projectRoot, relPath);
|
|
48912
49017
|
let chars = 0;
|
|
48913
|
-
if (
|
|
49018
|
+
if (existsSync39(fullPath)) {
|
|
48914
49019
|
try {
|
|
48915
49020
|
chars = readFileSync37(fullPath, "utf8").length;
|
|
48916
49021
|
} catch {
|
|
@@ -49044,10 +49149,10 @@ ${divider}
|
|
|
49044
49149
|
|
|
49045
49150
|
// plugins/kxm/src/ssh-remote.ts
|
|
49046
49151
|
init_safety_integrity();
|
|
49047
|
-
import { spawnSync as
|
|
49048
|
-
import { existsSync as
|
|
49152
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
49153
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync30, readFileSync as readFileSync38, readdirSync as readdirSync13, rmSync as rmSync12, statSync as statSync5 } from "node:fs";
|
|
49049
49154
|
import { homedir as homedir8 } from "node:os";
|
|
49050
|
-
import { join as
|
|
49155
|
+
import { join as join50, resolve as resolve31 } from "node:path";
|
|
49051
49156
|
var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
|
|
49052
49157
|
var MAX_SSH_OUTPUT_LINES = 2e3;
|
|
49053
49158
|
var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
|
|
@@ -49073,8 +49178,8 @@ function truncateSshOutput(raw) {
|
|
|
49073
49178
|
return { text, truncated };
|
|
49074
49179
|
}
|
|
49075
49180
|
function parseSshConfig(configPath) {
|
|
49076
|
-
const targetPath = configPath ??
|
|
49077
|
-
if (!
|
|
49181
|
+
const targetPath = configPath ?? join50(homedir8(), ".ssh", "config");
|
|
49182
|
+
if (!existsSync40(targetPath)) {
|
|
49078
49183
|
return [];
|
|
49079
49184
|
}
|
|
49080
49185
|
try {
|
|
@@ -49120,7 +49225,7 @@ function parseSshConfig(configPath) {
|
|
|
49120
49225
|
return [];
|
|
49121
49226
|
}
|
|
49122
49227
|
}
|
|
49123
|
-
function resolveSshHostG(host, execFn =
|
|
49228
|
+
function resolveSshHostG(host, execFn = spawnSync10) {
|
|
49124
49229
|
try {
|
|
49125
49230
|
const result = execFn("ssh", ["-G", host], { encoding: "utf-8" });
|
|
49126
49231
|
if (result.status !== 0 || !result.stdout) {
|
|
@@ -49156,14 +49261,14 @@ function resolveSshHostG(host, execFn = spawnSync9) {
|
|
|
49156
49261
|
}
|
|
49157
49262
|
function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
|
|
49158
49263
|
const resolved = resolve31(socketDir);
|
|
49159
|
-
if (!
|
|
49264
|
+
if (!existsSync40(resolved)) {
|
|
49160
49265
|
mkdirSync30(resolved, { recursive: true, mode: 448 });
|
|
49161
49266
|
}
|
|
49162
49267
|
return resolved;
|
|
49163
49268
|
}
|
|
49164
49269
|
function buildSshArgs(options) {
|
|
49165
49270
|
const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
|
|
49166
|
-
const controlPath =
|
|
49271
|
+
const controlPath = join50(socketDir, "%C");
|
|
49167
49272
|
const persist = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
|
|
49168
49273
|
const args = [
|
|
49169
49274
|
"-o",
|
|
@@ -49186,9 +49291,9 @@ function buildSshArgs(options) {
|
|
|
49186
49291
|
args.push(options.host);
|
|
49187
49292
|
return args;
|
|
49188
49293
|
}
|
|
49189
|
-
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn =
|
|
49294
|
+
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync10) {
|
|
49190
49295
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
49191
|
-
const controlPath =
|
|
49296
|
+
const controlPath = join50(resolvedDir, "%C");
|
|
49192
49297
|
try {
|
|
49193
49298
|
const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
|
|
49194
49299
|
encoding: "utf-8"
|
|
@@ -49198,9 +49303,9 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
49198
49303
|
return false;
|
|
49199
49304
|
}
|
|
49200
49305
|
}
|
|
49201
|
-
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn =
|
|
49306
|
+
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync10) {
|
|
49202
49307
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
49203
|
-
const controlPath =
|
|
49308
|
+
const controlPath = join50(resolvedDir, "%C");
|
|
49204
49309
|
try {
|
|
49205
49310
|
const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
|
|
49206
49311
|
encoding: "utf-8"
|
|
@@ -49212,7 +49317,7 @@ function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
49212
49317
|
}
|
|
49213
49318
|
function executeSshRun(params) {
|
|
49214
49319
|
const startTime = Date.now();
|
|
49215
|
-
const execSyncFn = params.execFn ??
|
|
49320
|
+
const execSyncFn = params.execFn ?? spawnSync10;
|
|
49216
49321
|
if (params.action === "info") {
|
|
49217
49322
|
if (params.host) {
|
|
49218
49323
|
const hostInfo = resolveSshHostG(params.host, execSyncFn);
|
|
@@ -49648,9 +49753,9 @@ complete -c kxm -n "__fish_seen_subcommand_from goal" -a "create list get"
|
|
|
49648
49753
|
}
|
|
49649
49754
|
|
|
49650
49755
|
// plugins/kxm/src/completion-install.ts
|
|
49651
|
-
import { existsSync as
|
|
49756
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync31, readFileSync as readFileSync39, writeFileSync as writeFileSync27 } from "node:fs";
|
|
49652
49757
|
import { homedir as homedir9 } from "node:os";
|
|
49653
|
-
import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as isAbsolute10, join as
|
|
49758
|
+
import { basename as basename10, delimiter, dirname as dirname24, isAbsolute as isAbsolute10, join as join51, resolve as resolve32 } from "node:path";
|
|
49654
49759
|
var COMPLETION_MARKER = "# kxm completion";
|
|
49655
49760
|
var PATH_MARKER = "# kxm path";
|
|
49656
49761
|
function detectShell(env = process.env, platform = process.platform) {
|
|
@@ -49672,25 +49777,25 @@ function completionScriptPath(shell, options = {}) {
|
|
|
49672
49777
|
const env = options.env ?? process.env;
|
|
49673
49778
|
const explicit = options.configDir ?? env.KXM_USER_CONFIG_DIR?.trim();
|
|
49674
49779
|
const base = explicit && explicit.length > 0 ? resolve32(explicit) : resolve32(effectiveHome(options), ".config", "kxm");
|
|
49675
|
-
return
|
|
49780
|
+
return join51(base, "completions", `kxm.${shell}`);
|
|
49676
49781
|
}
|
|
49677
49782
|
function bashRcCandidate(options) {
|
|
49678
49783
|
const home = effectiveHome(options);
|
|
49679
|
-
const candidates = [
|
|
49680
|
-
const existing = candidates.find((candidate) =>
|
|
49784
|
+
const candidates = [join51(home, ".bashrc"), join51(home, ".bash_profile")];
|
|
49785
|
+
const existing = candidates.find((candidate) => existsSync41(candidate));
|
|
49681
49786
|
return existing ?? candidates[0];
|
|
49682
49787
|
}
|
|
49683
49788
|
function zshRcCandidate(options) {
|
|
49684
49789
|
const env = options.env ?? process.env;
|
|
49685
49790
|
const home = effectiveHome(options);
|
|
49686
|
-
if (env.ZDOTDIR?.trim()) return
|
|
49687
|
-
return
|
|
49791
|
+
if (env.ZDOTDIR?.trim()) return join51(resolve32(env.ZDOTDIR.trim()), ".zshrc");
|
|
49792
|
+
return join51(home, ".zshrc");
|
|
49688
49793
|
}
|
|
49689
49794
|
function fishCompletionTarget(shell, options) {
|
|
49690
49795
|
const env = options.env ?? process.env;
|
|
49691
49796
|
const home = effectiveHome(options);
|
|
49692
|
-
if (env.XDG_CONFIG_HOME?.trim()) return
|
|
49693
|
-
return
|
|
49797
|
+
if (env.XDG_CONFIG_HOME?.trim()) return join51(resolve32(env.XDG_CONFIG_HOME.trim()), "fish", "completions", "kxm.fish");
|
|
49798
|
+
return join51(home, ".config", "fish", "completions", "kxm.fish");
|
|
49694
49799
|
}
|
|
49695
49800
|
function completionRcTarget(shell, options = {}) {
|
|
49696
49801
|
if (shell === "fish") {
|
|
@@ -49722,13 +49827,13 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
49722
49827
|
const scriptPath = completionScriptPath(shell, options);
|
|
49723
49828
|
const { rcFile } = completionRcTarget(shell, options);
|
|
49724
49829
|
const script = generateShellCompletion(shell);
|
|
49725
|
-
const existingScript =
|
|
49830
|
+
const existingScript = existsSync41(scriptPath);
|
|
49726
49831
|
const existingScriptMatches = existingScript && readFileSync39(scriptPath, "utf8") === script;
|
|
49727
49832
|
let rcModified = false;
|
|
49728
49833
|
let alreadyInstalled = false;
|
|
49729
49834
|
if (shell === "fish") {
|
|
49730
49835
|
const fishTarget = fishCompletionTarget(shell, options);
|
|
49731
|
-
const fishInstalled =
|
|
49836
|
+
const fishInstalled = existsSync41(fishTarget) && readFileSync39(fishTarget, "utf8") === script;
|
|
49732
49837
|
alreadyInstalled = fishInstalled;
|
|
49733
49838
|
if (!options.dryRun && (!fishInstalled || options.overwrite)) {
|
|
49734
49839
|
mkdirSync31(resolve32(fishTarget, ".."), { recursive: true });
|
|
@@ -49745,7 +49850,7 @@ function installShellCompletion(shellInput, options = {}) {
|
|
|
49745
49850
|
}
|
|
49746
49851
|
if (rcFile) {
|
|
49747
49852
|
const line = sourceLine(shell, scriptPath);
|
|
49748
|
-
const rcContent =
|
|
49853
|
+
const rcContent = existsSync41(rcFile) ? readFileSync39(rcFile, "utf8") : "";
|
|
49749
49854
|
alreadyInstalled = rcContent.includes(line) || rcContent.includes(`${COMPLETION_MARKER}`);
|
|
49750
49855
|
}
|
|
49751
49856
|
if (!options.dryRun) {
|
|
@@ -49761,7 +49866,7 @@ ${marker}
|
|
|
49761
49866
|
${line}
|
|
49762
49867
|
`;
|
|
49763
49868
|
mkdirSync31(resolve32(rcFile, ".."), { recursive: true });
|
|
49764
|
-
writeFileSync27(rcFile, (
|
|
49869
|
+
writeFileSync27(rcFile, (existsSync41(rcFile) ? readFileSync39(rcFile, "utf8") : "") + stanza, { encoding: "utf8" });
|
|
49765
49870
|
rcModified = true;
|
|
49766
49871
|
}
|
|
49767
49872
|
}
|
|
@@ -49778,13 +49883,13 @@ function kxmBinDir(env = process.env) {
|
|
|
49778
49883
|
const argv1 = env.KXM_ENTRY ?? process.argv[1];
|
|
49779
49884
|
if (argv1 && isAbsolute10(argv1)) {
|
|
49780
49885
|
const dir = dirname24(argv1);
|
|
49781
|
-
if (
|
|
49886
|
+
if (existsSync41(join51(dir, process.platform === "win32" ? "kxm.cmd" : "kxm"))) return dir;
|
|
49782
49887
|
}
|
|
49783
49888
|
const pathEnv = env.PATH ?? "";
|
|
49784
49889
|
for (const part of pathEnv.split(delimiter)) {
|
|
49785
49890
|
if (!part) continue;
|
|
49786
49891
|
const candidate = resolve32(part, process.platform === "win32" ? "kxm.cmd" : "kxm");
|
|
49787
|
-
if (
|
|
49892
|
+
if (existsSync41(candidate)) return resolve32(part);
|
|
49788
49893
|
}
|
|
49789
49894
|
return void 0;
|
|
49790
49895
|
}
|
|
@@ -49802,7 +49907,7 @@ function installPathEntry(shellInput, options = {}) {
|
|
|
49802
49907
|
}
|
|
49803
49908
|
const { rcFile } = completionRcTarget(shell, options);
|
|
49804
49909
|
const line = pathLine(binDir);
|
|
49805
|
-
const rcContent =
|
|
49910
|
+
const rcContent = existsSync41(rcFile ?? "") ? readFileSync39(rcFile, "utf8") : "";
|
|
49806
49911
|
const alreadyInstalled = rcContent.includes(binDir) || (options.env?.PATH ?? process.env.PATH ?? "").split(delimiter).includes(binDir);
|
|
49807
49912
|
if (!options.dryRun && rcFile && !alreadyInstalled) {
|
|
49808
49913
|
mkdirSync31(dirname24(rcFile), { recursive: true });
|
|
@@ -49817,8 +49922,8 @@ ${line}
|
|
|
49817
49922
|
// plugins/kxm/src/init-guide-setup.ts
|
|
49818
49923
|
var import_yaml18 = __toESM(require_dist(), 1);
|
|
49819
49924
|
init_routes();
|
|
49820
|
-
import { existsSync as
|
|
49821
|
-
import { dirname as dirname25, join as
|
|
49925
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync32, writeFileSync as writeFileSync28 } from "node:fs";
|
|
49926
|
+
import { dirname as dirname25, join as join52 } from "node:path";
|
|
49822
49927
|
var ADMITTED_GUIDE_BINDINGS = Object.freeze({
|
|
49823
49928
|
"anthropic/claude-fable-5.1": { harness: "claude", provider: "anthropic", model: "fable" },
|
|
49824
49929
|
"anthropic/fable": { harness: "claude", provider: "anthropic", model: "fable" },
|
|
@@ -50209,13 +50314,13 @@ function renderGuideSetupFiles(projectRoot, plan) {
|
|
|
50209
50314
|
const stage = roleStages.get(role);
|
|
50210
50315
|
if (!stage) continue;
|
|
50211
50316
|
files.push({
|
|
50212
|
-
path:
|
|
50317
|
+
path: join52(projectRoot, ".kxm", "agents", `${role}.yaml`),
|
|
50213
50318
|
content: (0, import_yaml18.stringify)(agentDocument(role, stage, binding))
|
|
50214
50319
|
});
|
|
50215
50320
|
}
|
|
50216
50321
|
for (const workflow of plan.workflows) {
|
|
50217
50322
|
files.push({
|
|
50218
|
-
path:
|
|
50323
|
+
path: join52(projectRoot, ".kxm", "workflows", `${workflow.slug}.yaml`),
|
|
50219
50324
|
content: (0, import_yaml18.stringify)(workflowDocument(workflow))
|
|
50220
50325
|
});
|
|
50221
50326
|
}
|
|
@@ -50232,7 +50337,7 @@ function mergeGuideRouteAdmission(projectRoot, plan) {
|
|
|
50232
50337
|
}
|
|
50233
50338
|
if (added.length === 0) return added;
|
|
50234
50339
|
policy.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
50235
|
-
const path4 =
|
|
50340
|
+
const path4 = join52(projectRoot, ".kxm", "routes.yaml");
|
|
50236
50341
|
mkdirSync32(dirname25(path4), { recursive: true });
|
|
50237
50342
|
writeFileSync28(path4, (0, import_yaml18.stringify)(policy), "utf8");
|
|
50238
50343
|
return added;
|
|
@@ -50241,7 +50346,7 @@ function writeGuideSetupFiles(files) {
|
|
|
50241
50346
|
const written = [];
|
|
50242
50347
|
const existed = [];
|
|
50243
50348
|
for (const file of files) {
|
|
50244
|
-
if (
|
|
50349
|
+
if (existsSync42(file.path)) {
|
|
50245
50350
|
existed.push(file.path);
|
|
50246
50351
|
continue;
|
|
50247
50352
|
}
|
|
@@ -50274,7 +50379,7 @@ init_types();
|
|
|
50274
50379
|
init_repo_root();
|
|
50275
50380
|
function cliSpawn(runtime, command, args, extra) {
|
|
50276
50381
|
if (runtime.io.spawnSync) return runtime.io.spawnSync(command, args);
|
|
50277
|
-
const result =
|
|
50382
|
+
const result = spawnSync11(command, [...args], {
|
|
50278
50383
|
encoding: "utf8",
|
|
50279
50384
|
windowsHide: true,
|
|
50280
50385
|
shell: process.platform === "win32",
|
|
@@ -50312,7 +50417,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
50312
50417
|
detail: `release v${notice.latest} has no sha256 digest for ${name}; refusing to install`
|
|
50313
50418
|
};
|
|
50314
50419
|
}
|
|
50315
|
-
const releaseDir = mkdtempSync3(
|
|
50420
|
+
const releaseDir = mkdtempSync3(join53(tmpdir2(), "kxm-pkg-update-"));
|
|
50316
50421
|
try {
|
|
50317
50422
|
const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset);
|
|
50318
50423
|
if (runtime.dryRun) {
|
|
@@ -50321,7 +50426,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
50321
50426
|
for (const step of planned) {
|
|
50322
50427
|
if (step.kind === "verify") {
|
|
50323
50428
|
if (!verifyReleaseAssetDigest(step.path, step.sha256)) {
|
|
50324
|
-
const actual =
|
|
50429
|
+
const actual = existsSync43(step.path) ? createHash17("sha256").update(readFileSync40(step.path)).digest("hex") : "missing";
|
|
50325
50430
|
return {
|
|
50326
50431
|
ok: false,
|
|
50327
50432
|
error: "release_digest_mismatch",
|
|
@@ -50599,7 +50704,7 @@ async function cmdValidate(runtime, fileFlag) {
|
|
|
50599
50704
|
}
|
|
50600
50705
|
const selectedFile = explicitFile || configuredFile;
|
|
50601
50706
|
const file = selectedFile ? resolve33(runtime.cwd, selectedFile) : void 0;
|
|
50602
|
-
if (file && !
|
|
50707
|
+
if (file && !existsSync43(file)) {
|
|
50603
50708
|
printWorker(runtime, worker, { ok: false, command: "validate", error: "file_not_found", file }, `workflow file not found: ${file}`);
|
|
50604
50709
|
return 1;
|
|
50605
50710
|
}
|
|
@@ -50699,7 +50804,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
50699
50804
|
print(runtime.io, runtime.json, { ok: false, command: "improve", error: "config_invalid", detail: message }, `config_invalid: ${message}`);
|
|
50700
50805
|
return 1;
|
|
50701
50806
|
}
|
|
50702
|
-
const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) :
|
|
50807
|
+
const candidatesDir = options.outDir ? resolve33(runtime.cwd, options.outDir) : join53(root, ".kxm", "candidates");
|
|
50703
50808
|
const report2 = buildImprovementReport(loaded.records, {
|
|
50704
50809
|
candidatesDir,
|
|
50705
50810
|
projectRoot: root,
|
|
@@ -50708,7 +50813,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
50708
50813
|
autoThreshold: config.improvement.autoThreshold,
|
|
50709
50814
|
halfLifeDays: config.improvement.telemetryHalfLifeDays
|
|
50710
50815
|
});
|
|
50711
|
-
const reportDir =
|
|
50816
|
+
const reportDir = join53(runtime.dirs.assets, "improvements");
|
|
50712
50817
|
const reportPath = writeImprovementReport(reportDir, report2, runtime.dryRun);
|
|
50713
50818
|
const text = [
|
|
50714
50819
|
"Sources:",
|
|
@@ -50852,7 +50957,7 @@ async function maybeOfferCompletionInstall(runtime) {
|
|
|
50852
50957
|
if (!pathNeeded) {
|
|
50853
50958
|
const scriptPath = completionScriptPath(shell, { env: runtime.env, configDir: runtime.env.KXM_USER_CONFIG_DIR });
|
|
50854
50959
|
const { rcFile } = completionRcTarget(shell, { env: runtime.env });
|
|
50855
|
-
if (rcFile &&
|
|
50960
|
+
if (rcFile && existsSync43(rcFile)) {
|
|
50856
50961
|
try {
|
|
50857
50962
|
if (readFileSync40(rcFile, "utf8").includes(scriptPath)) return;
|
|
50858
50963
|
} catch {
|
|
@@ -51017,7 +51122,7 @@ async function cmdRoutingReport(runtime, options) {
|
|
|
51017
51122
|
let catalog;
|
|
51018
51123
|
if (includeEquivalentListCost) {
|
|
51019
51124
|
try {
|
|
51020
|
-
const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) :
|
|
51125
|
+
const pricesPath = options.prices ? resolve33(runtime.cwd, options.prices) : join53(runtime.dirs.workspace, "prices.yaml");
|
|
51021
51126
|
catalog = loadPriceCatalog(pricesPath);
|
|
51022
51127
|
} catch {
|
|
51023
51128
|
}
|
|
@@ -51131,6 +51236,13 @@ var DRY_RUN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
51131
51236
|
"lane drop",
|
|
51132
51237
|
"lane run",
|
|
51133
51238
|
"land",
|
|
51239
|
+
"assign run",
|
|
51240
|
+
"assign witness",
|
|
51241
|
+
"assign plan-current",
|
|
51242
|
+
"assign attribute",
|
|
51243
|
+
"assign observe-cost",
|
|
51244
|
+
"assign accept",
|
|
51245
|
+
"assign change-report",
|
|
51134
51246
|
"plugin install",
|
|
51135
51247
|
"plugin",
|
|
51136
51248
|
"runs status",
|
|
@@ -51439,6 +51551,47 @@ function createProgram(ctx, result) {
|
|
|
51439
51551
|
...options.bodyFile !== void 0 ? { bodyFile: options.bodyFile } : {}
|
|
51440
51552
|
});
|
|
51441
51553
|
});
|
|
51554
|
+
const assignCmd = addGlobalOptions(program2.command("assign").description("Run this repository's developer assignment runner"));
|
|
51555
|
+
assignCmd.helpCommand("help", "Show assign help");
|
|
51556
|
+
addGlobalOptions(assignCmd.command("run").description("Dispatch a bound assignment manifest")).requiredOption("--manifest <path>", "Absolute path to the assignment manifest").action(async function assignRunAction(options) {
|
|
51557
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "run", { manifest: options.manifest });
|
|
51558
|
+
});
|
|
51559
|
+
addGlobalOptions(assignCmd.command("witness").description("Run the fixed verification witness for an existing assignment")).requiredOption("--record-dir <path>", "Absolute path to the assignment record directory").action(async function assignWitnessAction(options) {
|
|
51560
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "witness", { recordDir: options.recordDir });
|
|
51561
|
+
});
|
|
51562
|
+
addGlobalOptions(assignCmd.command("plan-current").description("Stamp or advance the current-plan pointer")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--plan <path>", "Absolute path to the plan file").requiredOption("--sha256 <hex>", "SHA-256 of the plan file").requiredOption("--base-commit <sha>", "Base commit the pointer records").requiredOption("--expected-generation <n>", "Generation the pointer must currently have").action(async function assignPlanCurrentAction(options) {
|
|
51563
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "plan-current", {
|
|
51564
|
+
taskDir: options.taskDir,
|
|
51565
|
+
plan: options.plan,
|
|
51566
|
+
sha256: options.sha256,
|
|
51567
|
+
baseCommit: options.baseCommit,
|
|
51568
|
+
expectedGeneration: options.expectedGeneration
|
|
51569
|
+
});
|
|
51570
|
+
});
|
|
51571
|
+
addGlobalOptions(assignCmd.command("attribute").description("Attach a private attribution note")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--record-dir <path>", "Absolute path to the assignment record directory").requiredOption("--class <class>", "orchestration, model, environment, or unclassified").requiredOption("--explanation-file <path>", "Absolute path to the note file").action(async function assignAttributeAction(options) {
|
|
51572
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "attribute", {
|
|
51573
|
+
taskDir: options.taskDir,
|
|
51574
|
+
recordDir: options.recordDir,
|
|
51575
|
+
classification: options.class,
|
|
51576
|
+
explanationFile: options.explanationFile
|
|
51577
|
+
});
|
|
51578
|
+
});
|
|
51579
|
+
addGlobalOptions(assignCmd.command("observe-cost").description("Import one historical cost observation as cost-only")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--input <path>", "Absolute path to the observation file").action(async function assignObserveCostAction(options) {
|
|
51580
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "observe-cost", { taskDir: options.taskDir, input: options.input });
|
|
51581
|
+
});
|
|
51582
|
+
addGlobalOptions(assignCmd.command("accept").description("Bind an exact witnessed commit and two critic PASS records")).requiredOption("--task-dir <path>", "Absolute path to the task directory").requiredOption("--commit <sha>", "Commit to accept").requiredOption("--record-dir <path>", "Absolute path to the writer record directory").requiredOption("--critic <path>", "Absolute path to a critic record directory; pass twice", (value, previous) => previous.concat(value), []).option("--observed-pr <id>", "Observed pull request id").option("--observed-ci <id>", "Observed CI run id").action(async function assignAcceptAction(options) {
|
|
51583
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "accept", {
|
|
51584
|
+
taskDir: options.taskDir,
|
|
51585
|
+
commit: options.commit,
|
|
51586
|
+
recordDir: options.recordDir,
|
|
51587
|
+
critics: options.critic,
|
|
51588
|
+
...options.observedPr !== void 0 ? { observedPr: options.observedPr } : {},
|
|
51589
|
+
...options.observedCi !== void 0 ? { observedCi: options.observedCi } : {}
|
|
51590
|
+
});
|
|
51591
|
+
});
|
|
51592
|
+
addGlobalOptions(assignCmd.command("change-report").description("Report attempts, rework, costs, and retained verification history")).requiredOption("--task-dir <path>", "Absolute path to the task directory").action(async function assignChangeReportAction(options) {
|
|
51593
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "change-report", { taskDir: options.taskDir });
|
|
51594
|
+
});
|
|
51442
51595
|
addGlobalOptions(program2.command("run").description("Create a KXM run without executing steps; follow its prerequisites, then kxm runs drive <runId> --wait").argument("[workflow]", "Workflow id to run").argument("[prompt...]", "Run prompt (events keep its hash; the full text is kept in a local 0600 sidecar file)").option("--brief <file>", "Read the run prompt from a file instead of the positional prompt").option("--lane <unit>", "Discover the project from this lane's worktree").action(async function runAction(workflow2, promptParts, options) {
|
|
51443
51596
|
result.code = await cmdKxmRunCli(runtimeFrom(ctx, this), workflow2, promptParts, options);
|
|
51444
51597
|
}));
|