@brainervirus/workit-cli 0.8.6 → 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 +179 -24
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -43026,16 +43026,22 @@ function mergeCursorMcp(mcp, serverName, server) {
43026
43026
  base2.mcpServers = servers;
43027
43027
  return { config: base2, changed };
43028
43028
  }
43029
- var CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@0.8.5";
43029
+ var CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@latest";
43030
43030
  function cursorMcpServerEntry(_packageDir) {
43031
43031
  return {
43032
43032
  command: "npx",
43033
- args: ["-y", `--package=${CURSOR_RUNTIME_PACKAGE}`, "workit-cursor-mcp", "${workspaceFolder}"]
43033
+ args: [
43034
+ "-y",
43035
+ "--prefer-online",
43036
+ `--package=${CURSOR_RUNTIME_PACKAGE}`,
43037
+ "workit-cursor-mcp",
43038
+ "${workspaceFolder}"
43039
+ ]
43034
43040
  };
43035
43041
  }
43036
43042
  function cursorHooksEntry(_packageDir) {
43037
43043
  return {
43038
- command: `npx -y --package=${CURSOR_RUNTIME_PACKAGE} workit-cursor-session-start`,
43044
+ command: `npx -y --prefer-online --package=${CURSOR_RUNTIME_PACKAGE} workit-cursor-session-start`,
43039
43045
  args: []
43040
43046
  };
43041
43047
  }
@@ -43405,12 +43411,9 @@ var registeredCursorLauncher = (res) => {
43405
43411
  return "invalid";
43406
43412
  }
43407
43413
  const executable = path9.basename(command).toLowerCase();
43414
+ const canonical = cursorMcpServerEntry("").args;
43408
43415
  if (executable === "npx" || executable === "npx.exe" || executable === "npx.cmd") {
43409
- if (args[0] !== "-y")
43410
- return "invalid";
43411
- if (args[1] !== `--package=${CURSOR_RUNTIME_PACKAGE}`)
43412
- return "invalid";
43413
- if (args[2] !== "workit-cursor-mcp")
43416
+ if (args.length !== canonical.length || args.some((a, i) => a !== canonical[i]))
43414
43417
  return "invalid";
43415
43418
  return { kind: "npx" };
43416
43419
  }
@@ -43487,7 +43490,11 @@ var checkLauncher = (res) => {
43487
43490
  detail: "no dev checkout found (WORKFLOW_TOOLKIT_DEV) — skipping non-Cursor launcher checks"
43488
43491
  };
43489
43492
  }
43490
- 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
+ };
43491
43498
  };
43492
43499
  var checkUtility = (res) => {
43493
43500
  const git = commandOnPath("git", res.env);
@@ -43507,7 +43514,11 @@ var checkUtility = (res) => {
43507
43514
  fix: "Install util-linux (flock)"
43508
43515
  };
43509
43516
  }
43510
- 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
+ };
43511
43522
  };
43512
43523
  var staleEntry = (entry) => {
43513
43524
  if (!entry)
@@ -43529,7 +43540,11 @@ var checkStalePin = (res) => {
43529
43540
  };
43530
43541
  }
43531
43542
  if (!existsSync7(res.opencodeConfig)) {
43532
- 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
+ };
43533
43548
  }
43534
43549
  const cfg = readJson(res.opencodeConfig);
43535
43550
  const entries = pluginEntries(cfg);
@@ -43560,6 +43575,118 @@ var checkStalePin = (res) => {
43560
43575
  }
43561
43576
  return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
43562
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
+ };
43563
43690
  var checkDuplicateRegistration = (res) => {
43564
43691
  const problems = [];
43565
43692
  const opencodeHost = res.host !== "cursor";
@@ -43595,7 +43722,11 @@ var checkDuplicateRegistration = (res) => {
43595
43722
  }
43596
43723
  }
43597
43724
  if (problems.length === 0) {
43598
- 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
+ };
43599
43730
  }
