@brainervirus/workit-cli 0.8.7 → 0.8.8

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.
Files changed (2) hide show
  1. package/dist/index.js +168 -13
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -43490,7 +43490,11 @@ var checkLauncher = (res) => {
43490
43490
  detail: "no dev checkout found (WORKFLOW_TOOLKIT_DEV) — skipping non-Cursor launcher checks"
43491
43491
  };
43492
43492
  }
43493
- return { id: "launcher", status: "pass", detail: `${res.host} launcher/hook entries present` };
43493
+ return {
43494
+ id: "launcher",
43495
+ status: "pass",
43496
+ detail: `${res.host} launcher/hook entries present`
43497
+ };
43494
43498
  };
43495
43499
  var checkUtility = (res) => {
43496
43500
  const git = commandOnPath("git", res.env);
@@ -43510,7 +43514,11 @@ var checkUtility = (res) => {
43510
43514
  fix: "Install util-linux (flock)"
43511
43515
  };
43512
43516
  }
43513
- return { id: "utility", status: "pass", detail: "git (and flock where required) on PATH" };
43517
+ return {
43518
+ id: "utility",
43519
+ status: "pass",
43520
+ detail: "git (and flock where required) on PATH"
43521
+ };
43514
43522
  };
43515
43523
  var staleEntry = (entry) => {
43516
43524
  if (!entry)
@@ -43532,7 +43540,11 @@ var checkStalePin = (res) => {
43532
43540
  };
43533
43541
  }
43534
43542
  if (!existsSync7(res.opencodeConfig)) {
43535
- return { id: "stale_pin", status: "pass", detail: "no opencode config — not registered" };
43543
+ return {
43544
+ id: "stale_pin",
43545
+ status: "pass",
43546
+ detail: "no opencode config — not registered"
43547
+ };
43536
43548
  }
43537
43549
  const cfg = readJson(res.opencodeConfig);
43538
43550
  const entries = pluginEntries(cfg);
@@ -43563,6 +43575,118 @@ var checkStalePin = (res) => {
43563
43575
  }
43564
43576
  return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
43565
43577
  };
