@brainervirus/workit-cli 8.39.4 → 8.40.1

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 +218 -48
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -9317,7 +9317,7 @@ var package_default;
9317
9317
  var init_package = __esm(() => {
9318
9318
  package_default = {
9319
9319
  name: "@brainervirus/workit-cli",
9320
- version: "8.39.4",
9320
+ version: "8.40.1",
9321
9321
  private: false,
9322
9322
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9323
9323
  keywords: [
@@ -9355,13 +9355,13 @@ var init_package = __esm(() => {
9355
9355
  },
9356
9356
  dependencies: {
9357
9357
  "@babel/parser": "7.29.9",
9358
- "@brainervirus/workit-cursor": "^8.39.4",
9358
+ "@brainervirus/workit-cursor": "^8.40.1",
9359
9359
  "@inkjs/ui": "2.0.0",
9360
9360
  ink: "7.1.1",
9361
9361
  react: "19.2.8"
9362
9362
  },
9363
9363
  devDependencies: {
9364
- "@brainervirus/workit-core": "^8.39.4"
9364
+ "@brainervirus/workit-core": "^8.40.1"
9365
9365
  },
9366
9366
  engines: {
9367
9367
  node: ">=24"
@@ -21793,13 +21793,51 @@ function emit(io, envelope, human) {
21793
21793
  }
21794
21794
  return exitCodeFor(envelope.code);
21795
21795
  }
21796
+ async function withFailureLine(io, command, run, outcome) {
21797
+ let wrote = false;
21798
+ let reason = null;
21799
+ const code = await run({
21800
+ ...io,
21801
+ stdout: (text) => {
21802
+ wrote ||= text.length > 0;
21803
+ io.stdout(text);
21804
+ },
21805
+ stderr: (text) => {
21806
+ wrote ||= text.length > 0;
21807
+ reason ??= /^workit: ([a-z][a-z_]*):/u.exec(text)?.[1] ?? null;
21808
+ io.stderr(text);
21809
+ }
21810
+ });
21811
+ if (code === 0)
21812
+ return code;
21813
+ if (outcome)
21814
+ io.stderr(`workit: error: ${outcome} (${reason ?? EXIT_NAMES[code] ?? "failed"}, exit ${code})
21815
+ `);
21816
+ else if (!wrote)
21817
+ io.stderr(`workit: error: ${command} failed (exit ${code})
21818
+ `);
21819
+ return code;
21820
+ }
21796
21821
  var EXIT, EXIT_BY_CODE, exitCodeFor = (code) => EXIT_BY_CODE[code], ok2 = (data) => ({ ok: true, code: "ok", data }), fail2 = (code, error, extra = {}) => ({
21797
21822
  ok: false,
21798
21823
  code,
21799
21824
  data: extra.data ?? {},
21800
21825
  error,
21801
21826
  ...extra.unblock ? { unblock: extra.unblock } : {}
21802
- });
21827
+ }), EXIT_NAMES, flushStreams = async (streams = [process.stdout, process.stderr], timeoutMs = 2000) => {
21828
+ await Promise.all(streams.map((stream) => new Promise((resolve) => {
21829
+ const timer = setTimeout(resolve, timeoutMs);
21830
+ const done = () => {
21831
+ clearTimeout(timer);
21832
+ resolve();
21833
+ };
21834
+ try {
21835
+ stream.write("", done);
21836
+ } catch {
21837
+ done();
21838
+ }
21839
+ })));
21840
+ };
21803
21841
  var init_output = __esm(() => {
21804
21842
  EXIT = {
21805
21843
  ok: 0,
@@ -21820,6 +21858,13 @@ var init_output = __esm(() => {
21820
21858
  pending: EXIT.busy,
21821
21859
  unavailable: EXIT.unavailable
21822
21860
  };
21861
+ EXIT_NAMES = {
21862
+ 1: "failed",
21863
+ 2: "invalid_input",
21864
+ 3: "blocked",
21865
+ 4: "busy",
21866
+ 5: "unavailable"
21867
+ };
21823
21868
  });
21824
21869
 
21825
21870
  // packages/workit-cli/src/verbs/task.ts
@@ -77034,6 +77079,7 @@ var init_uninstall2 = __esm(() => {
77034
77079
  // packages/workit-cli/src/verbs/grant.ts
77035
77080
  var exports_grant = {};
77036
77081
  __export(exports_grant, {
77082
+ agentMarker: () => agentMarker,
77037
77083
  run: () => run10,
77038
77084
  runGrant: () => runGrant
77039
77085
  });
@@ -77372,7 +77418,90 @@ function set2(argv, io) {
77372
77418
  `${name}: ${changes.map((change) => change.path.join(".")).join(", ")} updated in ${written(data.path, data.backup)}`
77373
77419
  ]);
77374
77420
  }
77375
- async function runWorkspace(argv, io) {
77421
+ async function rm(argv, io, deps) {
77422
+ const [name, extra] = argv;
77423
+ if (!name)
77424
+ return usage3(io, "rm needs <name>");
77425
+ if (extra)
77426
+ return usage3(io, `unexpected argument ${extra}`);
77427
+ const current = load(io);
77428
+ if (typeof current === "number")
77429
+ return current;
77430
+ const entries = entriesOf(current);
77431
+ const removed = entries.find((entry) => entry.name === name);
77432
+ if (!removed)
77433
+ return emit(io, fail2("not_found", `no workspace named "${name}" in ${current.path}`));
77434
+ const remaining = entries.filter((entry) => entry !== removed);
77435
+ if (remaining.length === 0)
77436
+ return emit(io, fail2("blocked", `"${name}" is the last workspace in ${current.path}: it holds your vcs, policies and grants, and without it every folder falls back to the defaults; workspace rm does not remove it`, {
77437
+ unblock: `add the workspace that should replace it first (workit workspace add <name> --glob <g> --from ${name}), or edit ${current.path} in your own editor`
77438
+ }));
77439
+ const before = deliveredCeilingOf(removed);
77440
+ const defaults = ceilingOf({});
77441
+ const nothing = {
77442
+ grants: Object.fromEntries(GRANT_KINDS.map((kind) => [kind, false])),
77443
+ endpoint: DEFAULT_ENDPOINT,
77444
+ verification: STRICTNESS[0]
77445
+ };
77446
+ const specificity = globSpecificity(removed.glob);
77447
+ const raised = [
77448
+ { taker: "defaults", kinds: raisedKinds(before, defaults), reason: "no entry matches" },
77449
+ ...remaining.map((entry) => ({
77450
+ taker: entry.name,
77451
+ kinds: raisedKinds(before, ceilingOf(entry)),
77452
+ reason: "may match a folder it covered"
77453
+ })),
77454
+ ...remaining.filter((entry) => globSpecificity(entry.glob) === specificity).map((entry) => ({
77455
+ taker: entry.name,
77456
+ kinds: raisedKinds(nothing, ceilingOf(entry)),
77457
+ reason: "equally specific: a folder both matched was ambiguous, with nothing granted"
77458
+ }))
77459
+ ].filter((raise) => raise.kinds.length > 0);
77460
+ if (raised.length > 0) {
77461
+ const kinds = [...new Set(raised.flatMap((raise) => raise.kinds))];
77462
+ const detail = raised.map((raise) => `${raise.taker} (${raise.reason}): ${raise.kinds.join(", ")}`).join("; ");
77463
+ const agent = agentMarker(io.env);
77464
+ if (!deps.interactive() || agent)
77465
+ return emit(io, fail2("blocked", `grant_raise_refused: removing "${name}" may raise ${kinds.join(", ")} for the folders it covered (${detail}); that needs the user at an interactive terminal${agent ? ` (this shell belongs to an agent: ${agent} is set)` : ""}; grants are never raised headless`, {
77466
+ unblock: `ask the user to run, in a terminal outside the agent host (not Claude Code's \`!\` prefix or an agent shell): workit workspace rm ${name}`
77467
+ }));
77468
+ const answer = await askOrCancel(io, () => deps.ask(`Removing workspace "${name}" may raise ${kinds.join(", ")} for the folders it covered (${detail}). An agent there may then do more without asking. Type the workspace name to confirm: `));
77469
+ if (answer === null)
77470
+ return cancelled(io);
77471
+ if (answer.trim() !== name)
77472
+ return emit(io, fail2("blocked", "workspace removal not confirmed; nothing was written"));
77473
+ }
77474
+ const result = save(current, remaining);
77475
+ if (!result.ok)
77476
+ return emit(io, fail2("invalid_input", result.error));
77477
+ const at = globRoot(removed.glob);
77478
+ let covers;
77479
+ try {
77480
+ covers = { at, workspace: resolveWorkspaceFromEntries(at, remaining)?.name ?? null };
77481
+ } catch (error) {
77482
+ covers = { at, workspace: null, error: error instanceof Error ? error.message : String(error) };
77483
+ }
77484
+ const coveringCeiling = ceilingOf(remaining.find((entry) => entry.name === covers.workspace));
77485
+ return emit(io, ok2({
77486
+ path: result.path,
77487
+ backup: result.backup,
77488
+ removed,
77489
+ covers: {
77490
+ ...covers,
77491
+ grants: coveringCeiling.grants,
77492
+ defaultEndpoint: coveringCeiling.endpoint,
77493
+ verification: coveringCeiling.verification
77494
+ },
77495
+ takers: overlappingEntries(removed.glob, remaining).map((entry) => entry.name),
77496
+ raises: raised
77497
+ }), (data) => [
77498
+ `${name} (${removed.glob}) removed from ${written(data.path, data.backup)}`,
77499
+ data.covers.error ? ` ${data.covers.at}: ${data.covers.error}` : ` ${data.covers.at} is now ${data.covers.workspace ? `workspace ${data.covers.workspace}` : "under the defaults (no workspace)"}: ${GRANT_KINDS.map((kind) => `${kind}=${String(data.covers.grants[kind])}`).join(" ")}; default endpoint ${data.covers.defaultEndpoint}; verification ${data.covers.verification}`,
77500
+ ...data.takers.length ? [` entries whose globs may cover its other folders: ${data.takers.join(", ")}`] : [],
77501
+ " workit workspace list --cwd <folder> shows which entry applies to a folder"
77502
+ ]);
77503
+ }
77504
+ async function runWorkspace(argv, io, deps = defaultDeps2) {
77376
77505
  const [sub, ...rest] = argv.filter((arg) => arg !== "--json" && arg !== "--");
77377
77506
  if (sub === undefined || sub === "list")
77378
77507
  return list2(rest, io);
@@ -77380,13 +77509,25 @@ async function runWorkspace(argv, io) {
77380
77509
  return add2(rest, io);
77381
77510
  if (sub === "set")
77382
77511
  return set2(rest, io);
77512
+ if (sub === "rm")
77513
+ return rm(rest, io, deps);
77383
77514
  return usage3(io, `unknown subcommand "${sub}"`);
77384
77515
  }
77385
- var USAGE5 = "workit workspace list | workspace add <name> --glob <g> [--from <parent>] | workspace set <name> <key>=<value>…", INHERITED_KEYS, GRANT_KEYS, SCOPE_KEYS, SETTABLE_KEYS, SEGMENT, UNSAFE_SEGMENTS, ceilingOf = (entry) => ({
77516
+ var USAGE5 = "workit workspace list | workspace add <name> --glob <g> [--from <parent>] | workspace set <name> <key>=<value>… | workspace rm <name>", INHERITED_KEYS, GRANT_KEYS, SCOPE_KEYS, SETTABLE_KEYS, SEGMENT, UNSAFE_SEGMENTS, ceilingOf = (entry) => ({
77386
77517
  grants: { ...DEFAULT_GRANTS, ...configuredGrants(entry).grants },
77387
77518
  endpoint: isDefaultEndpoint(entry?.defaultEndpoint) ? entry.defaultEndpoint : DEFAULT_ENDPOINT,
77388
77519
  verification: verificationOf(entry)
77389
- }), STRICTNESS, looser = (current, next) => STRICTNESS.indexOf(next) > STRICTNESS.indexOf(current), shadowedCeiling = (shadowed) => {
77520
+ }), deliveredCeilingOf = (entry) => {
77521
+ const ceiling = ceilingOf(entry);
77522
+ const account = entry.vcs?.account;
77523
+ if (Object.keys(configuredGrants(entry).grants).length === 0 || account)
77524
+ return ceiling;
77525
+ return {
77526
+ grants: Object.fromEntries(GRANT_KINDS.map((kind) => [kind, false])),
77527
+ endpoint: DEFAULT_ENDPOINT,
77528
+ verification: ceiling.verification
77529
+ };
77530
+ }, STRICTNESS, looser = (current, next) => STRICTNESS.indexOf(next) > STRICTNESS.indexOf(current), shadowedCeiling = (shadowed) => {
77390
77531
  if (shadowed.length === 0)
77391
77532
  return null;
77392
77533
  const ceilings = shadowed.map(ceilingOf);
@@ -77406,7 +77547,11 @@ var USAGE5 = "workit workspace list | workspace add <name> --glob <g> [--from <p
77406
77547
  ...Object.keys(autonomy).length ? { autonomy } : {},
77407
77548
  ...looser(shadowed.verification, DEFAULT_VERIFICATION) ? { verification: shadowed.verification } : {}
77408
77549
  };
77409
- }, usage3 = (io, message) => emit(io, fail2("invalid_input", `${message}
77550
+ }, defaultDeps2, raisedKinds = (before, after) => [
77551
+ ...GRANT_KINDS.filter((kind) => raises(kind, before.grants[kind], after.grants[kind])),
77552
+ ...raisesEndpoint(before.endpoint, after.endpoint) ? ["defaultEndpoint"] : [],
77553
+ ...looser(before.verification, after.verification) ? ["verification"] : []
77554
+ ], usage3 = (io, message) => emit(io, fail2("invalid_input", `${message}
77410
77555
  usage: ${USAGE5}`)), load = (io) => {
77411
77556
  const current = readWorkspacesResult();
77412
77557
  if (current.status === "malformed" || current.status === "invalid")
@@ -77455,6 +77600,8 @@ var init_workspace = __esm(() => {
77455
77600
  init_safe_write();
77456
77601
  init_workspaces();
77457
77602
  init_output();
77603
+ init_prompt();
77604
+ init_grant();
77458
77605
  INHERITED_KEYS = [
77459
77606
  "vcs",
77460
77607
  "issues",
@@ -77486,6 +77633,10 @@ var init_workspace = __esm(() => {
77486
77633
  SEGMENT = /^[A-Za-z0-9_-]+$/u;
77487
77634
  UNSAFE_SEGMENTS = new Set(["__proto__", "constructor", "prototype"]);
77488
77635
  STRICTNESS = ["independent", "self", "proportional"];
77636
+ defaultDeps2 = {
77637
+ interactive: () => process.stdin.isTTY === true && process.stdout.isTTY === true,
77638
+ ask: (question) => askLine(question)
77639
+ };
77489
77640
  });
77490
77641
 
77491
77642
  // packages/workit-core/src/core/heavy-rules.ts
@@ -81491,7 +81642,7 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
81491
81642
  return {
81492
81643
  ok: false,
81493
81644
  code: "failed",
81494
- error: `merge_unverified: the forge accepted the merge of ${label} but still reports it ${state}${"id" in recorded ? `; recorded as pr.merged ${recorded.id} (verified: false)` : `; the pr.merged row could not be written (${recorded.error})`}`,
81645
+ error: `merge_unverified: the forge accepted the merge of ${label} but still reports it ${state}${state === "open" ? ", so it is not merged yet (a merge queue or auto-merge may hold it)" : ""}${"id" in recorded ? `; recorded as pr.merged ${recorded.id} (verified: false)` : `; the pr.merged row could not be written (${recorded.error})`}`,
81495
81646
  unblock: `workit verify-delivery merged --pr ${doc.number}`,
81496
81647
  recorded
81497
81648
  };
@@ -107882,7 +108033,7 @@ var VERBS = [
107882
108033
  withSubcommands({
107883
108034
  name: "workspace",
107884
108035
  group: "setup",
107885
- summary: "Edit workspace entries without the wizard; never raises a grant",
108036
+ summary: "Edit workspace entries without the wizard; a raise (rm included) needs the user at a terminal",
107886
108037
  subcommands: [
107887
108038
  {
107888
108039
  name: "list",
@@ -107898,15 +108049,21 @@ var VERBS = [
107898
108049
  name: "set",
107899
108050
  usage: "workit workspace set <name> <key>=<value>…",
107900
108051
  summary: "Change non-grant keys (dotted paths, JSON values, null removes); grants stay with workit grant set"
108052
+ },
108053
+ {
108054
+ name: "rm",
108055
+ usage: "workit workspace rm <name>",
108056
+ summary: "Remove an entry; if another entry or the defaults could grant its folders more, the user confirms at their own terminal"
107901
108057
  }
107902
108058
  ],
107903
108059
  examples: [
107904
108060
  "workit workspace list",
107905
108061
  "workit workspace add kit --glob '/home/me/work/libs/kit/**' --from work",
107906
- "workit workspace set kit branchPolicy.integration=merge"
108062
+ "workit workspace set kit branchPolicy.integration=merge",
108063
+ "workit workspace rm kit"
107907
108064
  ],
107908
108065
  notes: [
107909
- "A new entry starts with no grants of its own. It starts at the strictest level of every entry and the defaults, so its folders never get more than they had. Remove an entry in your own editor. Raising a grant, defaultEndpoint or verification needs the user: workit grant set <name> <kind>=<value> in their own terminal.",
108066
+ "A new entry starts with no grants of its own. It starts at the strictest level of every entry and the defaults, so its folders never get more than they had. rm counts every other entry and the defaults as a possible taker of the removed folders: when any could grant more, it is refused in an agent or headless shell and the user types the name to confirm at their own terminal; it never removes the last entry. Raising a grant, defaultEndpoint or verification needs the user: workit grant set <name> <kind>=<value> in their own terminal.",
107910
108067
  "Every write keeps the previous file as workspaces.json.bak. `workit doctor` lists overlapping globs and which entry wins."
107911
108068
  ],
107912
108069
  load: () => Promise.resolve().then(() => (init_workspace(), exports_workspace))
@@ -108643,43 +108800,54 @@ async function main(argv, overrides = {}, options = {}) {
108643
108800
  const entry = findVerb(command);
108644
108801
  if (!entry)
108645
108802
  return unknown2(io, command);
108646
- if (wantsHelp(verbArgs)) {
108647
- const word = firstWord(verbArgs);
108648
- const sub = word === undefined ? undefined : findSubcommand(entry, word);
108649
- const asValue = helpAsValue(verbArgs, sub ? [sub.usage] : usageLines(entry));
108650
- if (asValue)
108651
- return emit(io, fail2("invalid_input", asValue, {
108652
- unblock: `workit help ${entry.name}${sub ? ` ${sub.name}` : ""}`
108653
- }));
108654
- return help(io, sub ? subcommandHelp(entry, sub) : verbHelp(entry));
108655
- }
108656
- const ended = endOfOptions(io, entry, args);
108657
- if (typeof ended === "number")
108658
- return ended;
108659
- const checked = checkFlags(entry, ended);
108660
- if ("error" in checked)
108661
- return emit(io, fail2("invalid_input", checked.error, { unblock: checked.unblock }));
108662
- if (parsed.cwd !== null) {
108663
- try {
108664
- process.chdir(io.cwd);
108665
- } catch {
108666
- return emit(io, fail2("invalid_input", `--cwd: cannot enter ${io.cwd}`));
108667
- }
108668
- if (process.env.WORKFLOW_WORKSPACE_ROOT !== undefined) {
108669
- process.env.WORKFLOW_WORKSPACE_ROOT = io.cwd;
108670
- io.env = process.env;
108803
+ const route = async (routed) => {
108804
+ if (wantsHelp(verbArgs)) {
108805
+ const word = firstWord(verbArgs);
108806
+ const sub = word === undefined ? undefined : findSubcommand(entry, word);
108807
+ const asValue = helpAsValue(verbArgs, sub ? [sub.usage] : usageLines(entry));
108808
+ if (asValue)
108809
+ return emit(routed, fail2("invalid_input", asValue, {
108810
+ unblock: `workit help ${entry.name}${sub ? ` ${sub.name}` : ""}`
108811
+ }));
108812
+ return help(routed, sub ? subcommandHelp(entry, sub) : verbHelp(entry));
108813
+ }
108814
+ const ended = endOfOptions(routed, entry, args);
108815
+ if (typeof ended === "number")
108816
+ return ended;
108817
+ const checked = checkFlags(entry, ended);
108818
+ if ("error" in checked)
108819
+ return emit(routed, fail2("invalid_input", checked.error, { unblock: checked.unblock }));
108820
+ if (parsed.cwd !== null) {
108821
+ try {
108822
+ process.chdir(routed.cwd);
108823
+ } catch {
108824
+ return emit(routed, fail2("invalid_input", `--cwd: cannot enter ${routed.cwd}`));
108825
+ }
108826
+ if (process.env.WORKFLOW_WORKSPACE_ROOT !== undefined) {
108827
+ process.env.WORKFLOW_WORKSPACE_ROOT = routed.cwd;
108828
+ routed.env = process.env;
108829
+ }
108671
108830
  }
108672
- }
108673
- if (options.diagnostics)
108674
- (await Promise.resolve().then(() => (init_diagnostics(), exports_diagnostics))).installDiagnostics(command);
108675
- globalThis[Symbol.for("workit.migrationReporter")] = (report) => io.stderr(`workit: migrated ${report.tasks} task${report.tasks === 1 ? "" : "s"} from ${report.from} to ${report.to} (backup: ${report.backup})
108831
+ if (options.diagnostics)
108832
+ (await Promise.resolve().then(() => (init_diagnostics(), exports_diagnostics))).installDiagnostics(command);
108833
+ globalThis[Symbol.for("workit.migrationReporter")] = (report) => routed.stderr(`workit: migrated ${report.tasks} task${report.tasks === 1 ? "" : "s"} from ${report.from} to ${report.to} (backup: ${report.backup})
108676
108834
  `);
108677
- const verb = await entry.load();
108678
- const runVerb = (target) => guarded(target, () => verb.run(checked.args, target));
108679
- if (!io.json)
108680
- return runVerb(io);
108681
- return runJsonPure(io, command, runVerb);
108682
- }
108835
+ const verb = await entry.load();
108836
+ const runVerb = (target) => guarded(target, () => verb.run(checked.args, target));
108837
+ return routed.json ? runJsonPure(routed, command, runVerb) : runVerb(routed);
108838
+ };
108839
+ if (io.json)
108840
+ return route(io);
108841
+ const verbWord = firstWord(verbArgs);
108842
+ const outcome = verbWord ? OUTCOMES2[`${entry.name} ${verbWord}`] : undefined;
108843
+ return withFailureLine(io, command, route, outcome);
108844
+ }
108845
+ var OUTCOMES2 = {
108846
+ "pr merge": "PR not merged",
108847
+ "pr create": "PR not created",
108848
+ "stack land": "stack not landed",
108849
+ "git push": "not pushed"
108850
+ };
108683
108851
  async function guarded(io, run) {
108684
108852
  try {
108685
108853
  return await run();
@@ -108783,7 +108951,9 @@ var describe4 = (entry) => ({
108783
108951
  });
108784
108952
  var unknown2 = (io, command) => emit(io, fail2("invalid_input", `unknown command "${command}"`, { unblock: commandUnblock(command) }));
108785
108953
  if (__require.main == __require.module) {
108786
- process.exit(await main(process.argv.slice(2), {}, { diagnostics: true }));
108954
+ const code = await main(process.argv.slice(2), {}, { diagnostics: true });
108955
+ await flushStreams();
108956
+ process.exit(code);
108787
108957
  }
108788
108958
  export {
108789
108959
  main,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "8.39.4",
3
+ "version": "8.40.1",
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.39.4",
41
+ "@brainervirus/workit-cursor": "^8.40.1",
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.39.4"
47
+ "@brainervirus/workit-core": "^8.40.1"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=24"