@brainervirus/workit-cli 8.40.6 → 8.40.7

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 +93 -26
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -6389,7 +6389,7 @@ var init_zod = __esm(() => {
6389
6389
  // packages/workit-core/src/core/workspaces.ts
6390
6390
  import { spawnSync as spawnSync2 } from "node:child_process";
6391
6391
  import { createHash } from "node:crypto";
6392
- import { existsSync as existsSync2, readFileSync as readFileSync2, realpathSync } from "node:fs";
6392
+ import { existsSync as existsSync2, lstatSync, readFileSync as readFileSync2, realpathSync } from "node:fs";
6393
6393
  import path2 from "node:path";
6394
6394
  function workspaceDefaultTarget(cwd, globalDefault) {
6395
6395
  const ws = resolveRuntimeWorkspaceVcs(cwd);
@@ -6566,7 +6566,16 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
6566
6566
  if (!gitDir || !common)
6567
6567
  return failed;
6568
6568
  let main = null;
6569
- if (path2.resolve(gitDir) !== path2.resolve(common)) {
6569
+ if (path2.resolve(gitDir) === path2.resolve(common)) {
6570
+ const real = realpathOf(common);
6571
+ if (!ownGitDir(path2.join(dir, ".git"), real)) {
6572
+ const owner = gitDirOwner(real);
6573
+ if (owner === null)
6574
+ return Error(`${cwd} uses the repository at ${real}, owned by no checkout workit can name`);
6575
+ if (owner !== realpathOf(dir))
6576
+ main = owner;
6577
+ }
6578
+ } else {
6570
6579
  const list = git(["worktree", "list", "--porcelain"]);
6571
6580
  if (list === null)
6572
6581
  return failed;
@@ -6575,6 +6584,20 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
6575
6584
  const probe = { main, superproject: superproject || null };
6576
6585
  probes.set(cwd, probe);
6577
6586
  return probe;
6587
+ }, ownGitDir = (dotGit, real) => {
6588
+ try {
6589
+ return lstatSync(dotGit).isDirectory() && realpathOf(dotGit) === real;
6590
+ } catch {
6591
+ return false;
6592
+ }
6593
+ }, gitDirOwner = (real) => {
6594
+ const parts = real.split(/[\\/]/u);
6595
+ const at = parts.lastIndexOf(".git");
6596
+ if (at < 1)
6597
+ return null;
6598
+ const rest = parts.slice(at + 1);
6599
+ const module = rest[0] === "modules" || rest[0] === "worktrees" && rest[2] === "modules";
6600
+ return rest.length === 0 || module ? parts.slice(0, at).join(path2.sep) || path2.sep : null;
6578
6601
  }, mainCheckoutOf = (cwd) => {
6579
6602
  const probe = probeCheckout(cwd);
6580
6603
  return probe instanceof Error ? null : probe?.main ?? null;
@@ -9352,7 +9375,7 @@ var package_default;
9352
9375
  var init_package = __esm(() => {
9353
9376
  package_default = {
9354
9377
  name: "@brainervirus/workit-cli",
9355
- version: "8.40.6",
9378
+ version: "8.40.7",
9356
9379
  private: false,
9357
9380
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9358
9381
  keywords: [
@@ -9390,13 +9413,13 @@ var init_package = __esm(() => {
9390
9413
  },
9391
9414
  dependencies: {
9392
9415
  "@babel/parser": "7.29.9",
9393
- "@brainervirus/workit-cursor": "^8.40.6",
9416
+ "@brainervirus/workit-cursor": "^8.40.7",
9394
9417
  "@inkjs/ui": "2.0.0",
9395
9418
  ink: "7.1.1",
9396
9419
  react: "19.2.8"
9397
9420
  },
9398
9421
  devDependencies: {
9399
- "@brainervirus/workit-core": "^8.40.6"
9422
+ "@brainervirus/workit-core": "^8.40.7"
9400
9423
  },
9401
9424
  engines: {
9402
9425
  node: ">=24"
@@ -9662,7 +9685,7 @@ import {
9662
9685
  closeSync,
9663
9686
  fchmodSync,
9664
9687
  fsyncSync,
9665
- lstatSync,
9688
+ lstatSync as lstatSync2,
9666
9689
  mkdirSync as mkdirSync3,
9667
9690
  openSync,
9668
9691
  renameSync,
@@ -9686,7 +9709,7 @@ function writeFileAtomic(file, content, mode) {
9686
9709
  const root = path10.parse(parent).root;
9687
9710
  for (;; ) {
9688
9711
  try {
9689
- if (lstatSync(parent).isSymbolicLink())
9712
+ if (lstatSync2(parent).isSymbolicLink())
9690
9713
  throw new Error(`symlinked write path: ${parent}`);
9691
9714
  } catch (error) {
9692
9715
  if (error.code !== "ENOENT")
@@ -9701,7 +9724,7 @@ function writeFileAtomic(file, content, mode) {
9701
9724
  mkdirSync3(directory, { recursive: true });
9702
9725
  let existing = null;
9703
9726
  try {
9704
- existing = lstatSync(absolute);
9727
+ existing = lstatSync2(absolute);
9705
9728
  } catch (error) {
9706
9729
  if (error.code !== "ENOENT")
9707
9730
  throw error;
@@ -18797,6 +18820,7 @@ var SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLARATIONS
18797
18820
  let here = dir;
18798
18821
  const config = [...inherited];
18799
18822
  let gitDir = env.GIT_DIR;
18823
+ let from = "GIT_DIR";
18800
18824
  let index = 0;
18801
18825
  for (;index < words.length; index++) {
18802
18826
  const word = words[index];
@@ -18804,18 +18828,21 @@ var SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLARATIONS
18804
18828
  here = words[index + 1] ? joinDir(here, words[++index]) : here;
18805
18829
  else if (GIT_CONFIG_OPTIONS.has(word)) {
18806
18830
  if (word === "--git-dir")
18807
- gitDir = words[index + 1];
18831
+ [gitDir, from] = [words[index + 1], "--git-dir"];
18808
18832
  if (words[index + 1] !== undefined)
18809
18833
  config.push(word, words[++index]);
18810
18834
  } else if (/^--(?:config-env|git-dir)=/.test(word)) {
18811
18835
  if (word.startsWith("--git-dir="))
18812
- gitDir = word.slice("--git-dir=".length);
18836
+ [gitDir, from] = [word.slice("--git-dir=".length), "--git-dir"];
18813
18837
  config.push(word);
18814
18838
  } else if (GIT_VALUE_OPTIONS.has(word))
18815
18839
  index++;
18816
18840
  else if (!word.startsWith("-"))
18817
18841
  break;
18818
18842
  }
18843
+ if (env.GIT_COMMON_DIR)
18844
+ [gitDir, from] = [env.GIT_COMMON_DIR, "GIT_COMMON_DIR"];
18845
+ const known = here !== undefined;
18819
18846
  if (gitDir)
18820
18847
  here = joinDir(here, gitDir.replace(/(?:^|[\\/]+)\.git[\\/]*$/, "") || ".");
18821
18848
  return {
@@ -18824,7 +18851,8 @@ var SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLARATIONS
18824
18851
  args: words.slice(index),
18825
18852
  ...config.length ? { config } : {},
18826
18853
  ...Object.keys(env).length ? { env } : {},
18827
- ...stdin === undefined ? {} : { stdin }
18854
+ ...stdin === undefined ? {} : { stdin },
18855
+ ...known && here === undefined ? { redirect: from } : {}
18828
18856
  };
18829
18857
  }, RECENT, LAUNCHERS, WORKIT_PACKAGE, PACKAGE_RUNNERS, OUTPUT_FILTERS, WORKIT_GLOBAL, PUSH_VALUE_OPTIONS, VALUE_OPTIONS, API_VALUES, API_FIELDS, GIT_COMMANDS;
18830
18858
  var init_raw_git = __esm(() => {
@@ -66622,7 +66650,7 @@ import { spawnSync as spawnSync15 } from "node:child_process";
66622
66650
  import {
66623
66651
  chmodSync,
66624
66652
  existsSync as existsSync15,
66625
- lstatSync as lstatSync4,
66653
+ lstatSync as lstatSync5,
66626
66654
  mkdirSync as mkdirSync5,
66627
66655
  readFileSync as readFileSync15,
66628
66656
  renameSync as renameSync3,
@@ -66833,7 +66861,7 @@ exit 0
66833
66861
  }
66834
66862
  }, exists = (file) => {
66835
66863
  try {
66836
- lstatSync4(file);
66864
+ lstatSync5(file);
66837
66865
  return true;
66838
66866
  } catch {
66839
66867
  return false;
@@ -67667,7 +67695,7 @@ import { spawnSync as spawnSync16 } from "node:child_process";
67667
67695
  import { createHash as createHash14 } from "node:crypto";
67668
67696
  import {
67669
67697
  existsSync as existsSync17,
67670
- lstatSync as lstatSync5,
67698
+ lstatSync as lstatSync6,
67671
67699
  mkdirSync as mkdirSync8,
67672
67700
  mkdtempSync,
67673
67701
  readdirSync as readdirSync10,
@@ -68145,7 +68173,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68145
68173
  const want = stampCodexAgent(readFileSync18(path39.join(source, file), "utf8"), version);
68146
68174
  let link = false;
68147
68175
  try {
68148
- link = lstatSync5(dest).isSymbolicLink();
68176
+ link = lstatSync6(dest).isSymbolicLink();
68149
68177
  } catch {
68150
68178
  link = false;
68151
68179
  }
@@ -68872,7 +68900,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68872
68900
  detail: "cursor plugin not inspected on this host"
68873
68901
  };
68874
68902
  }
68875
- if (existsSync17(res.cursorPluginDir) && lstatSync5(res.cursorPluginDir).isSymbolicLink()) {
68903
+ if (existsSync17(res.cursorPluginDir) && lstatSync6(res.cursorPluginDir).isSymbolicLink()) {
68876
68904
  let target = "";
68877
68905
  try {
68878
68906
  target = readlinkSync2(res.cursorPluginDir);
@@ -70086,7 +70114,7 @@ import {
70086
70114
  copyFileSync as copyFileSync5,
70087
70115
  cpSync as cpSync4,
70088
70116
  existsSync as existsSync18,
70089
- lstatSync as lstatSync6,
70117
+ lstatSync as lstatSync7,
70090
70118
  mkdirSync as mkdirSync9,
70091
70119
  mkdtempSync as mkdtempSync2,
70092
70120
  readFileSync as readFileSync19,
@@ -70539,7 +70567,7 @@ function applyOpenCode(root, res) {
70539
70567
  function copyPluginDir(src, dest) {
70540
70568
  const realSrc = realpathSync9(src);
70541
70569
  const marker = path40.join(dest, ".workit-root");
70542
- const destIsLink = existsSync18(dest) && lstatSync6(dest).isSymbolicLink();
70570
+ const destIsLink = existsSync18(dest) && lstatSync7(dest).isSymbolicLink();
70543
70571
  const synced = !destIsLink && readFileSafe(marker)?.trim() === realSrc && samePluginContent(realSrc, dest, dest);
70544
70572
  if (synced)
70545
70573
  return "Skipped";
@@ -70566,7 +70594,7 @@ function copyPluginDir(src, dest) {
70566
70594
  `, "utf8");
70567
70595
  if (!samePluginContent(realSrc, stage, dest))
70568
70596
  throw new Error("staged adapter content is incomplete");
70569
- if (lstatSync6(stage).isSymbolicLink()) {
70597
+ if (lstatSync7(stage).isSymbolicLink()) {
70570
70598
  throw new Error("staged adapter resolved to a symlink — refusing fragile cache install");
70571
70599
  }
70572
70600
  if (hadDir)
@@ -75660,7 +75688,7 @@ var init_apply = __esm(() => {
75660
75688
  });
75661
75689
 
75662
75690
  // packages/workit-cli/src/upgrade/plan.ts
75663
- import { existsSync as existsSync23, mkdtempSync as mkdtempSync3, rmSync as rmSync8, lstatSync as lstatSync7, readFileSync as readFileSync23 } from "node:fs";
75691
+ import { existsSync as existsSync23, mkdtempSync as mkdtempSync3, rmSync as rmSync8, lstatSync as lstatSync8, readFileSync as readFileSync23 } from "node:fs";
75664
75692
  import path47 from "node:path";
75665
75693
  import os17 from "node:os";
75666
75694
  function previewUpgrade(hosts = HOSTS2, deps = {}) {
@@ -75970,7 +75998,7 @@ var codexRegistered = (configFile) => {
75970
75998
  }
75971
75999
  const packageFile = path47.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
75972
76000
  const installed = objectOrNull(packageFile);
75973
- if (installed?.name !== "@brainervirus/workit-cli" || lstatSync7(path47.dirname(packageFile)).isSymbolicLink()) {
76001
+ if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path47.dirname(packageFile)).isSymbolicLink()) {
75974
76002
  plan.skipped.push({
75975
76003
  host: "cli",
75976
76004
  reason: "no managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
@@ -106949,7 +106977,7 @@ var init_audit = __esm(() => {
106949
106977
  import { spawn as spawn2 } from "node:child_process";
106950
106978
  import {
106951
106979
  existsSync as existsSync29,
106952
- lstatSync as lstatSync8,
106980
+ lstatSync as lstatSync9,
106953
106981
  mkdirSync as mkdirSync12,
106954
106982
  mkdtempSync as mkdtempSync4,
106955
106983
  readdirSync as readdirSync15,
@@ -107059,7 +107087,7 @@ function removeStaleCopies(tmp = os23.tmpdir()) {
107059
107087
  continue;
107060
107088
  const dir = path72.join(tmp, name);
107061
107089
  try {
107062
- const stat = lstatSync8(dir);
107090
+ const stat = lstatSync9(dir);
107063
107091
  if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
107064
107092
  continue;
107065
107093
  const pid = Number(readFileSync30(path72.join(dir, PID_FILE), "utf8"));
@@ -107125,7 +107153,7 @@ function copySymlink(repo, tree, from, to) {
107125
107153
  function writeInside(copy, file, content) {
107126
107154
  const target = path72.join(copy, file);
107127
107155
  try {
107128
- const stat = lstatSync8(target);
107156
+ const stat = lstatSync9(target);
107129
107157
  if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path72.dirname(target))))
107130
107158
  return false;
107131
107159
  } catch {
@@ -107159,7 +107187,7 @@ function copyWorkingTree(repo) {
107159
107187
  const from = path72.join(repo, relative);
107160
107188
  let stat;
107161
107189
  try {
107162
- stat = lstatSync8(from);
107190
+ stat = lstatSync9(from);
107163
107191
  } catch {
107164
107192
  continue;
107165
107193
  }
@@ -107956,10 +107984,28 @@ var init_handoff = __esm(() => {
107956
107984
  init_output();
107957
107985
  });
107958
107986
 
107987
+ // packages/workit-cli/src/main.ts
107988
+ import path77 from "node:path";
107989
+
107990
+ // packages/workit-core/src/git/env-redirect.ts
107991
+ var GIT_REDIRECT_ENV = [
107992
+ "GIT_DIR",
107993
+ "GIT_WORK_TREE",
107994
+ "GIT_COMMON_DIR",
107995
+ "GIT_INDEX_FILE",
107996
+ "GIT_OBJECT_DIRECTORY",
107997
+ "GIT_ALTERNATE_OBJECT_DIRECTORIES",
107998
+ "GIT_NAMESPACE"
107999
+ ];
108000
+ var gitRedirectsIn = (...envs) => GIT_REDIRECT_ENV.filter((name) => envs.some((env) => env[name] !== undefined));
108001
+ var gitRedirectRefusal = (names, verb, cwd) => ({
108002
+ error: `git_env_redirect: ${names.join(", ")} ${names.length === 1 ? "is" : "are"} set, so git would act on the repository ${names.length === 1 ? "it names" : "they name"} while grants are checked for ${cwd}; workit ${verb} does not run`,
108003
+ unblock: `unset ${names.join(" ")}, or cd into the repository and run workit ${verb} there`
108004
+ });
108005
+
107959
108006
  // packages/workit-cli/src/main.ts
107960
108007
  init_host_session();
107961
108008
  init_package();
107962
- import path77 from "node:path";
107963
108009
 
107964
108010
  // packages/workit-cli/src/verbs/registry.ts
107965
108011
  var TASK_FAMILY_NAMES = [
@@ -108942,6 +108988,14 @@ async function main(argv, overrides = {}, options = {}) {
108942
108988
  const checked = checkFlags(entry, ended);
108943
108989
  if ("error" in checked)
108944
108990
  return emit(routed, fail2("invalid_input", checked.error, { unblock: checked.unblock }));
108991
+ const gated = gatedVerb(entry, checked.args);
108992
+ if (gated) {
108993
+ const redirects = gitRedirectsIn(routed.env, process.env);
108994
+ if (redirects.length) {
108995
+ const refusal = gitRedirectRefusal(redirects, gated, routed.cwd);
108996
+ return emit(routed, fail2("blocked", refusal.error, { unblock: refusal.unblock }));
108997
+ }
108998
+ }
108945
108999
  if (parsed.cwd !== null) {
108946
109000
  try {
108947
109001
  process.chdir(routed.cwd);
@@ -108967,6 +109021,19 @@ async function main(argv, overrides = {}, options = {}) {
108967
109021
  const outcome = verbWord ? OUTCOMES2[`${entry.name} ${verbWord}`] : undefined;
108968
109022
  return withFailureLine(io, command, route, outcome);
108969
109023
  }
109024
+ var GRANT_GATED = {
109025
+ git: new Set(["push"]),
109026
+ release: new Set(["start", "finish", "publish"]),
109027
+ pr: new Set(["create", "merge", "ready", "edit"]),
109028
+ stack: new Set(["sync", "restack", "land"]),
109029
+ ci: new Set(["rerun"])
109030
+ };
109031
+ var gatedVerb = (entry, args) => {
109032
+ const word = firstWord(args);
109033
+ const sub = word === undefined ? undefined : findSubcommand(entry, word);
109034
+ const name = sub?.name ?? word;
109035
+ return name !== undefined && GRANT_GATED[entry.name]?.has(name) ? `${entry.name} ${name}` : null;
109036
+ };
108970
109037
  var OUTCOMES2 = {
108971
109038
  "pr merge": "PR not merged",
108972
109039
  "pr create": "PR not created",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "8.40.6",
3
+ "version": "8.40.7",
4
4
  "private": false,
5
5
  "description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
6
6
  "keywords": [
@@ -38,13 +38,13 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/parser": "7.29.9",
41
- "@brainervirus/workit-cursor": "^8.40.6",
41
+ "@brainervirus/workit-cursor": "^8.40.7",
42
42
  "@inkjs/ui": "2.0.0",
43
43
  "ink": "7.1.1",
44
44
  "react": "19.2.8"
45
45
  },
46
46
  "devDependencies": {
47
- "@brainervirus/workit-core": "^8.40.6"
47
+ "@brainervirus/workit-core": "^8.40.7"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=24"