@brainervirus/workit-cli 1.0.3 → 1.0.5

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 +176 -27
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -43028,10 +43028,12 @@ import {
43028
43028
  copyFileSync as copyFileSync2,
43029
43029
  cpSync as cpSync3,
43030
43030
  existsSync as existsSync10,
43031
+ lstatSync as lstatSync2,
43031
43032
  mkdirSync as mkdirSync5,
43032
43033
  mkdtempSync,
43033
43034
  readFileSync as readFileSync10,
43034
43035
  readdirSync as readdirSync4,
43036
+ realpathSync as realpathSync2,
43035
43037
  renameSync,
43036
43038
  rmSync as rmSync2,
43037
43039
  statSync as statSync4,
@@ -43135,6 +43137,7 @@ var readSetupState = (dir = resolveConfigDir()) => ({
43135
43137
 
43136
43138
  // packages/workit-core/src/core/registration.ts
43137
43139
  import path7 from "node:path";
43140
+ var OPENCODE_NPM_PIN = "@brainervirus/workit-opencode";
43138
43141
  var isRecord = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
43139
43142
  var named = (s, name) => s === name || s.startsWith(`${name}@`);
43140
43143
  function isWorkitPlugin(value) {
@@ -43257,7 +43260,16 @@ function cursorHooksEntry(_packageDir) {
43257
43260
 
43258
43261
  // packages/workit-core/src/core/doctor.ts
43259
43262
  import { spawnSync as spawnSync2 } from "node:child_process";
43260
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync9, statSync as statSync3, unlinkSync, writeFileSync as writeFileSync6 } from "node:fs";
43263
+ import {
43264
+ existsSync as existsSync9,
43265
+ lstatSync,
43266
+ mkdirSync as mkdirSync4,
43267
+ readFileSync as readFileSync9,
43268
+ readlinkSync,
43269
+ statSync as statSync3,
43270
+ unlinkSync,
43271
+ writeFileSync as writeFileSync6
43272
+ } from "node:fs";
43261
43273
  import os5 from "node:os";
43262
43274
  import path11 from "node:path";
43263
43275
 
@@ -51956,6 +51968,7 @@ var resolve = (options) => {
51956
51968
  cwd,
51957
51969
  dev,
51958
51970
  opencodeConfig: options.opencodeConfig ?? path11.join(home, ".config", "opencode", "opencode.json"),
51971
+ opencodePackageCacheDir: options.opencodePackageCacheDir ?? path11.join(home, ".cache", "opencode", "packages", "@brainervirus", "workit-opencode@latest"),
51959
51972
  cursorSettings: options.cursorSettings ?? path11.join(home, ".cursor", "settings.json"),
51960
51973
  cursorMcp: options.cursorMcp ?? path11.join(home, ".cursor", "mcp.json"),
51961
51974
  cursorPluginDir: options.cursorPluginDir ?? path11.join(home, ".cursor", "plugins", "local", "workit"),
@@ -52358,11 +52371,19 @@ var checkUtility = (res) => {
52358
52371
  detail: "git (and flock where required) on PATH"
52359
52372
  };
52360
52373
  };
52374
+ var isFragileCachePin = (entry) => {
52375
+ const n = entry.replaceAll("\\", "/").toLowerCase();
52376
+ if (!n.startsWith("file:"))
52377
+ return false;
52378
+ return n.includes("/caches/pnpm/dlx/") || n.includes("/_npx/") || n.includes("/.pacquet/") || n.includes("/library/caches/pnpm/");
52379
+ };
52361
52380
  var staleEntry = (entry) => {
52362
52381
  if (!entry)
52363
52382
  return "stale";
52364
52383
  if (entry.includes("git+file"))
52365
52384
  return "stale";
52385
+ if (isFragileCachePin(entry))
52386
+ return "fragile-cache";
52366
52387
  if (entry.startsWith("file:")) {
52367
52388
  const target = entry.replace(/^file:\/\//, "").replace(/^file:/, "");
52368
52389
  return existsSync9(target) ? "ok" : "missing-file";
@@ -52391,7 +52412,7 @@ var checkStalePin = (res) => {
52391
52412
  id: "stale_pin",
52392
52413
  status: "fail",
52393
52414
  detail: "no workit plugin registered in the opencode config",
52394
- fix: "Run install-opencode-plugin.sh to pin the workit plugin entry"
52415
+ fix: 'Run `workit init` and select OpenCode — pin "@brainervirus/workit-opencode"'
52395
52416
  };
52396
52417
  }
52397
52418
  const first = staleEntry(entries[0]);
@@ -52400,7 +52421,15 @@ var checkStalePin = (res) => {
52400
52421
  id: "stale_pin",
52401
52422
  status: "fail",
52402
52423
  detail: `stale workit pin: ${entries[0]}`,
52403
- fix: "Re-run install-opencode-plugin.sh — the pin points at a git+file or non-file source"
52424
+ fix: "Run `workit init` (or install-opencode-plugin.sh for a checkout) — replace git+file pins"
52425
+ };
52426
+ }
52427
+ if (first === "fragile-cache") {
52428
+ return {
52429
+ id: "stale_pin",
52430
+ status: "fail",
52431
+ detail: `workit pin points at a package-manager cache path: ${entries[0]}`,
52432
+ fix: 'Run `workit init` and select OpenCode — pin should be "@brainervirus/workit-opencode"'
52404
52433
  };
52405
52434
  }
52406
52435
  if (first === "missing-file") {
@@ -52408,7 +52437,7 @@ var checkStalePin = (res) => {
52408
52437
  id: "stale_pin",
52409
52438
  status: "fail",
52410
52439
  detail: `workit pin points at a missing file: ${entries[0]}`,
52411
- fix: "Re-run install-opencode-plugin.sh after restoring the checkout the pin references"
52440
+ fix: "Run `workit init` (or restore the checkout and re-run install-opencode-plugin.sh)"
52412
52441
  };
52413
52442
  }
52414
52443
  return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
@@ -52426,7 +52455,11 @@ var pluginMcpSelectors = (res) => {
52426
52455
  return null;
52427
52456
  return args.map(String).filter((a) => a.startsWith("--package="));
52428
52457
  };
52429
- var registryLatestVersion = (res) => {
52458
+ var isFloatingOpenCodeNpmPin = (entry) => {
52459
+ const s = entry.trim();
52460
+ return s === OPENCODE_NPM_PIN || s === `${OPENCODE_NPM_PIN}@latest`;
52461
+ };
52462
+ var registryLatestVersion = (res, pkgName = CURSOR_RUNTIME_PACKAGE) => {
52430
52463
  const seam = res.env.WORKIT_DOCTOR_STALE_REGISTRY_VERSION;
52431
52464
  if (typeof seam === "string" && seam) {
52432
52465
  return /^\d+(?:\.\d+){1,2}$/.test(seam) ? seam : null;
@@ -52435,7 +52468,7 @@ var registryLatestVersion = (res) => {
52435
52468
  if (!cmd)
52436
52469
  return null;
52437
52470
  try {
52438
- const r = spawnSync2(cmd, ["view", CURSOR_RUNTIME_PACKAGE, "version"], {
52471
+ const r = spawnSync2(cmd, ["view", pkgName, "version"], {
52439
52472
  encoding: "utf8",
52440
52473
  timeout: 20000,
52441
52474
  env: res.env
@@ -52450,12 +52483,100 @@ var installedPluginVersion = (res) => {
52450
52483
  const pkg = readJson(path11.join(res.cursorPluginDir, "package.json"));
52451
52484
  return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
52452
52485
  };
52486
+ var installedOpenCodeCacheVersion = (res) => {
52487
+ const pkg = readJson(path11.join(res.opencodePackageCacheDir, "node_modules", "@brainervirus", "workit-opencode", "package.json"));
52488
+ return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
52489
+ };
52490
+ var checkOpenCodePackageCache = (res) => {
52491
+ if (!existsSync9(res.opencodeConfig)) {
52492
+ return {
52493
+ id: "stale_install",
52494
+ status: "pass",
52495
+ detail: "no opencode config — package cache not inspected"
52496
+ };
52497
+ }
52498
+ const entries = pluginEntries(readJson(res.opencodeConfig));
52499
+ if (entries.length === 0) {
52500
+ return {
52501
+ id: "stale_install",
52502
+ status: "pass",
52503
+ detail: "no workit opencode pin — package cache not inspected"
52504
+ };
52505
+ }
52506
+ const pin = entries[0];
52507
+ if (pin.startsWith("file:") || pin.startsWith("git+file:")) {
52508
+ return {
52509
+ id: "stale_install",
52510
+ status: "pass",
52511
+ detail: "opencode checkout pin — package cache not used for npm resolution"
52512
+ };
52513
+ }
52514
+ if (!isFloatingOpenCodeNpmPin(pin)) {
52515
+ return {
52516
+ id: "stale_install",
52517
+ status: "pass",
52518
+ detail: `opencode pin ${pin} is an exact version — not compared to registry latest`
52519
+ };
52520
+ }
52521
+ const installed = installedOpenCodeCacheVersion(res);
52522
+ if (installed === null) {
52523
+ return {
52524
+ id: "stale_install",
52525
+ status: "pass",
52526
+ detail: "opencode @latest package cache empty — OpenCode will resolve on next launch"
52527
+ };
52528
+ }
52529
+ const expected = registryLatestVersion(res, OPENCODE_NPM_PIN);
52530
+ if (expected === null) {
52531
+ return {
52532
+ id: "registry_unreachable",
52533
+ status: "warn",
52534
+ registryProbed: true,
52535
+ detail: "registry_unreachable: cannot compare OpenCode @latest cache against published workit-opencode",
52536
+ fix: `Retry when npm is reachable, or remove ${res.opencodePackageCacheDir} and restart OpenCode to re-resolve`
52537
+ };
52538
+ }
52539
+ if (!semverAtLeast(installed, expected)) {
52540
+ return {
52541
+ id: "stale_install",
52542
+ status: "fail",
52543
+ registryProbed: true,
52544
+ detail: `stale_install: OpenCode @latest cache has workit-opencode ${installed} behind published ${expected}`,
52545
+ fix: `Remove ${res.opencodePackageCacheDir} and restart OpenCode — it re-resolves @latest on the next launch`
52546
+ };
52547
+ }
52548
+ return {
52549
+ id: "stale_install",
52550
+ status: "pass",
52551
+ registryProbed: true,
52552
+ detail: `OpenCode @latest cache workit-opencode ${installed} matches published ${expected}`
52553
+ };
52554
+ };
52453
52555
  var checkStaleInstall = (res) => {
52556
+ if (res.host === "opencode") {
52557
+ return checkOpenCodePackageCache(res);
52558
+ }
52454
52559
  if (res.host !== "cursor" && res.host !== "cli") {
52455
52560
  return {
52456
52561
  id: "stale_install",
52457
52562
  status: "pass",
52458
- detail: "cursor plugin not inspected on the opencode host"
52563
+ detail: "cursor plugin not inspected on this host"
52564
+ };
52565
+ }
52566
+ if (existsSync9(res.cursorPluginDir) && lstatSync(res.cursorPluginDir).isSymbolicLink()) {
52567
+ let target = "";
52568
+ try {
52569
+ target = readlinkSync(res.cursorPluginDir);
52570
+ } catch {
52571
+ target = "(unreadable)";
52572
+ }
52573
+ const n = target.replaceAll("\\", "/").toLowerCase();
52574
+ const fragile = n.includes("/caches/pnpm/dlx/") || n.includes("/_npx/") || n.includes("/.pacquet/") || n.includes("/library/caches/pnpm/");
52575
+ return {
52576
+ id: "stale_install",
52577
+ status: "fail",
52578
+ detail: fragile ? `stale_install: cursor plugin dir is a symlink into a package-manager cache (${target})` : `stale_install: cursor plugin dir is a symlink (${target}) — expected a real directory copy`,
52579
+ fix: "Run `workit init` and select Cursor — install must copy into ~/.cursor/plugins/local/workit"
52459
52580
  };
52460
52581
  }
52461
52582
  const canonicalMcp = cursorMcpServerEntry("").args.find((a) => a.startsWith("--package="));
@@ -52521,18 +52642,30 @@ var checkStaleInstall = (res) => {
52521
52642
  fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory with the current build"
52522
52643
  };
52523
52644
  }
52524
- return {
52645
+ const cursorOk = {
52525
52646
  id: "stale_install",
52526
52647
  status: "pass",
52527
52648
  registryProbed: true,
52528
52649
  detail: `installed local-dist workit-cursor ${installed} matches the published runtime ${expected}`
52529
52650
  };
52651
+ if (res.host === "cli") {
52652
+ const oc = checkOpenCodePackageCache(res);
52653
+ if (oc.status !== "pass")
52654
+ return oc;
52655
+ }
52656
+ return cursorOk;
52530
52657
  }
52531
- return {
52658
+ const cursorOk = {
52532
52659
  id: "stale_install",
52533
52660
  status: "pass",
52534
52661
  detail: installed === null ? "installed workit-cursor selectors are canonical" : `installed workit-cursor ${installed} is metadata on the canonical @latest install (fresh at launch)`
52535
52662
  };
52663
+ if (res.host === "cli") {
52664
+ const oc = checkOpenCodePackageCache(res);
52665
+ if (oc.status !== "pass")
52666
+ return oc;
52667
+ }
52668
+ return cursorOk;
52536
52669
  };
52537
52670
  var checkDuplicateRegistration = (res) => {
52538
52671
  const problems = [];
@@ -52657,7 +52790,9 @@ var checkCredentialMetadata = (res) => {
52657
52790
  tokenPaths.push(path11.join(res.configDir, "youtrack.token"));
52658
52791
  }
52659
52792
  const vcsJson = readJson(path11.join(res.configDir, "vcs.json"));
52660
- for (const key of ["gitlab", "github"]) {
52793
+ const active = typeof vcsJson?.provider === "string" ? vcsJson.provider.trim().toLowerCase() : null;
52794
+ const vcsKeys = active === "gitlab" || active === "github" ? [active] : ["gitlab", "github"];
52795
+ for (const key of vcsKeys) {
52661
52796
  const provider = vcsJson?.[key];
52662
52797
  if (provider && typeof provider === "object") {
52663
52798
  const tf = provider.tokenFile;
@@ -53517,7 +53652,15 @@ function adapterRoot(platform, res) {
53517
53652
  }
53518
53653
  return null;
53519
53654
  }
53520
- var opencodePin = (root) => {
53655
+ var isDevOpenCodeAdapterRoot = (root, dev) => {
53656
+ if (dev)
53657
+ return true;
53658
+ const norm = root.replaceAll("\\", "/");
53659
+ return /\/packages\/workit-opencode\/?$/.test(norm);
53660
+ };
53661
+ var resolveOpenCodePin = (root, opts = {}) => {
53662
+ if (!isDevOpenCodeAdapterRoot(root, opts.dev))
53663
+ return OPENCODE_NPM_PIN;
53521
53664
  for (const rel of ["src/plugin.ts", "dist/plugin.js"]) {
53522
53665
  const entry = path12.join(root, rel);
53523
53666
  if (existsSync10(entry))
@@ -53525,8 +53668,9 @@ var opencodePin = (root) => {
53525
53668
  }
53526
53669
  return null;
53527
53670
  };
53671
+ var opencodePin = (root, res) => resolveOpenCodePin(root, { dev: res.dev });
53528
53672
  function applyOpenCode(root, res) {
53529
- const pin = opencodePin(root);
53673
+ const pin = opencodePin(root, res);
53530
53674
  if (!pin) {
53531
53675
  return {
53532
53676
  platform: "opencode",
@@ -53613,30 +53757,35 @@ var preservedCursorRules = (src, dest) => {
53613
53757
  return preserved;
53614
53758
  };
53615
53759
  function copyPluginDir(src, dest) {
53760
+ const realSrc = realpathSync2(src);
53616
53761
  const marker = path12.join(dest, ".workit-root");
53617
- const synced = readFileSafe(marker)?.trim() === src && samePluginContent(src, dest);
53762
+ const destIsLink = existsSync10(dest) && lstatSync2(dest).isSymbolicLink();
53763
+ const synced = !destIsLink && readFileSafe(marker)?.trim() === realSrc && samePluginContent(realSrc, dest);
53618
53764
  if (synced)
53619
53765
  return "Skipped";
53620
53766
  const hadDir = existsSync10(dest);
53621
- const rules = preservedCursorRules(src, dest);
53767
+ const rules = preservedCursorRules(realSrc, dest);
53622
53768
  const parent = path12.dirname(dest);
53623
53769
  mkdirSync5(parent, { recursive: true });
53624
53770
  const swap = mkdtempSync(path12.join(parent, `.${path12.basename(dest)}.swap-`));
53625
53771
  const stage = path12.join(swap, "stage");
53626
53772
  const backup = path12.join(swap, "backup");
53627
53773
  try {
53628
- cpSync3(src, stage, {
53774
+ cpSync3(realSrc, stage, {
53629
53775
  recursive: true,
53630
- filter: (entry) => !path12.relative(src, entry).split(path12.sep).includes("node_modules")
53776
+ filter: (entry) => !path12.relative(realSrc, entry).split(path12.sep).includes("node_modules")
53631
53777
  });
53632
53778
  for (const [name, content] of rules) {
53633
53779
  mkdirSync5(path12.join(stage, "rules"), { recursive: true });
53634
53780
  writeFileSync7(path12.join(stage, "rules", name), content);
53635
53781
  }
53636
- writeFileSync7(path12.join(stage, ".workit-root"), src + `
53782
+ writeFileSync7(path12.join(stage, ".workit-root"), realSrc + `
53637
53783
  `, "utf8");
53638
- if (!samePluginContent(src, stage))
53784
+ if (!samePluginContent(realSrc, stage))
53639
53785
  throw new Error("staged adapter content is incomplete");
53786
+ if (lstatSync2(stage).isSymbolicLink()) {
53787
+ throw new Error("staged adapter resolved to a symlink — refusing fragile cache install");
53788
+ }
53640
53789
  if (hadDir)
53641
53790
  renameSync(dest, backup);
53642
53791
  try {
@@ -54394,7 +54543,7 @@ import os8 from "node:os";
54394
54543
  import path15 from "node:path";
54395
54544
 
54396
54545
  // packages/workit-core/src/core/uninstall.ts
54397
- import { existsSync as existsSync12, readFileSync as readFileSync11, realpathSync as realpathSync2, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
54546
+ import { existsSync as existsSync12, readFileSync as readFileSync11, realpathSync as realpathSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
54398
54547
  import os7 from "node:os";
54399
54548
  import path14 from "node:path";
54400
54549
  var resolveUninstallPaths = (options = {}) => {
@@ -54593,7 +54742,7 @@ var canonicalRemoveDirAllowed = (actionPath, res) => {
54593
54742
  return false;
54594
54743
  }
54595
54744
  try {
54596
- return realpathSync2(actionPath) === realpathSync2(expected);
54745
+ return realpathSync3(actionPath) === realpathSync3(expected);
54597
54746
  } catch {
54598
54747
  return true;
54599
54748
  }
@@ -56430,7 +56579,7 @@ import { createInterface as createInterface2 } from "node:readline/promises";
56430
56579
 
56431
56580
  // packages/workit-core/src/core.ts
56432
56581
  import { spawnSync as spawnSync4 } from "node:child_process";
56433
- import { existsSync as existsSync16, realpathSync as realpathSync7 } from "node:fs";
56582
+ import { existsSync as existsSync16, realpathSync as realpathSync8 } from "node:fs";
56434
56583
  import path22 from "node:path";
56435
56584
 
56436
56585
  // packages/workit-core/src/core/task-store.ts
@@ -59144,7 +59293,7 @@ async function runAuthorizedExternalAction(input, effect) {
59144
59293
  };
59145
59294
  }
59146
59295
  // packages/workit-core/src/core/task-engine.ts
59147
- import { realpathSync as realpathSync6 } from "node:fs";
59296
+ import { realpathSync as realpathSync7 } from "node:fs";
59148
59297
 
59149
59298
  // packages/workit-core/src/core/policy-resolver.ts
59150
59299
  var resolverInputSchema = object({
@@ -59988,7 +60137,7 @@ class WorkitCore {
59988
60137
  }
59989
60138
  contextRootError() {
59990
60139
  try {
59991
- if (realpathSync6(this.context.root) !== this.store.root)
60140
+ if (realpathSync7(this.context.root) !== this.store.root)
59992
60141
  return failure("invalid_input", "operation context root does not match the task store root");
59993
60142
  } catch {
59994
60143
  return failure("invalid_input", "operation context root cannot be resolved");
@@ -61217,7 +61366,7 @@ class WorkitCore {
61217
61366
  if (view.task.workspaceId !== view.workspace.id)
61218
61367
  return failure("invalid_input", "task and workspace bindings are invalid");
61219
61368
  try {
61220
- if (realpathSync6(view.workspace.root) !== this.store.root)
61369
+ if (realpathSync7(view.workspace.root) !== this.store.root)
61221
61370
  return failure("invalid_input", "task view root does not match the task store");
61222
61371
  } catch {
61223
61372
  return failure("invalid_input", "task view root cannot be resolved");
@@ -61486,7 +61635,7 @@ function resolveGitRevision(root, value) {
61486
61635
  }
61487
61636
  }
61488
61637
  function resolveInside(root, candidate) {
61489
- const base = realpathSync7(root);
61638
+ const base = realpathSync8(root);
61490
61639
  const target = path22.resolve(base, candidate);
61491
61640
  if (target !== base && !target.startsWith(base + path22.sep)) {
61492
61641
  throw new Error("path must stay inside repository root");
@@ -61494,14 +61643,14 @@ function resolveInside(root, candidate) {
61494
61643
  let ancestor = target;
61495
61644
  while (!existsSync16(ancestor))
61496
61645
  ancestor = path22.dirname(ancestor);
61497
- const canonicalAncestor = realpathSync7(ancestor);
61646
+ const canonicalAncestor = realpathSync8(ancestor);
61498
61647
  if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path22.sep)) {
61499
61648
  throw new Error("path must stay inside repository root");
61500
61649
  }
61501
61650
  return target;
61502
61651
  }
61503
61652
  function run(root, executable, args, env = {}) {
61504
- const cwd = realpathSync7(root);
61653
+ const cwd = realpathSync8(root);
61505
61654
  const result = spawnSync4(executable, args, {
61506
61655
  cwd,
61507
61656
  encoding: "utf8",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "private": false,
5
5
  "description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
6
6
  "keywords": [
@@ -37,9 +37,9 @@
37
37
  "typecheck": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
- "@brainervirus/workit-core": "^1.0.3",
41
- "@brainervirus/workit-cursor": "^1.0.3",
42
- "@brainervirus/workit-opencode": "^1.0.3",
40
+ "@brainervirus/workit-core": "^1.0.5",
41
+ "@brainervirus/workit-cursor": "^1.0.5",
42
+ "@brainervirus/workit-opencode": "^1.0.5",
43
43
  "@inkjs/ui": "2.0.0",
44
44
  "ink": "7.1.1",
45
45
  "react": "19.2.8"