@brainervirus/workit-cursor 8.28.0 → 8.28.1
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/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +6 -1
- package/dist/mcp-server.js +95 -7
- package/dist/workit-hook.js +6 -0
- package/hooks/launch.mjs +30 -0
- package/package.json +3 -3
|
@@ -9739,11 +9739,15 @@ var withReleaseTracks = (workspaceRoot, policy) => {
|
|
|
9739
9739
|
source,
|
|
9740
9740
|
fingerprint
|
|
9741
9741
|
};
|
|
9742
|
+
}, rethrowRuntimeBug = (error) => {
|
|
9743
|
+
if (error instanceof TypeError || error instanceof ReferenceError)
|
|
9744
|
+
throw error;
|
|
9742
9745
|
}, validateBranchNameFor = (workspaceRoot, name) => {
|
|
9743
9746
|
try {
|
|
9744
9747
|
const resolved = branchPolicySnapshotFor(workspaceRoot);
|
|
9745
9748
|
return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
|
|
9746
9749
|
} catch (error) {
|
|
9750
|
+
rethrowRuntimeBug(error);
|
|
9747
9751
|
const correction = "repair or select a valid workspace policy before creating a branch";
|
|
9748
9752
|
return {
|
|
9749
9753
|
ok: false,
|
|
@@ -11523,7 +11527,7 @@ var str2 = (d, values) => ({
|
|
|
11523
11527
|
description: typeof description === "string" ? description : "",
|
|
11524
11528
|
paths: ["."],
|
|
11525
11529
|
exclusions: []
|
|
11526
|
-
}), LISTS, ENVELOPE;
|
|
11530
|
+
}), LISTS, ENVELOPE, NOT_FLAT;
|
|
11527
11531
|
var init_operation_input = __esm(() => {
|
|
11528
11532
|
init_task_contract();
|
|
11529
11533
|
scopeFields = {
|
|
@@ -11645,6 +11649,7 @@ var init_operation_input = __esm(() => {
|
|
|
11645
11649
|
"expectedWorkspaceRevision",
|
|
11646
11650
|
"judgment"
|
|
11647
11651
|
]);
|
|
11652
|
+
NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
|
|
11648
11653
|
});
|
|
11649
11654
|
|
|
11650
11655
|
// packages/workit-core/src/core/policy/judgment.ts
|
package/dist/mcp-server.js
CHANGED
|
@@ -15951,8 +15951,9 @@ function flatOperationJsonSchema(family, options = {}) {
|
|
|
15951
15951
|
};
|
|
15952
15952
|
const properties = { action: { type: "string", enum: actions } };
|
|
15953
15953
|
const readField = (name) => name === "taskId" || (family === "task" ? READ_TASK_FIELDS.has(name) : family === "policy");
|
|
15954
|
+
const taken = (name) => family === "policy" || actions.some((action) => actionKeys(family, action)?.accepted.has(name));
|
|
15954
15955
|
for (const [name, field] of Object.entries({ ...COMMON, ...spec.fields }))
|
|
15955
|
-
if (options.readOnly ? readField(name) :
|
|
15956
|
+
if (options.readOnly ? readField(name) : taken(name))
|
|
15956
15957
|
properties[name] = property(field);
|
|
15957
15958
|
return {
|
|
15958
15959
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -16194,6 +16195,98 @@ function normalizeOperationInput(family, input, host) {
|
|
|
16194
16195
|
request[key] = strings(request[key]);
|
|
16195
16196
|
return request;
|
|
16196
16197
|
}
|
|
16198
|
+
var defOf = (node) => node._zod.def;
|
|
16199
|
+
var unwrap = (node) => {
|
|
16200
|
+
let inner = node;
|
|
16201
|
+
while (["optional", "nullable"].includes(defOf(inner).type) && defOf(inner).innerType)
|
|
16202
|
+
inner = defOf(inner).innerType;
|
|
16203
|
+
return inner;
|
|
16204
|
+
};
|
|
16205
|
+
var FLAT_NAME = {
|
|
16206
|
+
authorityRefs: "refs",
|
|
16207
|
+
contentRefs: "refs",
|
|
16208
|
+
statedChoice: "choice",
|
|
16209
|
+
reviewContext: "reviewSession"
|
|
16210
|
+
};
|
|
16211
|
+
var NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
|
|
16212
|
+
function actionKeys(family, action) {
|
|
16213
|
+
const options = advertisedOperationSchemas[family].options;
|
|
16214
|
+
const option = options.find((item) => {
|
|
16215
|
+
const literal = defOf(item).shape?.action;
|
|
16216
|
+
return literal._zod.def.values.includes(action);
|
|
16217
|
+
});
|
|
16218
|
+
if (!option)
|
|
16219
|
+
return null;
|
|
16220
|
+
const out = { accepted: new Set, required: [] };
|
|
16221
|
+
const walk = (shape, nested) => {
|
|
16222
|
+
for (const [key, node] of Object.entries(shape)) {
|
|
16223
|
+
if (NOT_FLAT.has(key) || nested && key === "taskId")
|
|
16224
|
+
continue;
|
|
16225
|
+
const inner = unwrap(node);
|
|
16226
|
+
const type = defOf(inner).type;
|
|
16227
|
+
const needed = !["optional", "nullable"].includes(defOf(node).type);
|
|
16228
|
+
if (key === "scope")
|
|
16229
|
+
for (const name of ["scope", "paths", "exclusions"])
|
|
16230
|
+
out.accepted.add(name);
|
|
16231
|
+
else if (type === "object" && key !== "bundle" && !(key in FLAT_NAME)) {
|
|
16232
|
+
out.accepted.add(key);
|
|
16233
|
+
walk(defOf(inner).shape, true);
|
|
16234
|
+
} else {
|
|
16235
|
+
const name = FLAT_NAME[key] ?? key;
|
|
16236
|
+
out.accepted.add(name);
|
|
16237
|
+
if (needed && type !== "array" && type !== "record" && !out.required.includes(name))
|
|
16238
|
+
out.required.push(name);
|
|
16239
|
+
}
|
|
16240
|
+
}
|
|
16241
|
+
};
|
|
16242
|
+
walk(defOf(option).shape, false);
|
|
16243
|
+
return out;
|
|
16244
|
+
}
|
|
16245
|
+
function exampleOperation(family, action) {
|
|
16246
|
+
const keys = actionKeys(family, action);
|
|
16247
|
+
const example = { action };
|
|
16248
|
+
for (const name of keys?.required ?? [])
|
|
16249
|
+
example[name] = FLAT[family].fields[name]?.enum?.[0] ?? `<${name}>`;
|
|
16250
|
+
if (family === "policy" && !keys?.required.length && action !== "explain")
|
|
16251
|
+
example.riskTier = "normal";
|
|
16252
|
+
return example;
|
|
16253
|
+
}
|
|
16254
|
+
var oneOf = (values) => values.join(" | ");
|
|
16255
|
+
function invalidOperation(family, input, error) {
|
|
16256
|
+
const request = isObject2(input) ? input : {};
|
|
16257
|
+
const action = typeof request.action === "string" ? request.action : "";
|
|
16258
|
+
const actions = OPERATION_ACTIONS[family];
|
|
16259
|
+
if (!actions.includes(action))
|
|
16260
|
+
return failure2("invalid_input", `${family}: action must be one of ${oneOf(actions)}`, {
|
|
16261
|
+
fields: [{ path: "action", reason: `got ${JSON.stringify(request.action ?? null)}` }]
|
|
16262
|
+
});
|
|
16263
|
+
const own = actionKeys(family, action);
|
|
16264
|
+
const fields = [];
|
|
16265
|
+
const sentence = [];
|
|
16266
|
+
for (const issue of error.issues) {
|
|
16267
|
+
if (issue.code === "unrecognized_keys") {
|
|
16268
|
+
for (const key of issue.keys) {
|
|
16269
|
+
const home = actions.find((other) => other !== action && actionKeys(family, other).accepted.has(key));
|
|
16270
|
+
const reason = home ? `${key} belongs to action: ${home}` : `${key} is not a field of ${family} ${action}; it takes ${[...own.accepted].join(", ")}`;
|
|
16271
|
+
fields.push({ path: key, reason });
|
|
16272
|
+
sentence.push(reason);
|
|
16273
|
+
}
|
|
16274
|
+
continue;
|
|
16275
|
+
}
|
|
16276
|
+
const last = String(issue.path.at(-1) ?? "");
|
|
16277
|
+
const name = Object.entries(FLAT_NAME).find(([contract]) => contract === last)?.[1] ?? last;
|
|
16278
|
+
const missing = issue.code === "invalid_type" && /received undefined/.test(issue.message);
|
|
16279
|
+
const absent = own.required.filter((key) => !(key in request));
|
|
16280
|
+
const needs = missing && issue.path.length === 1 && absent.length ? absent.join(", ") : name;
|
|
16281
|
+
const reason = missing ? `${family} ${action} requires ${needs}` : `${name}: ${issue.message}`;
|
|
16282
|
+
fields.push({ path: issue.path.join("."), reason });
|
|
16283
|
+
sentence.push(reason);
|
|
16284
|
+
}
|
|
16285
|
+
const example = JSON.stringify(exampleOperation(family, action));
|
|
16286
|
+
return failure2("invalid_input", `${[...new Set(sentence)].join("; ")}. Example: ${example}`, {
|
|
16287
|
+
fields
|
|
16288
|
+
});
|
|
16289
|
+
}
|
|
16197
16290
|
function parseAdvertisedOperation(family, input, host) {
|
|
16198
16291
|
const request = normalizeOperationInput(family, input, host);
|
|
16199
16292
|
if (isObject2(request) && request.schemaVersion !== SCHEMA_VERSION)
|
|
@@ -16201,12 +16294,7 @@ function parseAdvertisedOperation(family, input, host) {
|
|
|
16201
16294
|
const parsed = advertisedOperationSchemas[family].safeParse(request);
|
|
16202
16295
|
if (parsed.success)
|
|
16203
16296
|
return success(null, null, request);
|
|
16204
|
-
return
|
|
16205
|
-
fields: parsed.error.issues.map((issue) => ({
|
|
16206
|
-
path: issue.code === "unrecognized_keys" ? issue.keys.join(".") : issue.path.join("."),
|
|
16207
|
-
reason: issue.message
|
|
16208
|
-
}))
|
|
16209
|
-
});
|
|
16297
|
+
return invalidOperation(family, request, parsed.error);
|
|
16210
16298
|
}
|
|
16211
16299
|
// packages/workit-core/src/core/task-store.ts
|
|
16212
16300
|
import { createHash as createHash8, randomUUID as randomUUID3 } from "node:crypto";
|
package/dist/workit-hook.js
CHANGED
|
@@ -9728,11 +9728,16 @@ var branchPolicySnapshotFor = (workspaceRoot) => {
|
|
|
9728
9728
|
fingerprint
|
|
9729
9729
|
};
|
|
9730
9730
|
};
|
|
9731
|
+
var rethrowRuntimeBug = (error) => {
|
|
9732
|
+
if (error instanceof TypeError || error instanceof ReferenceError)
|
|
9733
|
+
throw error;
|
|
9734
|
+
};
|
|
9731
9735
|
var validateBranchNameFor = (workspaceRoot, name) => {
|
|
9732
9736
|
try {
|
|
9733
9737
|
const resolved = branchPolicySnapshotFor(workspaceRoot);
|
|
9734
9738
|
return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
|
|
9735
9739
|
} catch (error) {
|
|
9740
|
+
rethrowRuntimeBug(error);
|
|
9736
9741
|
const correction = "repair or select a valid workspace policy before creating a branch";
|
|
9737
9742
|
return {
|
|
9738
9743
|
ok: false,
|
|
@@ -11636,6 +11641,7 @@ function normalizeOperationInput(family, input, host) {
|
|
|
11636
11641
|
request[key] = strings(request[key]);
|
|
11637
11642
|
return request;
|
|
11638
11643
|
}
|
|
11644
|
+
var NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
|
|
11639
11645
|
|
|
11640
11646
|
// packages/workit-core/src/core/policy/judgment.ts
|
|
11641
11647
|
var isObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
package/hooks/launch.mjs
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
// failure, npx network error, timeout, a crash) prints `{}`, exits 0 and
|
|
16
16
|
// writes one `[workit] Cursor hook unavailable: …` line on stderr. Only a
|
|
17
17
|
// policy deny from the hook itself (exit 2 with Cursor's deny JSON) blocks.
|
|
18
|
+
import { readFileSync } from "node:fs";
|
|
18
19
|
import path from "node:path";
|
|
19
20
|
import { fileURLToPath } from "node:url";
|
|
20
21
|
import {
|
|
@@ -25,6 +26,35 @@ import {
|
|
|
25
26
|
|
|
26
27
|
const pluginRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
27
28
|
|
|
29
|
+
// A Node below this package's own engines minimum cannot run the bundled hook:
|
|
30
|
+
// fail open with one clear line. WORKIT_HOOK_NODE_VERSION stands in for
|
|
31
|
+
// process.versions.node (tests). An unreadable minimum never blocks.
|
|
32
|
+
const nodeFloorMessage = () => {
|
|
33
|
+
try {
|
|
34
|
+
const found = process.env.WORKIT_HOOK_NODE_VERSION || process.versions.node;
|
|
35
|
+
const range = JSON.parse(readFileSync(path.join(pluginRoot, "package.json"), "utf8")).engines
|
|
36
|
+
?.node;
|
|
37
|
+
const min = /^>=\s*(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(String(range ?? ""));
|
|
38
|
+
if (!min) return null;
|
|
39
|
+
const need = [min[1], min[2] ?? 0, min[3] ?? 0].map(Number);
|
|
40
|
+
const have = String(found).replace(/^v/, "").split(".").map(Number);
|
|
41
|
+
for (let i = 0; i < 3; i++) {
|
|
42
|
+
const a = have[i] ?? 0;
|
|
43
|
+
if (Number.isNaN(a)) return null;
|
|
44
|
+
if (a !== need[i]) return a < need[i] ? `needs Node ${range}, found ${found}` : null;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const tooOld = nodeFloorMessage();
|
|
52
|
+
if (tooOld && process.argv[2] !== "--probe") {
|
|
53
|
+
process.stderr.write(`[workit] Cursor hook unavailable: ${tooOld}\n`);
|
|
54
|
+
process.stdout.write("{}\n");
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
28
58
|
// `--probe <bin>` (for `workit doctor`): run one no-op preCompact through
|
|
29
59
|
// the candidate Cursor would use and print which one it was and how it went.
|
|
30
60
|
if (process.argv[2] === "--probe") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cursor",
|
|
3
|
-
"version": "8.28.
|
|
3
|
+
"version": "8.28.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Cursor plugin — shared MCP transport, native hooks, and sixteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"build": "bun scripts/build.ts"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@brainervirus/workit-core": "^8.28.
|
|
50
|
-
"@brainervirus/workit-mcp": "^8.28.
|
|
49
|
+
"@brainervirus/workit-core": "^8.28.1",
|
|
50
|
+
"@brainervirus/workit-mcp": "^8.28.1"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=24"
|