@brainervirus/workit-opencode 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/plugin.js +167 -12
  2. package/package.json +2 -2
package/dist/plugin.js CHANGED
@@ -1596,7 +1596,11 @@ var checkLauncher = (res) => {
1596
1596
  detail: "no dev checkout found (WORKFLOW_TOOLKIT_DEV) — skipping non-Cursor launcher checks"
1597
1597
  };
1598
1598
  }
1599
- return { id: "launcher", status: "pass", detail: `${res.host} launcher/hook entries present` };
1599
+ return {
1600
+ id: "launcher",
1601
+ status: "pass",
1602
+ detail: `${res.host} launcher/hook entries present`
1603
+ };
1600
1604
  };
1601
1605
  var checkUtility = (res) => {
1602
1606
  const git = commandOnPath("git", res.env);
@@ -1616,7 +1620,11 @@ var checkUtility = (res) => {
1616
1620
  fix: "Install util-linux (flock)"
1617
1621
  };
1618
1622
  }
1619
- return { id: "utility", status: "pass", detail: "git (and flock where required) on PATH" };
1623
+ return {
1624
+ id: "utility",
1625
+ status: "pass",
1626
+ detail: "git (and flock where required) on PATH"
1627
+ };
1620
1628
  };
1621
1629
  var staleEntry = (entry) => {
1622
1630
  if (!entry)
@@ -1638,7 +1646,11 @@ var checkStalePin = (res) => {
1638
1646
  };
1639
1647
  }
1640
1648
  if (!existsSync7(res.opencodeConfig)) {
1641
- return { id: "stale_pin", status: "pass", detail: "no opencode config — not registered" };
1649
+ return {
1650
+ id: "stale_pin",
1651
+ status: "pass",
1652
+ detail: "no opencode config — not registered"
1653
+ };
1642
1654
  }
1643
1655
  const cfg = readJson(res.opencodeConfig);
1644
1656
  const entries = pluginEntries(cfg);
@@ -1669,6 +1681,118 @@ var checkStalePin = (res) => {
1669
1681
  }
1670
1682
  return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
1671
1683
  };
