@brainervirus/workit-core 0.8.0 → 0.8.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/package.json +1 -1
- package/scripts/run-cursor-mcp.sh +1 -1
- package/src/core/doctor.ts +32 -2
- package/src/core/registration.ts +9 -7
package/package.json
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
# Launch the published package's MCP bin through npx, never a repo-relative
|
|
4
4
|
# dist or share clone; a startup/network failure surfaces via npx's nonzero exit.
|
|
5
5
|
set -euo pipefail
|
|
6
|
-
exec npx -y --package=@brainervirus/workit-cursor@
|
|
6
|
+
exec npx -y --package=@brainervirus/workit-cursor@0.8.0 workit-cursor-mcp "$@"
|
package/src/core/doctor.ts
CHANGED
|
@@ -11,7 +11,7 @@ import path from "node:path";
|
|
|
11
11
|
import { SUPPORT_MATRIX } from "./support-matrix";
|
|
12
12
|
import { EVENT } from "./boundary";
|
|
13
13
|
import { getDiagnosticLogger, isConfigObject } from "./config";
|
|
14
|
-
import { isWorkitPlugin } from "./registration";
|
|
14
|
+
import { CURSOR_RUNTIME_PACKAGE, cursorHooksEntry, isWorkitPlugin } from "./registration";
|
|
15
15
|
import { resolveWorkspaceFrom } from "./workspaces";
|
|
16
16
|
import { validateCursorSkills } from "./skill-manifests";
|
|
17
17
|
|
|
@@ -422,7 +422,7 @@ const registeredCursorLauncher = (res: Resolved): CursorLauncher | null | "inval
|
|
|
422
422
|
// CA-17: exact positional tokens — a substring match would accept
|
|
423
423
|
// `@latest-alpha` or `workit-cursor-mcp-foo`.
|
|
424
424
|
if (args[0] !== "-y") return "invalid";
|
|
425
|
-
if (args[1] !==
|
|
425
|
+
if (args[1] !== `--package=${CURSOR_RUNTIME_PACKAGE}`) return "invalid";
|
|
426
426
|
if (args[2] !== "workit-cursor-mcp") return "invalid";
|
|
427
427
|
return { kind: "npx" };
|
|
428
428
|
}
|
|
@@ -434,6 +434,26 @@ const registeredCursorLauncher = (res: Resolved): CursorLauncher | null | "inval
|
|
|
434
434
|
};
|
|
435
435
|
};
|
|
436
436
|
|
|
437
|
+
// CA-17: the canonical session-start hook runs the published package through
|
|
438
|
+
// npx as a single command string (Cursor's documented hook format). The doctor
|
|
439
|
+
// validates its shape exactly like the MCP launcher — no substring matching,
|
|
440
|
+
// no version abstraction.
|
|
441
|
+
const canonicalCursorHook = cursorHooksEntry("").command;
|
|
442
|
+
|
|
443
|
+
const registeredCursorHook = (res: Resolved): string | null | "invalid" => {
|
|
444
|
+
const hooksFile = path.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
|
|
445
|
+
if (!existsSync(hooksFile)) return "invalid";
|
|
446
|
+
const config = readJson(hooksFile);
|
|
447
|
+
// Unlike mcp.json, the hook file is not covered by checkMalformedConfig, so
|
|
448
|
+
// an unparseable hook must fail the launcher check rather than slip through.
|
|
449
|
+
if (!config) return "invalid";
|
|
450
|
+
const sessionStart = config.hooks?.sessionStart;
|
|
451
|
+
if (!Array.isArray(sessionStart) || sessionStart.length !== 1) return "invalid";
|
|
452
|
+
const entry = sessionStart[0];
|
|
453
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return "invalid";
|
|
454
|
+
return typeof entry.command === "string" ? entry.command : "invalid";
|
|
455
|
+
};
|
|
456
|
+
|
|
437
457
|
const checkLauncher = (res: Resolved): DoctorCheck => {
|
|
438
458
|
const dev = res.dev;
|
|
439
459
|
const hosts = hostsFor(res.host);
|
|
@@ -458,6 +478,16 @@ const checkLauncher = (res: Resolved): DoctorCheck => {
|
|
|
458
478
|
) {
|
|
459
479
|
missing.push(`cursor: registered ${registered.entry}`);
|
|
460
480
|
}
|
|
481
|
+
const hook = registeredCursorHook(res);
|
|
482
|
+
if (hook === "invalid") {
|
|
483
|
+
missing.push(
|
|
484
|
+
`cursor: canonical session-start hook in ${path.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")}`,
|
|
485
|
+
);
|
|
486
|
+
} else if (hook !== null && hook !== canonicalCursorHook) {
|
|
487
|
+
missing.push(
|
|
488
|
+
`cursor: canonical session-start hook in ${path.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")} (registered ${hook})`,
|
|
489
|
+
);
|
|
490
|
+
}
|
|
461
491
|
}
|
|
462
492
|
if (dev) {
|
|
463
493
|
missing.push(
|
package/src/core/registration.ts
CHANGED
|
@@ -179,6 +179,13 @@ export function mergeCursorHooks(
|
|
|
179
179
|
return { config: base, changed: ["hooks.sessionStart"] };
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Canonical reviewed pin for the Cursor npm runtime (README "Update review").
|
|
184
|
+
* The single source for every source-derived Cursor runtime selector; the
|
|
185
|
+
* committed manifests keep the literal (static data cannot import TS).
|
|
186
|
+
*/
|
|
187
|
+
export const CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@0.8.0";
|
|
188
|
+
|
|
182
189
|
/**
|
|
183
190
|
* Portable Cursor MCP server entry (CA-16/CA-17): launch the published package
|
|
184
191
|
* through npx against its npm bin, so the Marketplace plugin never depends on a
|
|
@@ -190,12 +197,7 @@ export function cursorMcpServerEntry(_packageDir: string): {
|
|
|
190
197
|
} {
|
|
191
198
|
return {
|
|
192
199
|
command: "npx",
|
|
193
|
-
args: [
|
|
194
|
-
"-y",
|
|
195
|
-
"--package=@brainervirus/workit-cursor@latest",
|
|
196
|
-
"workit-cursor-mcp",
|
|
197
|
-
"${workspaceFolder}",
|
|
198
|
-
],
|
|
200
|
+
args: ["-y", `--package=${CURSOR_RUNTIME_PACKAGE}`, "workit-cursor-mcp", "${workspaceFolder}"],
|
|
199
201
|
};
|
|
200
202
|
}
|
|
201
203
|
|
|
@@ -208,7 +210,7 @@ export function cursorHooksEntry(_packageDir: string): {
|
|
|
208
210
|
args: string[];
|
|
209
211
|
} {
|
|
210
212
|
return {
|
|
211
|
-
command:
|
|
213
|
+
command: `npx -y --package=${CURSOR_RUNTIME_PACKAGE} workit-cursor-session-start`,
|
|
212
214
|
args: [],
|
|
213
215
|
};
|
|
214
216
|
}
|