43600
43731
  return {
43601
43732
  id: "duplicate_registration",
@@ -43621,7 +43752,11 @@ var checkMalformedConfig = (res) => {
43621
43752
  files.push(res.cursorMcp);
43622
43753
  const bad = files.filter((p) => !parsesAsConfigObject(p));
43623
43754
  if (bad.length === 0)
43624
- 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
+ };
43625
43760
  return {
43626
43761
  id: "malformed_config",
43627
43762
  status: "fail",
@@ -43632,10 +43767,18 @@ var checkMalformedConfig = (res) => {
43632
43767
  var checkWorkspaceMismatch = (res) => {
43633
43768
  const file = path9.join(res.configDir, "workspaces.json");
43634
43769
  if (!existsSync7(file))
43635
- 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
+ };
43636
43775
  const ws = readJson(file);
43637
43776
  if (!Array.isArray(ws?.workspaces)) {
43638
- 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
+ };
43639
43782
  }
43640
43783
  const match = resolveWorkspaceFrom(res.cwd, res.configDir);
43641
43784
  if (match)
@@ -43677,7 +43820,11 @@ var checkCredentialMetadata = (res) => {
43677
43820
  }
43678
43821
  }
43679
43822
  if (tokenPaths.length === 0) {
43680
- 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
+ };
43681
43828
  }
43682
43829
  const problems = [];
43683
43830
  for (const raw of tokenPaths) {
@@ -43715,7 +43862,11 @@ var checkLogWritable = (res) => {
43715
43862
  mkdirSync2(logsDir, { recursive: true, mode: 448 });
43716
43863
  writeFileSync4(probe, `{"probe":true}
43717
43864
  `, { mode: 384 });
43718
- 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
+ };
43719
43870
  } catch (err) {
43720
43871
  return {
43721
43872
  id: "log_writable",
@@ -43736,6 +43887,7 @@ var RUN_CHECKS = [
43736
43887
  checkLauncher,
43737
43888
  checkUtility,
43738
43889
  checkStalePin,
43890
+ checkStaleInstall,
43739
43891
  checkDuplicateRegistration,
43740
43892
  checkMalformedConfig,
43741
43893
  checkWorkspaceMismatch,
@@ -43748,21 +43900,27 @@ var INSTALLER_REQUIRED = new Set([
43748
43900
  "launcher",
43749
43901
  "utility",
43750
43902
  "stale_pin",
43903
+ "stale_install",
43751
43904
  "duplicate_registration",
43752
43905
  "malformed_config"
43753
43906
  ]);
43754
43907
  var runDoctor = (options = {}) => {
43755
43908
  const res = resolve(options);
43756
43909
  const raw = RUN_CHECKS.map((fn) => fn(res));
43757
- 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;
43758
43915
  const failed = checks.filter((c) => c.status === "fail").length;
43759
43916
  const warned = checks.filter((c) => c.status === "warn").length;
43760
43917
  const passed = checks.filter((c) => c.status === "pass").length;
43761
43918
  const exitCode = failed > 0 ? 1 : 0;
43919
+ const offline = !raw.some((c) => ("registryProbed" in c) && c.registryProbed);
43762
43920
  const report = {
43763
43921
  ok: failed === 0,
43764
43922
  exitCode,
43765
- offline: true,
43923
+ offline,
43766
43924
  host: res.host,
43767
43925
  checked_at: new Date().toISOString(),
43768
43926
  summary: { passed, warned, failed, total: checks.length },
@@ -43772,7 +43930,7 @@ var runDoctor = (options = {}) => {
43772
43930
  getDiagnosticLogger()?.info(EVENT.doctor, {
43773
43931
  host: res.host,
43774
43932
  exit_code: exitCode,
43775
- offline: true,
43933
+ offline,
43776
43934
  failed: checks.filter((c) => c.status === "fail").map((c) => c.id),
43777
43935
  total: checks.length
43778
43936
  });
@@ -47504,9 +47662,6 @@ var resetForSpecDrift = (state) => ({
47504
47662
  var resetForPlanDrift = (state) => ({
47505
47663
  ...state,
47506
47664
  plan: { ...state.plan, status: "draft", evidence: null, approved_digest: null },
47507
- menu: { presented: false, chosen: "", evidence: null },
47508
- execution: { status: "pending", mode: null, evidence: null },
47509
- handoff_destination: false,
47510
47665
  updated_at: Date.now()
47511
47666
  });
47512
47667
  var driftCodeFor = (root, relPath, storedDigest) => {
@@ -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.6",
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.6",
38
- "@brainervirus/workit-cursor": "^0.8.6",
39
- "@brainervirus/workit-opencode": "^0.8.6",
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"