43578
+ var pluginMcpSelectors = (res) => {
43579
+ const p = path9.join(res.cursorPluginDir, "mcp.json");
43580
+ if (!existsSync7(p))
43581
+ return null;
43582
+ const cfg = readJson(p);
43583
+ const server = cfg?.mcpServers?.workit;
43584
+ if (!server || typeof server !== "object" || Array.isArray(server))
43585
+ return null;
43586
+ const args = server.args;
43587
+ if (!Array.isArray(args))
43588
+ return null;
43589
+ return args.map(String).filter((a) => a.startsWith("--package="));
43590
+ };
43591
+ var registryLatestVersion = (res) => {
43592
+ const seam = res.env.WORKIT_DOCTOR_STALE_REGISTRY_VERSION;
43593
+ if (typeof seam === "string" && seam) {
43594
+ return /^\d+(?:\.\d+){1,2}$/.test(seam) ? seam : null;
43595
+ }
43596
+ const cmd = res.env.WORKIT_DOCTOR_STALE_REGISTRY_CMD ?? (commandOnPath("npm", res.env) ? "npm" : null);
43597
+ if (!cmd)
43598
+ return null;
43599
+ try {
43600
+ const r = spawnSync2(cmd, ["view", CURSOR_RUNTIME_PACKAGE, "version"], {
43601
+ encoding: "utf8",
43602
+ timeout: 20000,
43603
+ env: res.env
43604
+ });
43605
+ const v = (r.stdout ?? "").trim().split(/\s+/)[0];
43606
+ return r.status === 0 && /^\d+(?:\.\d+){1,2}$/.test(v) ? v : null;
43607
+ } catch {
43608
+ return null;
43609
+ }
43610
+ };
43611
+ var installedPluginVersion = (res) => {
43612
+ const pkg = readJson(path9.join(res.cursorPluginDir, "package.json"));
43613
+ return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
43614
+ };
43615
+ var checkStaleInstall = (res) => {
43616
+ if (res.host !== "cursor" && res.host !== "cli") {
43617
+ return {
43618
+ id: "stale_install",
43619
+ status: "pass",
43620
+ detail: "cursor plugin not inspected on the opencode host"
43621
+ };
43622
+ }
43623
+ const canonicalMcp = cursorMcpServerEntry("").args.find((a) => a.startsWith("--package="));
43624
+ const mcpSelectors = pluginMcpSelectors(res);
43625
+ const legacyPin = (mcpSelectors ?? []).find((s) => s !== canonicalMcp && s.includes("@brainervirus/workit-cursor@"));
43626
+ if (legacyPin) {
43627
+ return {
43628
+ id: "stale_install",
43629
+ status: "fail",
43630
+ detail: `stale_install: plugin mcp.json pins a legacy selector ${legacyPin} (canonical: ${canonicalMcp})`,
43631
+ fix: "Re-run install-cursor-plugin.sh — it rewrites the workit MCP entry to the canonical @latest selector"
43632
+ };
43633
+ }
43634
+ const hooksFile = path9.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
43635
+ const hookCmd = readJson(hooksFile)?.hooks?.sessionStart?.[0]?.command ?? null;
43636
+ const canonicalHook = canonicalCursorHook;
43637
+ const staleHook = hookCmd !== null && hookCmd !== canonicalHook && !hookCmd.startsWith("node ") && hookCmd.includes("@brainervirus/workit-cursor@");
43638
+ if (staleHook) {
43639
+ return {
43640
+ id: "stale_install",
43641
+ status: "fail",
43642
+ detail: `stale_install: sessionStart hook runs a legacy selector (canonical: ${canonicalHook})`,
43643
+ fix: "Re-run install-cursor-plugin.sh — it rewrites the sessionStart hook to the canonical @latest selector"
43644
+ };
43645
+ }
43646
+ const installed = installedPluginVersion(res);
43647
+ const source = res.dev ? readJson(path9.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path9.join(packageRoot(), "package.json"))?.version ?? null;
43648
+ const localDist = mcpSelectors === null && hookCmd !== null && hookCmd.startsWith("node ");
43649
+ if (localDist && installed !== null && source !== null && !semverAtLeast(installed, source)) {
43650
+ return {
43651
+ id: "stale_install",
43652
+ status: "fail",
43653
+ detail: `stale_install: installed workit-cursor ${installed} is behind the current runtime ${source}`,
43654
+ fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory and rewrites the workit MCP/hook entries"
43655
+ };
43656
+ }
43657
+ if (installed !== null && localDist) {
43658
+ const expected = registryLatestVersion(res);
43659
+ if (expected === null) {
43660
+ return {
43661
+ id: "registry_unreachable",
43662
+ status: "warn",
43663
+ registryProbed: true,
43664
+ detail: "registry_unreachable: cannot compare installed workit-cursor against the published runtime",
43665
+ fix: "Retry when the npm registry is reachable, or re-run install-cursor-plugin.sh to refresh the install"
43666
+ };
43667
+ }
43668
+ if (!semverAtLeast(installed, expected)) {
43669
+ return {
43670
+ id: "stale_install",
43671
+ status: "fail",
43672
+ registryProbed: true,
43673
+ detail: `stale_install: local-dist workit-cursor ${installed} is behind the published runtime ${expected}`,
43674
+ fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory with the current build"
43675
+ };
43676
+ }
43677
+ return {
43678
+ id: "stale_install",
43679
+ status: "pass",
43680
+ registryProbed: true,
43681
+ detail: `installed local-dist workit-cursor ${installed} matches the published runtime ${expected}`
43682
+ };
43683
+ }
43684
+ return {
43685
+ id: "stale_install",
43686
+ status: "pass",
43687
+ detail: installed === null ? "installed workit-cursor selectors are canonical" : `installed workit-cursor ${installed} is metadata on the canonical @latest install (fresh at launch)`
43688
+ };
43689
+ };
43566
43690
  var checkDuplicateRegistration = (res) => {
43567
43691
  const problems = [];
43568
43692
  const opencodeHost = res.host !== "cursor";
@@ -43598,7 +43722,11 @@ var checkDuplicateRegistration = (res) => {
43598
43722
  }
43599
43723
  }
