@kontextmind/kxm 0.6.0 → 0.7.0
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/agents/coordinator.yaml +9 -0
- package/.kxm/agents/critic-arch.yaml +13 -0
- package/.kxm/agents/critic-cli.yaml +13 -0
- package/.kxm/agents/implementer.yaml +13 -0
- package/.kxm/gates.yaml +8 -0
- package/.kxm/producers.yaml +22 -0
- package/.kxm/project.yaml +15 -0
- package/.kxm/roles/writer.yaml +5 -0
- package/.kxm/workflows/default.yaml +47 -0
- package/CHANGELOG.md +39 -7
- package/README.md +1 -0
- package/docs/README.md +2 -0
- package/docs/agent-skills.md +118 -0
- package/docs/architecture.md +1 -1
- package/docs/assignment-runner.md +21 -8
- package/docs/configuration.md +2 -2
- package/docs/kxm-handbook.md +3 -3
- package/docs/operator-pi-packages.md +63 -0
- package/docs/skills/repo-work-delivery.md +102 -0
- package/docs/test-matrix.md +4 -3
- package/docs/troubleshooting.md +19 -0
- package/docs/vnext/validation.md +9 -0
- package/docs/webhook-workflows.md +2 -2
- package/examples/README.md +1 -1
- package/package.json +16 -17
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/README.md +1 -1
- package/plugins/kxm/dist/cli.js +6875 -3672
- package/plugins/kxm/dist/core.js +214 -34
- package/plugins/kxm/dist/extension.js +7721 -85
- package/plugins/kxm/dist/mcp-server.js +75 -21
- package/plugins/kxm/dist/runtime.js +5403 -1014
- package/plugins/kxm/dist/server.js +3008 -2268
- package/plugins/kxm/dist/vnext-runtime-supervisor.js +5751 -631
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/SUITE.md +5 -0
- package/plugins/kxm/skills/hints.json +73 -0
- package/plugins/kxm/skills/kxm/SKILL.md +30 -83
- package/plugins/kxm/skills/kxm-context-memory/SKILL.md +69 -0
- package/plugins/kxm/skills/kxm-definitions/SKILL.md +65 -0
- package/plugins/kxm/skills/kxm-harness-auth/SKILL.md +34 -0
- package/plugins/kxm/skills/kxm-harvest/SKILL.md +48 -0
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +34 -0
- package/plugins/kxm/skills/kxm-insights/SKILL.md +48 -0
- package/plugins/kxm/skills/kxm-mind/SKILL.md +59 -0
- package/plugins/kxm/skills/kxm-peer/SKILL.md +110 -0
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +35 -0
- package/plugins/kxm/skills/kxm-projects/SKILL.md +43 -0
- package/plugins/kxm/skills/kxm-protocol/SKILL.md +66 -0
- package/plugins/kxm/skills/kxm-query/SKILL.md +45 -0
- package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +30 -0
- package/plugins/kxm/skills/kxm-runs/SKILL.md +29 -0
- package/plugins/kxm/skills/kxm-setup/SKILL.md +55 -0
- package/plugins/kxm/skills/kxm-skill-lifecycle/SKILL.md +31 -0
- package/plugins/kxm/skills/kxm-tasks/SKILL.md +33 -0
- package/plugins/kxm/skills/kxm-triage/SKILL.md +47 -0
- package/plugins/kxm/skills/kxm-work/SKILL.md +44 -0
- package/plugins/kxm/skills/kxm-workflow/SKILL.md +45 -0
- package/plugins/kxm/src/autocomplete.ts +9 -3
- package/plugins/kxm/src/cli.ts +1077 -11
- package/plugins/kxm/src/commands.ts +150 -8
- package/plugins/kxm/src/config.ts +7 -4
- package/plugins/kxm/src/context-packet.ts +172 -0
- package/plugins/kxm/src/extension.ts +36 -1
- package/plugins/kxm/src/external-effects.ts +356 -7
- package/plugins/kxm/src/hub.ts +2 -4
- package/plugins/kxm/src/improve.ts +72 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/model-inventory.ts +127 -0
- package/plugins/kxm/src/policy-draft.d.mts +55 -0
- package/plugins/kxm/src/policy-draft.mjs +565 -0
- package/plugins/kxm/src/price-calc.ts +17 -18
- package/plugins/kxm/src/prices.ts +32 -16
- package/plugins/kxm/src/producers.ts +71 -0
- package/plugins/kxm/src/restricted-yaml.d.mts +31 -0
- package/plugins/kxm/src/restricted-yaml.mjs +145 -0
- package/plugins/kxm/src/role.ts +375 -0
- package/plugins/kxm/src/routing.ts +99 -1
- package/plugins/kxm/src/session-work.ts +9 -2
- package/plugins/kxm/src/studio-layout.ts +660 -17
- package/plugins/kxm/src/suggest.ts +7 -13
- package/plugins/kxm/src/telemetry.ts +82 -0
- package/plugins/kxm/src/tui.ts +140 -0
- package/plugins/kxm/src/vnext-config.ts +15 -110
- package/plugins/kxm/src/vnext-engine.ts +198 -62
- package/plugins/kxm/src/vnext-harness.ts +263 -81
- package/plugins/kxm/src/vnext-oneshot-evidence.ts +85 -0
- package/plugins/kxm/src/vnext-oneshot-process.ts +149 -0
- package/plugins/kxm/src/vnext-oneshot-producer.ts +170 -233
- package/plugins/kxm/src/vnext-runtime-store.ts +35 -1
- package/plugins/kxm/src/vnext-runtime-supervisor.ts +120 -5
- package/plugins/kxm/src/vnext-runtime.ts +14 -0
- package/plugins/kxm/src/workflow-manager.ts +392 -0
- package/plugins/kxm/src/workflow-tui.ts +255 -0
- package/schemas/policy-draft/README.md +17 -0
- package/schemas/policy-draft/model.v2.schema.json +140 -0
- package/schemas/policy-draft/role.v2.schema.json +91 -0
- package/schemas/vnext/role.schema.json +76 -0
- package/schemas/vnext/run-event.schema.json +1 -0
- package/scripts/assignment-run.d.mts +1 -1
- package/scripts/assignment-run.mjs +44 -35
- package/scripts/check-generated.mjs +33 -9
- package/scripts/emit-codex-artifacts.mjs +255 -11
- package/scripts/harness-run.d.mts +12 -4
- package/scripts/harness-run.mjs +65 -17
- package/scripts/kxm-hub.mjs +6 -0
- package/scripts/native-critic.d.mts +5 -0
- package/scripts/native-critic.mjs +60 -0
- package/.kxm/config/README.md +0 -5
- package/.kxm/config/agents.json +0 -43
- package/.kxm/config/env.example +0 -56
- package/.kxm/config/update.example.yaml +0 -9
- package/.kxm/config/workflows/fix.json +0 -160
- package/.kxm/config/workflows/jira-development.json +0 -116
- package/.kxm/config/workflows/provenance-quorum.json +0 -150
- package/.kxm/config/workflows/v04-dogfood.json +0 -72
|
@@ -2984,7 +2984,7 @@ var require_compile = __commonJS({
|
|
|
2984
2984
|
const schOrFunc = root.refs[ref];
|
|
2985
2985
|
if (schOrFunc)
|
|
2986
2986
|
return schOrFunc;
|
|
2987
|
-
let _sch =
|
|
2987
|
+
let _sch = resolve2.call(this, root, ref);
|
|
2988
2988
|
if (_sch === void 0) {
|
|
2989
2989
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
2990
2990
|
const { schemaId } = this.opts;
|
|
@@ -3011,7 +3011,7 @@ var require_compile = __commonJS({
|
|
|
3011
3011
|
function sameSchemaEnv(s1, s2) {
|
|
3012
3012
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3013
3013
|
}
|
|
3014
|
-
function
|
|
3014
|
+
function resolve2(root, ref) {
|
|
3015
3015
|
let sch;
|
|
3016
3016
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3017
3017
|
ref = sch;
|
|
@@ -3836,7 +3836,7 @@ var require_fast_uri = __commonJS({
|
|
|
3836
3836
|
}
|
|
3837
3837
|
return uri;
|
|
3838
3838
|
}
|
|
3839
|
-
function
|
|
3839
|
+
function resolve2(baseURI, relativeURI, options) {
|
|
3840
3840
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3841
3841
|
const {
|
|
3842
3842
|
parsed: baseParsed,
|
|
@@ -4198,7 +4198,7 @@ var require_fast_uri = __commonJS({
|
|
|
4198
4198
|
var fastUri = {
|
|
4199
4199
|
SCHEMES,
|
|
4200
4200
|
normalize,
|
|
4201
|
-
resolve,
|
|
4201
|
+
resolve: resolve2,
|
|
4202
4202
|
resolveComponent,
|
|
4203
4203
|
equal,
|
|
4204
4204
|
serialize,
|
|
@@ -14508,7 +14508,7 @@ var Protocol = class {
|
|
|
14508
14508
|
return;
|
|
14509
14509
|
}
|
|
14510
14510
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
14511
|
-
await new Promise((
|
|
14511
|
+
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
14512
14512
|
options?.signal?.throwIfAborted();
|
|
14513
14513
|
}
|
|
14514
14514
|
} catch (error2) {
|
|
@@ -14525,7 +14525,7 @@ var Protocol = class {
|
|
|
14525
14525
|
*/
|
|
14526
14526
|
request(request, resultSchema, options) {
|
|
14527
14527
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
14528
|
-
return new Promise((
|
|
14528
|
+
return new Promise((resolve2, reject) => {
|
|
14529
14529
|
const earlyReject = (error2) => {
|
|
14530
14530
|
reject(error2);
|
|
14531
14531
|
};
|
|
@@ -14603,7 +14603,7 @@ var Protocol = class {
|
|
|
14603
14603
|
if (!parseResult.success) {
|
|
14604
14604
|
reject(parseResult.error);
|
|
14605
14605
|
} else {
|
|
14606
|
-
|
|
14606
|
+
resolve2(parseResult.data);
|
|
14607
14607
|
}
|
|
14608
14608
|
} catch (error2) {
|
|
14609
14609
|
reject(error2);
|
|
@@ -14864,12 +14864,12 @@ var Protocol = class {
|
|
|
14864
14864
|
}
|
|
14865
14865
|
} catch {
|
|
14866
14866
|
}
|
|
14867
|
-
return new Promise((
|
|
14867
|
+
return new Promise((resolve2, reject) => {
|
|
14868
14868
|
if (signal.aborted) {
|
|
14869
14869
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
14870
14870
|
return;
|
|
14871
14871
|
}
|
|
14872
|
-
const timeoutId = setTimeout(
|
|
14872
|
+
const timeoutId = setTimeout(resolve2, interval);
|
|
14873
14873
|
signal.addEventListener("abort", () => {
|
|
14874
14874
|
clearTimeout(timeoutId);
|
|
14875
14875
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -15745,12 +15745,12 @@ var StdioServerTransport = class {
|
|
|
15745
15745
|
this.onclose?.();
|
|
15746
15746
|
}
|
|
15747
15747
|
send(message) {
|
|
15748
|
-
return new Promise((
|
|
15748
|
+
return new Promise((resolve2) => {
|
|
15749
15749
|
const json = serializeMessage(message);
|
|
15750
15750
|
if (this._stdout.write(json)) {
|
|
15751
|
-
|
|
15751
|
+
resolve2();
|
|
15752
15752
|
} else {
|
|
15753
|
-
this._stdout.once("drain",
|
|
15753
|
+
this._stdout.once("drain", resolve2);
|
|
15754
15754
|
}
|
|
15755
15755
|
});
|
|
15756
15756
|
}
|
|
@@ -16025,7 +16025,7 @@ var HubClient = class {
|
|
|
16025
16025
|
if (signal?.aborted) throw new MeshWaitError("aborted", messageId);
|
|
16026
16026
|
const message = await this.getMessage(messageId);
|
|
16027
16027
|
if (["replied", "cancelled", "expired", "error"].includes(message.status)) return message;
|
|
16028
|
-
await new Promise((
|
|
16028
|
+
await new Promise((resolve2, reject) => {
|
|
16029
16029
|
const onAbort = () => {
|
|
16030
16030
|
signal?.removeEventListener("abort", onAbort);
|
|
16031
16031
|
clearTimeout(timer);
|
|
@@ -16033,7 +16033,7 @@ var HubClient = class {
|
|
|
16033
16033
|
};
|
|
16034
16034
|
const timer = setTimeout(() => {
|
|
16035
16035
|
signal?.removeEventListener("abort", onAbort);
|
|
16036
|
-
|
|
16036
|
+
resolve2();
|
|
16037
16037
|
}, Math.min(500, Math.max(1, deadline - Date.now())));
|
|
16038
16038
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
16039
16039
|
if (signal?.aborted) onAbort();
|
|
@@ -16088,7 +16088,7 @@ var HubClient = class {
|
|
|
16088
16088
|
} catch (error2) {
|
|
16089
16089
|
if (this.stopped || error2 instanceof Error && error2.name === "AbortError") return;
|
|
16090
16090
|
}
|
|
16091
|
-
if (!this.stopped) await new Promise((
|
|
16091
|
+
if (!this.stopped) await new Promise((resolve2) => setTimeout(resolve2, this.options.reconnectMs));
|
|
16092
16092
|
}
|
|
16093
16093
|
}
|
|
16094
16094
|
headers(includeIdentity = true) {
|
|
@@ -16170,6 +16170,9 @@ var HubClient = class {
|
|
|
16170
16170
|
};
|
|
16171
16171
|
|
|
16172
16172
|
// plugins/kxm/src/commands.ts
|
|
16173
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
16174
|
+
import { homedir } from "node:os";
|
|
16175
|
+
import { dirname, join, resolve } from "node:path";
|
|
16173
16176
|
function requiredString(value, name) {
|
|
16174
16177
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`${name} is required`);
|
|
16175
16178
|
return value.trim();
|
|
@@ -16890,6 +16893,12 @@ function parseSessionToken(token) {
|
|
|
16890
16893
|
const raw = Buffer.from(token.trim(), "base64url").toString("utf8");
|
|
16891
16894
|
const parsed = JSON.parse(raw);
|
|
16892
16895
|
if (parsed && typeof parsed === "object" && parsed.schema === "kxm.session-token.v1" && typeof parsed.sessionId === "string") {
|
|
16896
|
+
if (parsed.expiresAt) {
|
|
16897
|
+
const expiryTime = new Date(parsed.expiresAt).getTime();
|
|
16898
|
+
if (!Number.isNaN(expiryTime) && Date.now() >= expiryTime) {
|
|
16899
|
+
return void 0;
|
|
16900
|
+
}
|
|
16901
|
+
}
|
|
16893
16902
|
return parsed;
|
|
16894
16903
|
}
|
|
16895
16904
|
} catch {
|
|
@@ -16897,6 +16906,13 @@ function parseSessionToken(token) {
|
|
|
16897
16906
|
}
|
|
16898
16907
|
return void 0;
|
|
16899
16908
|
}
|
|
16909
|
+
function resolveUserConfigDirectory(overrideDir) {
|
|
16910
|
+
if (overrideDir) return resolve(overrideDir);
|
|
16911
|
+
return resolve(process.env.KXM_USER_CONFIG_DIR?.trim() || join(homedir(), ".config", "kxm"));
|
|
16912
|
+
}
|
|
16913
|
+
function sessionTokenPath(userConfigDir) {
|
|
16914
|
+
return join(resolveUserConfigDirectory(userConfigDir), "session.token");
|
|
16915
|
+
}
|
|
16900
16916
|
function matchToolPattern(pattern, toolName) {
|
|
16901
16917
|
if (pattern === "*" || pattern === toolName) return true;
|
|
16902
16918
|
if (pattern.endsWith("*")) {
|
|
@@ -16939,7 +16955,7 @@ function isToolAllowed(commandName, policy) {
|
|
|
16939
16955
|
}
|
|
16940
16956
|
return true;
|
|
16941
16957
|
}
|
|
16942
|
-
function enforceToolPolicy(commandName, env = process.env) {
|
|
16958
|
+
function enforceToolPolicy(commandName, env = process.env, options) {
|
|
16943
16959
|
const attemptTokenRaw = env.KXM_ATTEMPT_TOKEN?.trim();
|
|
16944
16960
|
if (attemptTokenRaw) {
|
|
16945
16961
|
const attempt = parseAttemptToken(attemptTokenRaw);
|
|
@@ -16953,13 +16969,51 @@ function enforceToolPolicy(commandName, env = process.env) {
|
|
|
16953
16969
|
detail: `command ${commandName} is denied by attempt tool policy`
|
|
16954
16970
|
};
|
|
16955
16971
|
}
|
|
16972
|
+
if (commandName === "kxm_promote" || commandName === "promote") {
|
|
16973
|
+
const explicitAllow = attempt.toolPolicy?.allow ?? attempt.toolPolicy?.allowedTools;
|
|
16974
|
+
if (!Array.isArray(explicitAllow) || !explicitAllow.includes("kxm_promote") && !explicitAllow.includes("promote") && !explicitAllow.includes("*")) {
|
|
16975
|
+
return {
|
|
16976
|
+
allowed: false,
|
|
16977
|
+
error: "attempt_token_admin_denied",
|
|
16978
|
+
detail: "AttemptToken worker cannot perform operator state promotion without explicit policy grant"
|
|
16979
|
+
};
|
|
16980
|
+
}
|
|
16981
|
+
}
|
|
16982
|
+
if (options?.runId && attempt.runId && options.runId !== attempt.runId) {
|
|
16983
|
+
return {
|
|
16984
|
+
allowed: false,
|
|
16985
|
+
error: "attempt_token_scope_violation",
|
|
16986
|
+
detail: `attempt token runId ${attempt.runId} does not match request runId ${options.runId}`
|
|
16987
|
+
};
|
|
16988
|
+
}
|
|
16956
16989
|
return { allowed: true };
|
|
16957
16990
|
}
|
|
16958
|
-
const
|
|
16959
|
-
if (
|
|
16960
|
-
const session = parseSessionToken(
|
|
16991
|
+
const envSessionRaw = env.KXM_SESSION_TOKEN?.trim();
|
|
16992
|
+
if (envSessionRaw) {
|
|
16993
|
+
const session = parseSessionToken(envSessionRaw);
|
|
16994
|
+
if (!session) {
|
|
16995
|
+
return { allowed: false, error: "session_token_invalid", detail: "KXM_SESSION_TOKEN is malformed or expired" };
|
|
16996
|
+
}
|
|
16997
|
+
if (!isToolAllowed(commandName, session.toolPolicy)) {
|
|
16998
|
+
return {
|
|
16999
|
+
allowed: false,
|
|
17000
|
+
error: "tool_policy_denied",
|
|
17001
|
+
detail: `command ${commandName} is denied by session tool policy`
|
|
17002
|
+
};
|
|
17003
|
+
}
|
|
17004
|
+
return { allowed: true };
|
|
17005
|
+
}
|
|
17006
|
+
const tokenFile = sessionTokenPath(env.KXM_USER_CONFIG_DIR);
|
|
17007
|
+
if (existsSync(tokenFile)) {
|
|
17008
|
+
let tokenRaw;
|
|
17009
|
+
try {
|
|
17010
|
+
tokenRaw = readFileSync(tokenFile, "utf8").trim();
|
|
17011
|
+
} catch {
|
|
17012
|
+
return { allowed: false, error: "session_token_invalid", detail: "Session token file on disk could not be read" };
|
|
17013
|
+
}
|
|
17014
|
+
const session = tokenRaw ? parseSessionToken(tokenRaw) : void 0;
|
|
16961
17015
|
if (!session) {
|
|
16962
|
-
return { allowed: false, error: "session_token_invalid", detail: "
|
|
17016
|
+
return { allowed: false, error: "session_token_invalid", detail: "Session token on disk is malformed or expired" };
|
|
16963
17017
|
}
|
|
16964
17018
|
if (!isToolAllowed(commandName, session.toolPolicy)) {
|
|
16965
17019
|
return {
|
|
@@ -16982,7 +17036,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
|
|
|
16982
17036
|
}
|
|
16983
17037
|
|
|
16984
17038
|
// plugins/kxm/src/mcp-server.ts
|
|
16985
|
-
var VERSION = "0.
|
|
17039
|
+
var VERSION = "0.7.0";
|
|
16986
17040
|
var inbox = /* @__PURE__ */ new Map();
|
|
16987
17041
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
16988
17042
|
var meshClient;
|