1684
+ var pluginMcpSelectors = (res) => {
1685
+ const p = path10.join(res.cursorPluginDir, "mcp.json");
1686
+ if (!existsSync7(p))
1687
+ return null;
1688
+ const cfg = readJson(p);
1689
+ const server = cfg?.mcpServers?.workit;
1690
+ if (!server || typeof server !== "object" || Array.isArray(server))
1691
+ return null;
1692
+ const args = server.args;
1693
+ if (!Array.isArray(args))
1694
+ return null;
1695
+ return args.map(String).filter((a) => a.startsWith("--package="));
1696
+ };
1697
+ var registryLatestVersion = (res) => {
1698
+ const seam = res.env.WORKIT_DOCTOR_STALE_REGISTRY_VERSION;
1699
+ if (typeof seam === "string" && seam) {
1700
+ return /^\d+(?:\.\d+){1,2}$/.test(seam) ? seam : null;
1701
+ }
1702
+ const cmd = res.env.WORKIT_DOCTOR_STALE_REGISTRY_CMD ?? (commandOnPath("npm", res.env) ? "npm" : null);
1703
+ if (!cmd)
1704
+ return null;
1705
+ try {
1706
+ const r = spawnSync2(cmd, ["view", CURSOR_RUNTIME_PACKAGE, "version"], {
1707
+ encoding: "utf8",
1708
+ timeout: 20000,
1709
+ env: res.env
1710
+ });
1711
+ const v = (r.stdout ?? "").trim().split(/\s+/)[0];
1712
+ return r.status === 0 && /^\d+(?:\.\d+){1,2}$/.test(v) ? v : null;
1713
+ } catch {
1714
+ return null;
1715
+ }
1716
+ };
1717
+ var installedPluginVersion = (res) => {
1718
+ const pkg = readJson(path10.join(res.cursorPluginDir, "package.json"));
1719
+ return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
1720
+ };
1721
+ var checkStaleInstall = (res) => {
1722
+ if (res.host !== "cursor" && res.host !== "cli") {
1723
+ return {
1724
+ id: "stale_install",
1725
+ status: "pass",
1726
+ detail: "cursor plugin not inspected on the opencode host"
1727
+ };
1728
+ }
1729
+ const canonicalMcp = cursorMcpServerEntry("").args.find((a) => a.startsWith("--package="));
1730
+ const mcpSelectors = pluginMcpSelectors(res);
1731
+ const legacyPin = (mcpSelectors ?? []).find((s) => s !== canonicalMcp && s.includes("@brainervirus/workit-cursor@"));
1732
+ if (legacyPin) {
1733
+ return {
1734
+ id: "stale_install",
1735
+ status: "fail",
1736
+ detail: `stale_install: plugin mcp.json pins a legacy selector ${legacyPin} (canonical: ${canonicalMcp})`,
1737
+ fix: "Re-run install-cursor-plugin.sh — it rewrites the workit MCP entry to the canonical @latest selector"
1738
+ };
1739
+ }
1740
+ const hooksFile = path10.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
1741
+ const hookCmd = readJson(hooksFile)?.hooks?.sessionStart?.[0]?.command ?? null;
1742
+ const canonicalHook = canonicalCursorHook;
1743
+ const staleHook = hookCmd !== null && hookCmd !== canonicalHook && !hookCmd.startsWith("node ") && hookCmd.includes("@brainervirus/workit-cursor@");
1744
+ if (staleHook) {
1745
+ return {
1746
+ id: "stale_install",
1747
+ status: "fail",
1748
+ detail: `stale_install: sessionStart hook runs a legacy selector (canonical: ${canonicalHook})`,
1749
+ fix: "Re-run install-cursor-plugin.sh — it rewrites the sessionStart hook to the canonical @latest selector"
1750
+ };
1751
+ }
1752
+ const installed = installedPluginVersion(res);
1753
+ const source = res.dev ? readJson(path10.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path10.join(packageRoot(), "package.json"))?.version ?? null;
1754
+ const localDist = mcpSelectors === null && hookCmd !== null && hookCmd.startsWith("node ");
1755
+ if (localDist && installed !== null && source !== null && !semverAtLeast(installed, source)) {
1756
+ return {
1757
+ id: "stale_install",
1758
+ status: "fail",
1759
+ detail: `stale_install: installed workit-cursor ${installed} is behind the current runtime ${source}`,
1760
+ fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory and rewrites the workit MCP/hook entries"
1761
+ };
1762
+ }
1763
+ if (installed !== null && localDist) {
1764
+ const expected = registryLatestVersion(res);
1765
+ if (expected === null) {
1766
+ return {
1767
+ id: "registry_unreachable",
1768
+ status: "warn",
1769
+ registryProbed: true,
1770
+ detail: "registry_unreachable: cannot compare installed workit-cursor against the published runtime",
1771
+ fix: "Retry when the npm registry is reachable, or re-run install-cursor-plugin.sh to refresh the install"
1772
+ };
1773
+ }
1774
+ if (!semverAtLeast(installed, expected)) {
1775
+ return {
1776
+ id: "stale_install",
1777
+ status: "fail",
1778
+ registryProbed: true,
1779
+ detail: `stale_install: local-dist workit-cursor ${installed} is behind the published runtime ${expected}`,
1780
+ fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory with the current build"
1781
+ };
1782
+ }
1783
+ return {
1784
+ id: "stale_install",
1785
+ status: "pass",
1786
+ registryProbed: true,
1787
+ detail: `installed local-dist workit-cursor ${installed} matches the published runtime ${expected}`
1788
+ };
1789
+ }
1790
+ return {
1791
+ id: "stale_install",
1792
+ status: "pass",
1793
+ detail: installed === null ? "installed workit-cursor selectors are canonical" : `installed workit-cursor ${installed} is metadata on the canonical @latest install (fresh at launch)`
1794
+ };
1795
+ };
1672
1796
  var checkDuplicateRegistration = (res) => {
1673
1797
  const problems = [];
1674
1798
  const opencodeHost = res.host !== "cursor";
@@ -1704,7 +1828,11 @@ var checkDuplicateRegistration = (res) => {
1704
1828
  }
1705
1829
  }
1706
1830
  if (problems.length === 0) {
1707
- return { id: "duplicate_registration", status: "pass", detail: "no duplicate registrations" };
1831
+ return {
1832
+ id: "duplicate_registration",
1833
+ status: "pass",
1834
+ detail: "no duplicate registrations"
1835
+ };
1708
1836
  }