43600
43724
  if (problems.length === 0) {
43601
- return { id: "duplicate_registration", status: "pass", detail: "no duplicate registrations" };
43725
+ return {
43726
+ id: "duplicate_registration",
43727
+ status: "pass",
43728
+ detail: "no duplicate registrations"
43729
+ };
43602
43730
  }
43603
43731
  return {
43604
43732
  id: "duplicate_registration",
@@ -43624,7 +43752,11 @@ var checkMalformedConfig = (res) => {
43624
43752
  files.push(res.cursorMcp);
43625
43753
  const bad = files.filter((p) => !parsesAsConfigObject(p));
43626
43754
  if (bad.length === 0)
43627
- return { id: "malformed_config", status: "pass", detail: "config files parse" };
43755
+ return {
43756
+ id: "malformed_config",
43757
+ status: "pass",
43758
+ detail: "config files parse"
43759
+ };
43628
43760
  return {
43629
43761
  id: "malformed_config",
43630
43762
  status: "fail",
@@ -43635,10 +43767,18 @@ var checkMalformedConfig = (res) => {
43635
43767
  var checkWorkspaceMismatch = (res) => {
43636
43768
  const file = path9.join(res.configDir, "workspaces.json");
43637
43769
  if (!existsSync7(file))
43638
- return { id: "workspace_mismatch", status: "pass", detail: "no workspaces configured" };
43770
+ return {
43771
+ id: "workspace_mismatch",
43772
+ status: "pass",
43773
+ detail: "no workspaces configured"
43774
+ };
43639
43775
  const ws = readJson(file);
43640
43776
  if (!Array.isArray(ws?.workspaces)) {
43641
- return { id: "workspace_mismatch", status: "pass", detail: "no workspaces configured" };
43777
+ return {
43778
+ id: "workspace_mismatch",
43779
+ status: "pass",
43780
+ detail: "no workspaces configured"
43781
+ };
43642
43782
  }
43643
43783
  const match = resolveWorkspaceFrom(res.cwd, res.configDir);
43644
43784
  if (match)
@@ -43680,7 +43820,11 @@ var checkCredentialMetadata = (res) => {
43680
43820
  }
43681
43821
  }
43682
43822
  if (tokenPaths.length === 0) {
43683
- return { id: "credential_metadata", status: "pass", detail: "no credentials configured" };
43823
+ return {
43824
+ id: "credential_metadata",
43825
+ status: "pass",
43826
+ detail: "no credentials configured"
43827
+ };
43684
43828
  }
43685
43829
  const problems = [];
43686
43830
  for (const raw of tokenPaths) {
@@ -43718,7 +43862,11 @@ var checkLogWritable = (res) => {
43718
43862
  mkdirSync2(logsDir, { recursive: true, mode: 448 });
43719
43863
  writeFileSync4(probe, `{"probe":true}
43720
43864
  `, { mode: 384 });
43721
- return { id: "log_writable", status: "pass", detail: "log directory writable" };
43865
+ return {
43866
+ id: "log_writable",
43867
+ status: "pass",
43868
+ detail: "log directory writable"
43869
+ };
43722
43870
  } catch (err) {
43723
43871
  return {
43724
43872
  id: "log_writable",
@@ -43739,6 +43887,7 @@ var RUN_CHECKS = [
43739
43887
  checkLauncher,
43740
43888
  checkUtility,
43741
43889
  checkStalePin,
43890
+ checkStaleInstall,
43742
43891
  checkDuplicateRegistration,
43743
43892
  checkMalformedConfig,
43744
43893
  checkWorkspaceMismatch,
@@ -43751,21 +43900,27 @@ var INSTALLER_REQUIRED = new Set([
43751
43900
  "launcher",
43752
43901
  "utility",
43753
43902
  "stale_pin",
43903
+ "stale_install",
43754
43904
  "duplicate_registration",
43755
43905
  "malformed_config"
43756
43906
  ]);
43757
43907
  var runDoctor = (options = {}) => {
43758
43908
  const res = resolve(options);
43759
43909
  const raw = RUN_CHECKS.map((fn) => fn(res));
43760
- const checks = res.installer ? raw.map((c) => c.status === "fail" && !INSTALLER_REQUIRED.has(c.id) ? { ...c, status: "warn", detail: `${c.detail} (not enforced by installer)` } : c) : raw;
43910
+ const checks = res.installer ? raw.map((c) => c.status === "fail" && !INSTALLER_REQUIRED.has(c.id) ? {
43911
+ ...c,
43912
+ status: "warn",
43913
+ detail: `${c.detail} (not enforced by installer)`
43914
+ } : c) : raw;
43761
43915
  const failed = checks.filter((c) => c.status === "fail").length;
43762
43916
  const warned = checks.filter((c) => c.status === "warn").length;
43763
43917
  const passed = checks.filter((c) => c.status === "pass").length;
43764
43918
  const exitCode = failed > 0 ? 1 : 0;
43919
+ const offline = !raw.some((c) => ("registryProbed" in c) && c.registryProbed);
43765
43920
  const report = {
43766
43921
  ok: failed === 0,
43767
43922
  exitCode,
43768
- offline: true,
43923
+ offline,
43769
43924
  host: res.host,
43770
43925
  checked_at: new Date().toISOString(),
43771
43926
  summary: { passed, warned, failed, total: checks.length },
@@ -43775,7 +43930,7 @@ var runDoctor = (options = {}) => {
43775
43930
  getDiagnosticLogger()?.info(EVENT.doctor, {
43776
43931
  host: res.host,
43777
43932
  exit_code: exitCode,
43778
- offline: true,
43933
+ offline,
43779
43934
  failed: checks.filter((c) => c.status === "fail").map((c) => c.id),
43780
43935
  total: checks.length
43781
43936
  });
@@ -48582,7 +48737,7 @@ function runDoctorCommand(args) {
48582
48737
  if (args.includes("--json")) {
48583
48738
  console.log(JSON.stringify(report, null, 2));
48584
48739
  } else {
48585
- console.log(`workit doctor — ${report.ok ? "healthy" : "problems found"} (offline)`);
48740
+ console.log(`workit doctor — ${report.ok ? "healthy" : "problems found"} (${report.offline ? "offline" : "online"})`);
48586
48741
  for (const check2 of report.checks) {
48587
48742
  const mark = check2.status === "fail" ? "FAIL" : check2.status === "warn" ? "WARN" : "ok ";
48588
48743
  console.log(`${mark} ${check2.id} — ${check2.detail}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "0.8.7",
3
+ "version": "0.8.8",
4
4
  "private": false,
5
5
  "description": "Workit interactive setup wizard (Ink TUI)",
6
6
  "keywords": [
@@ -34,9 +34,9 @@
34
34
  "typecheck": "tsc --noEmit"
35
35
  },
36
36
  "dependencies": {
37
- "@brainervirus/workit-core": "^0.8.7",
38
- "@brainervirus/workit-cursor": "^0.8.7",
39
- "@brainervirus/workit-opencode": "^0.8.7",
37
+ "@brainervirus/workit-core": "^0.8.8",
38
+ "@brainervirus/workit-cursor": "^0.8.8",
39
+ "@brainervirus/workit-opencode": "^0.8.8",
40
40
  "@inkjs/ui": "2.0.0",
41
41
  "ink": "7.1.1",
42
42
  "react": "19.2.8"