@brainervirus/workit-cursor 8.28.0 → 8.29.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/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +20 -2
- package/dist/mcp-server.js +109 -8
- package/dist/workit-hook.js +20 -1
- 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
|
|
@@ -14806,9 +14811,22 @@ function detectedChecks(root) {
|
|
|
14806
14811
|
add(plain("test", ["make", "test"]));
|
|
14807
14812
|
return checks;
|
|
14808
14813
|
}
|
|
14814
|
+
function configFileFor(root) {
|
|
14815
|
+
const own = checksConfigFile(root);
|
|
14816
|
+
if (fs13.existsSync(own))
|
|
14817
|
+
return own;
|
|
14818
|
+
const common = git4(root, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
14819
|
+
if (!common || path18.basename(common) !== ".git")
|
|
14820
|
+
return own;
|
|
14821
|
+
const main = path18.dirname(common);
|
|
14822
|
+
if (path18.resolve(main) === path18.resolve(root))
|
|
14823
|
+
return own;
|
|
14824
|
+
const shared = checksConfigFile(main);
|
|
14825
|
+
return fs13.existsSync(shared) ? shared : own;
|
|
14826
|
+
}
|
|
14809
14827
|
function loadCheckConfig(cwd) {
|
|
14810
14828
|
const root = checkRoot(cwd);
|
|
14811
|
-
const file =
|
|
14829
|
+
const file = configFileFor(root);
|
|
14812
14830
|
const legacy = path18.basename(file) === LEGACY_CHECKS_FILE;
|
|
14813
14831
|
const label = legacy ? LEGACY_CHECKS_FILE : CHECKS_FILE;
|
|
14814
14832
|
const note = legacy ? {
|
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";
|
|
@@ -21557,9 +21645,22 @@ function detectedChecks(root) {
|
|
|
21557
21645
|
return checks;
|
|
21558
21646
|
}
|
|
21559
21647
|
var GATES = ["testing", "verification"];
|
|
21648
|
+
function configFileFor(root) {
|
|
21649
|
+
const own = checksConfigFile(root);
|
|
21650
|
+
if (fs11.existsSync(own))
|
|
21651
|
+
return own;
|
|
21652
|
+
const common = git3(root, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
21653
|
+
if (!common || path13.basename(common) !== ".git")
|
|
21654
|
+
return own;
|
|
21655
|
+
const main = path13.dirname(common);
|
|
21656
|
+
if (path13.resolve(main) === path13.resolve(root))
|
|
21657
|
+
return own;
|
|
21658
|
+
const shared = checksConfigFile(main);
|
|
21659
|
+
return fs11.existsSync(shared) ? shared : own;
|
|
21660
|
+
}
|
|
21560
21661
|
function loadCheckConfig(cwd) {
|
|
21561
21662
|
const root = checkRoot(cwd);
|
|
21562
|
-
const file =
|
|
21663
|
+
const file = configFileFor(root);
|
|
21563
21664
|
const legacy = path13.basename(file) === LEGACY_CHECKS_FILE;
|
|
21564
21665
|
const label = legacy ? LEGACY_CHECKS_FILE : CHECKS_FILE;
|
|
21565
21666
|
const note = legacy ? {
|
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);
|
|
@@ -14847,9 +14853,22 @@ function detectedChecks(root) {
|
|
|
14847
14853
|
return checks;
|
|
14848
14854
|
}
|
|
14849
14855
|
var GATES = ["testing", "verification"];
|
|
14856
|
+
function configFileFor(root) {
|
|
14857
|
+
const own = checksConfigFile(root);
|
|
14858
|
+
if (fs13.existsSync(own))
|
|
14859
|
+
return own;
|
|
14860
|
+
const common = git4(root, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
14861
|
+
if (!common || path18.basename(common) !== ".git")
|
|
14862
|
+
return own;
|
|
14863
|
+
const main = path18.dirname(common);
|
|
14864
|
+
if (path18.resolve(main) === path18.resolve(root))
|
|
14865
|
+
return own;
|
|
14866
|
+
const shared = checksConfigFile(main);
|
|
14867
|
+
return fs13.existsSync(shared) ? shared : own;
|
|
14868
|
+
}
|
|
14850
14869
|
function loadCheckConfig(cwd) {
|
|
14851
14870
|
const root = checkRoot(cwd);
|
|
14852
|
-
const file =
|
|
14871
|
+
const file = configFileFor(root);
|
|
14853
14872
|
const legacy = path18.basename(file) === LEGACY_CHECKS_FILE;
|
|
14854
14873
|
const label = legacy ? LEGACY_CHECKS_FILE : CHECKS_FILE;
|
|
14855
14874
|
const note = legacy ? {
|
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.
|
|
3
|
+
"version": "8.29.0",
|
|
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.
|
|
50
|
-
"@brainervirus/workit-mcp": "^8.
|
|
49
|
+
"@brainervirus/workit-core": "^8.29.0",
|
|
50
|
+
"@brainervirus/workit-mcp": "^8.29.0"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=24"
|