1709
1837
  return {
1710
1838
  id: "duplicate_registration",
@@ -1730,7 +1858,11 @@ var checkMalformedConfig = (res) => {
1730
1858
  files.push(res.cursorMcp);
1731
1859
  const bad = files.filter((p) => !parsesAsConfigObject(p));
1732
1860
  if (bad.length === 0)
1733
- return { id: "malformed_config", status: "pass", detail: "config files parse" };
1861
+ return {
1862
+ id: "malformed_config",
1863
+ status: "pass",
1864
+ detail: "config files parse"
1865
+ };
1734
1866
  return {
1735
1867
  id: "malformed_config",
1736
1868
  status: "fail",
@@ -1741,10 +1873,18 @@ var checkMalformedConfig = (res) => {
1741
1873
  var checkWorkspaceMismatch = (res) => {
1742
1874
  const file = path10.join(res.configDir, "workspaces.json");
1743
1875
  if (!existsSync7(file))
1744
- return { id: "workspace_mismatch", status: "pass", detail: "no workspaces configured" };
1876
+ return {
1877
+ id: "workspace_mismatch",
1878
+ status: "pass",
1879
+ detail: "no workspaces configured"
1880
+ };
1745
1881
  const ws = readJson(file);
1746
1882
  if (!Array.isArray(ws?.workspaces)) {
1747
- return { id: "workspace_mismatch", status: "pass", detail: "no workspaces configured" };
1883
+ return {
1884
+ id: "workspace_mismatch",
1885
+ status: "pass",
1886
+ detail: "no workspaces configured"
1887
+ };
1748
1888
  }
1749
1889
  const match = resolveWorkspaceFrom(res.cwd, res.configDir);
1750
1890
  if (match)
@@ -1786,7 +1926,11 @@ var checkCredentialMetadata = (res) => {
1786
1926
  }
1787
1927
  }
1788
1928
  if (tokenPaths.length === 0) {
1789
- return { id: "credential_metadata", status: "pass", detail: "no credentials configured" };
1929
+ return {
1930
+ id: "credential_metadata",
1931
+ status: "pass",
1932
+ detail: "no credentials configured"
1933
+ };
1790
1934
  }
1791
1935
  const problems = [];
1792
1936
  for (const raw of tokenPaths) {
@@ -1824,7 +1968,11 @@ var checkLogWritable = (res) => {
1824
1968
  mkdirSync3(logsDir, { recursive: true, mode: 448 });
1825
1969
  writeFileSync6(probe, `{"probe":true}
1826
1970
  `, { mode: 384 });
1827
- return { id: "log_writable", status: "pass", detail: "log directory writable" };
1971
+ return {
1972
+ id: "log_writable",
1973
+ status: "pass",
1974
+ detail: "log directory writable"
1975
+ };
1828
1976
  } catch (err) {
1829
1977
  return {
1830
1978
  id: "log_writable",
@@ -1845,6 +1993,7 @@ var RUN_CHECKS = [
1845
1993
  checkLauncher,
1846
1994
  checkUtility,
1847
1995
  checkStalePin,
1996
+ checkStaleInstall,
1848
1997
  checkDuplicateRegistration,
1849
1998
  checkMalformedConfig,
1850
1999
  checkWorkspaceMismatch,
@@ -1857,21 +2006,27 @@ var INSTALLER_REQUIRED = new Set([
1857
2006
  "launcher",
1858
2007
  "utility",
1859
2008
  "stale_pin",
2009
+ "stale_install",
1860
2010
  "duplicate_registration",
1861
2011
  "malformed_config"
1862
2012
  ]);
1863
2013
  var runDoctor = (options = {}) => {
1864
2014
  const res = resolve(options);
1865
2015
  const raw = RUN_CHECKS.map((fn) => fn(res));
1866
- 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;
2016
+ const checks = res.installer ? raw.map((c) => c.status === "fail" && !INSTALLER_REQUIRED.has(c.id) ? {
2017
+ ...c,
2018
+ status: "warn",
2019
+ detail: `${c.detail} (not enforced by installer)`
2020
+ } : c) : raw;
1867
2021
  const failed = checks.filter((c) => c.status === "fail").length;
1868
2022
  const warned = checks.filter((c) => c.status === "warn").length;
1869
2023
  const passed = checks.filter((c) => c.status === "pass").length;
1870
2024
  const exitCode = failed > 0 ? 1 : 0;
2025
+ const offline = !raw.some((c) => ("registryProbed" in c) && c.registryProbed);
1871
2026
  const report = {
1872
2027
  ok: failed === 0,
1873
2028
  exitCode,
1874
- offline: true,
2029
+ offline,
1875
2030
  host: res.host,
1876
2031
  checked_at: new Date().toISOString(),
1877
2032
  summary: { passed, warned, failed, total: checks.length },
@@ -1881,7 +2036,7 @@ var runDoctor = (options = {}) => {
1881
2036
  getDiagnosticLogger()?.info(EVENT.doctor, {
1882
2037
  host: res.host,
1883
2038
  exit_code: exitCode,
1884
- offline: true,
2039
+ offline,
1885
2040
  failed: checks.filter((c) => c.status === "fail").map((c) => c.id),
1886
2041
  total: checks.length
1887
2042
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-opencode",
3
- "version": "0.8.7",
3
+ "version": "0.8.8",
4
4
  "private": false,
5
5
  "description": "Workit OpenCode plugin (thin wrapper over @brainervirus/workit-core)",
6
6
  "keywords": [
@@ -34,7 +34,7 @@
34
34
  "typecheck": "tsc --noEmit"
35
35
  },
36
36
  "dependencies": {
37
- "@brainervirus/workit-core": "^0.8.7"
37
+ "@brainervirus/workit-core": "^0.8.8"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@opencode-ai/plugin": "1.17.7"