@brainervirus/workit-cli 8.9.0 → 8.9.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 +179 -46
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -65,7 +65,7 @@ var package_default;
65
65
  var init_package = __esm(() => {
66
66
  package_default = {
67
67
  name: "@brainervirus/workit-cli",
68
- version: "8.9.0",
68
+ version: "8.9.1",
69
69
  private: false,
70
70
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
71
71
  keywords: [
@@ -103,9 +103,9 @@ var init_package = __esm(() => {
103
103
  },
104
104
  dependencies: {
105
105
  "@babel/parser": "7.29.9",
106
- "@brainervirus/workit-core": "^8.9.0",
107
- "@brainervirus/workit-cursor": "^8.9.0",
108
- "@brainervirus/workit-opencode": "^8.9.0",
106
+ "@brainervirus/workit-core": "^8.9.1",
107
+ "@brainervirus/workit-cursor": "^8.9.1",
108
+ "@brainervirus/workit-opencode": "^8.9.1",
109
109
  "@inkjs/ui": "2.0.0",
110
110
  ink: "7.1.1",
111
111
  react: "19.2.8"
@@ -11079,6 +11079,66 @@ class TaskStore {
11079
11079
  return bound;
11080
11080
  return success(null, null, { key: key.data, bound: bound.data });
11081
11081
  }
11082
+ taskForWorker(workerId) {
11083
+ if (typeof workerId !== "string" || !validId(workerId))
11084
+ return failure2("invalid_input", "needs a worker id: `workit worker cancel|report <workerId>`");
11085
+ const listed = this.listTaskIndex();
11086
+ if (!listed.ok)
11087
+ return listed;
11088
+ for (const entry of listed.data) {
11089
+ if (entry.status === "closed")
11090
+ continue;
11091
+ const loaded = this.load(entry.id);
11092
+ if (!loaded.ok)
11093
+ return loaded;
11094
+ if (loaded.data?.record.workers.some((worker) => worker.id === workerId))
11095
+ return success(null, null, entry.id);
11096
+ }
11097
+ return success(null, null, null);
11098
+ }
11099
+ originTaskEntry() {
11100
+ const key = this.currentKey();
11101
+ const location = this.location();
11102
+ const branch = key.ok ? key.data.branch : null;
11103
+ if (!branch || !location.ok)
11104
+ return success(null, null, null);
11105
+ const common = path8.dirname(location.data.dir);
11106
+ const heads = path8.join(common, "logs", "refs", "heads");
11107
+ const headLog = location.data.git ? path8.join(location.data.git.gitDir, "logs", "HEAD") : "";
11108
+ const signatures = [
11109
+ path8.join(heads, branch),
11110
+ headLog,
11111
+ heads,
11112
+ path8.join(common, "packed-refs")
11113
+ ].map((file) => fileSignature(file) ?? "-");
11114
+ const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
11115
+ let resolved = origins.get(slot);
11116
+ if (resolved?.signature !== signatures.join("|")) {
11117
+ const renames = branchRenames(location.data);
11118
+ const aliases = [branch];
11119
+ for (const rename of renames.toReversed())
11120
+ if (rename.to === aliases.at(-1))
11121
+ aliases.push(rename.from);
11122
+ const start = branchStart(location.data, branch, aliases);
11123
+ const slash = start?.indexOf("/") ?? -1;
11124
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path8.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
11125
+ const name = start && (remote ? start.slice(slash + 1) : start);
11126
+ resolved = {
11127
+ signature: signatures.join("|"),
11128
+ name: name && !aliases.includes(name) ? name : null,
11129
+ renames
11130
+ };
11131
+ origins.set(slot, resolved);
11132
+ }
11133
+ const entry = resolved.name ? this.openTasksForKey(resolved.name, resolved.renames) : null;
11134
+ if (entry && !entry.ok)
11135
+ return entry;
11136
+ return success(null, null, entry?.data[0] ? { origin: `branch ${resolved.name}`, entry: entry.data[0] } : null);
11137
+ }
11138
+ readStoreTask(taskId) {
11139
+ const loaded = this.load(taskId);
11140
+ return loaded.ok ? success(null, null, loaded.data?.record ?? null) : loaded;
11141
+ }
11082
11142
  create(input, provenance, expectedWorkspaceRevision) {
11083
11143
  const value = "intent" in input ? input : {
11084
11144
  intent: input,
@@ -11748,12 +11808,12 @@ class TaskStore {
11748
11808
  return 0;
11749
11809
  }
11750
11810
  }
11751
- openTasksForKey(key) {
11811
+ openTasksForKey(key, known) {
11752
11812
  const all = this.listStoreIndex();
11753
11813
  if (!all.ok)
11754
11814
  return all;
11755
- const location = this.location();
11756
- const renames = location.ok ? branchRenames(location.data) : [];
11815
+ const location = known ? null : this.location();
11816
+ const renames = known ?? (location?.ok ? branchRenames(location.data) : []);
11757
11817
  return success(null, null, all.data.filter((entry) => entry.key !== null && entry.status !== "closed").filter((entry) => (renames.length ? followRenames(entry.key, entry.boundAt ?? entry.createdAt, renames) : entry.key) === key).toSorted(oldestFirst));
11758
11818
  }
11759
11819
  openTaskForKey(key) {
@@ -12440,7 +12500,34 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
12440
12500
  return left > right;
12441
12501
  }
12442
12502
  return false;
12443
- }, validId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value), sameDirectoryIdentity = (left, right) => {
12503
+ }, validId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value), readText = (file) => {
12504
+ try {
12505
+ return fs8.readFileSync(file, "utf8");
12506
+ } catch {
12507
+ return "";
12508
+ }
12509
+ }, REFLOG_LINE, branchStart = (location, branch, aliases) => {
12510
+ const first = readText(path8.join(path8.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
12511
+ `, 1)[0];
12512
+ const created = REFLOG_LINE.exec(first);
12513
+ const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
12514
+ if (!created || !start)
12515
+ return null;
12516
+ if (start !== "HEAD")
12517
+ return start;
12518
+ if (!location.git)
12519
+ return null;
12520
+ for (const line of readText(path8.join(location.git.gitDir, "logs", "HEAD")).split(`
12521
+ `)) {
12522
+ const entry = REFLOG_LINE.exec(line);
12523
+ const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
12524
+ const seconds = entry ? Number(entry[2]) - Number(created[2]) : -1;
12525
+ if (moved && entry[1] === created[1] && seconds >= 0 && seconds <= 1 && aliases.includes(moved[2]))
12526
+ return moved[1];
12527
+ }
12528
+ return null;
12529
+ }, refExists = (common, ref) => fs8.existsSync(path8.join(common, ref)) || readText(path8.join(common, "packed-refs")).includes(` ${ref}
12530
+ `), origins, sameDirectoryIdentity = (left, right) => {
12444
12531
  if (!path8.isAbsolute(left) || !path8.isAbsolute(right))
12445
12532
  return false;
12446
12533
  const normalizedLeft = path8.resolve(left);
@@ -12488,6 +12575,8 @@ var init_task_store = __esm(() => {
12488
12575
  AUTO_COMPACT_BYTES = 2 * 1024 * 1024;
12489
12576
  TOMBSTONE = Symbol("tombstone");
12490
12577
  STALE_TEMPORARY_MS = 60 * 60000;
12578
+ REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
12579
+ origins = new Map;
12491
12580
  heldInProcess = new Map;
12492
12581
  });
12493
12582
 
@@ -16442,38 +16531,29 @@ function reconcileResume(view, observations = []) {
16442
16531
  reassessmentRequired: view.task.policy?.policyVersion !== POLICY_VERSION
16443
16532
  });
16444
16533
  }
16445
- function compactTaskContext(view) {
16446
- const decisions = view.task.decisions.slice().toSorted((left, right) => {
16447
- const leftAt = compactTimestamp(left.recordedAt);
16448
- const rightAt = compactTimestamp(right.recordedAt);
16449
- if (leftAt !== rightAt)
16450
- return leftAt > rightAt ? -1 : 1;
16451
- return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
16452
- }).slice(0, COMPACT_MAX_ITEMS).map((entry) => ({
16453
- id: entry.id,
16454
- purpose: entry.data.purpose,
16455
- status: entry.data.response,
16456
- digest: entry.data.digest,
16457
- choice: compactDecisionChoice(entry) || `task.inspect taskId=${view.task.id} view=full; decision=${entry.id}`,
16458
- references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference)
16459
- }));
16460
- const methods = view.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
16534
+ function compactTaskContext(view, inherited = null) {
16535
+ const decisions = compactDecisions([
16536
+ view && { origin: null, taskId: view.task.id, decisions: view.task.decisions },
16537
+ inherited
16538
+ ]);
16539
+ const methods = view?.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
16461
16540
  id: method.id,
16462
16541
  assurance: method.assurance,
16463
16542
  reason: compactText(method.reason, COMPACT_TEXT_BYTES) ?? ""
16464
16543
  })) : [];
16544
+ const stale = view?.evidence.filter((entry) => entry.status === "stale").length;
16465
16545
  const gaps = Array.from(new Set([
16466
- ...view.evidence.filter((entry) => entry.status === "stale").map((entry) => `stale evidence: ${entry.evidenceId}`),
16467
- ...view.requirements.filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
16468
- ...view.task.progress.blockers.map((entry) => entry.reason)
16546
+ ...stale ? [`stale evidence: ${stale}; workit task inspect --task ${view.task.id} --view full`] : [],
16547
+ ...(view?.requirements ?? []).filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
16548
+ ...(view?.task.progress.blockers ?? []).map((entry) => entry.reason)
16469
16549
  ])).toSorted().slice(0, COMPACT_MAX_ITEMS).map((gap) => compactText(gap, COMPACT_TEXT_BYTES));
16470
16550
  const context = {
16471
- objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
16472
- status: view.task.status,
16551
+ objective: view ? compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "" : "no task on this branch yet",
16552
+ status: view?.task.status ?? null,
16473
16553
  decisions,
16474
16554
  methods,
16475
16555
  gaps,
16476
- nextAction: compactText(view.task.progress.nextAction, COMPACT_TEXT_BYTES)
16556
+ nextAction: compactText(view?.task.progress.nextAction ?? null, COMPACT_TEXT_BYTES)
16477
16557
  };
16478
16558
  let encoded = JSON.stringify(context);
16479
16559
  while (compactBytes(encoded) > COMPACT_MAX_BYTES && (context.decisions.length || context.methods.length || context.gaps.length)) {
@@ -16516,7 +16596,21 @@ var COMPACT_MAX_BYTES = 4096, COMPACT_MAX_ITEMS = 8, COMPACT_TEXT_BYTES = 128, s
16516
16596
  id: ref.id
16517
16597
  };
16518
16598
  return { kind: ref.kind };
16519
- }, exportDigest = (bundle) => sha256({
16599
+ }, newestDecisionFirst = (left, right) => {
16600
+ const leftAt = compactTimestamp(left.recordedAt);
16601
+ const rightAt = compactTimestamp(right.recordedAt);
16602
+ if (leftAt !== rightAt)
16603
+ return leftAt > rightAt ? -1 : 1;
16604
+ return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
16605
+ }, compactDecisions = (sources) => sources.flatMap((source) => source ? source.decisions.toSorted(newestDecisionFirst).map((entry) => ({
16606
+ id: entry.id,
16607
+ purpose: entry.data.purpose,
16608
+ status: entry.data.response,
16609
+ digest: entry.data.digest,
16610
+ choice: compactDecisionChoice(entry) || `task.inspect taskId=${source.taskId} view=full; decision=${entry.id}`,
16611
+ references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference),
16612
+ origin: source.origin ?? undefined
16613
+ })) : []).slice(0, COMPACT_MAX_ITEMS), exportDigest = (bundle) => sha256({
16520
16614
  schemaVersion: bundle.schemaVersion,
16521
16615
  exportedAt: bundle.exportedAt,
16522
16616
  sourceWorkspaceId: bundle.sourceWorkspaceId,
@@ -17256,6 +17350,17 @@ class WorkitCore {
17256
17350
  const root = this.contextRootError();
17257
17351
  if (!root.ok)
17258
17352
  return root;
17353
+ const addressed = WORKER_ADDRESSED_ACTIONS.has(action);
17354
+ const workerId = addressed ? value.workerId : this.context.workerId ?? null;
17355
+ if (workerId !== null) {
17356
+ const owner = this.store.taskForWorker(workerId);
17357
+ if (!owner.ok)
17358
+ return owner;
17359
+ if (owner.data)
17360
+ return success(null, null, { ...request, taskId: owner.data });
17361
+ if (addressed)
17362
+ return failure2("not_found", `worker ${workerId} is on no open task; find its task with \`workit task status --all\`, then run \`${workerCommand("<task-id>", request)}\``);
17363
+ }
17259
17364
  const create = CREATING_ACTIONS.has(action) && (this.context.workerId ?? null) === null;
17260
17365
  const found = this.store.implicitTask({
17261
17366
  provenance: provenance(this.context),
@@ -17962,7 +18067,9 @@ class WorkitCore {
17962
18067
  if (!resolved.ok)
17963
18068
  return resolved;
17964
18069
  const value = resolved.data;
17965
- return this.retryOmittedRevisions(value, () => this.workerOnce(value));
18070
+ const result = this.retryOmittedRevisions(value, () => this.workerOnce(value));
18071
+ const { action, taskId } = value ?? {};
18072
+ return result.ok || request?.taskId !== undefined || typeof taskId !== "string" || !WORKER_ADDRESSED_ACTIONS.has(`worker.${String(action)}`) ? result : { ...result, error: `${result.error}; run \`${workerCommand(taskId, value)}\`` };
17966
18073
  }
17967
18074
  workerOnce(request) {
17968
18075
  const root = this.contextRootError();
@@ -18167,10 +18274,18 @@ class WorkitCore {
18167
18274
  requirements
18168
18275
  });
18169
18276
  }
18170
- compactContext(taskId, freshness) {
18277
+ compactContext(taskId, freshness, origin = null) {
18171
18278
  const root = this.contextRootError();
18172
18279
  if (!root.ok)
18173
18280
  return root;
18281
+ const base = origin && this.store.readStoreTask(origin.taskId);
18282
+ const inherited = base?.ok && base.data ? {
18283
+ origin: origin.origin,
18284
+ taskId: base.data.id,
18285
+ decisions: base.data.decisions.filter((entry) => entry.data.revoked === null)
18286
+ } : null;
18287
+ if (taskId === null)
18288
+ return success(null, null, inherited?.decisions.length ? compactTaskContext(null, inherited) : "");
18174
18289
  const task = this.store.readTask(taskId);
18175
18290
  if (!task.ok)
18176
18291
  return task;
@@ -18180,7 +18295,7 @@ class WorkitCore {
18180
18295
  const view = this.view(task.data, false, freshness ?? signalFreshness(this.store.root));
18181
18296
  if (!view.ok)
18182
18297
  return view;
18183
- return success(view.revision, view.workspaceRevision, compactTaskContext(view.data));
18298
+ return success(view.revision, view.workspaceRevision, compactTaskContext(view.data, inherited));
18184
18299
  }
18185
18300
  view(task, capture = true, freshness = treeFreshness(this.store.root)) {
18186
18301
  const workspace = this.store.readWorkspace();
@@ -18591,7 +18706,12 @@ var MAX_JUDGED_REFS = 5, workspaceVerification = (root) => {
18591
18706
  return changed;
18592
18707
  const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
18593
18708
  return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
18594
- }, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || scopeCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), TASK_SCOPED_ACTIONS, CREATING_ACTIONS, REVISION_RETRY_ATTEMPTS = 8, retryPause, filledRevisions = (request) => {
18709
+ }, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || scopeCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), TASK_SCOPED_ACTIONS, WORKER_ADDRESSED_ACTIONS, workerCommand = (taskId, request) => {
18710
+ const { action, workerId, reason, report } = request;
18711
+ const rest = JSON.stringify({ reason, report });
18712
+ const payload = rest === "{}" ? "" : ` --payload '${rest.replace(/'/gu, "'\\''")}'`;
18713
+ return `workit worker ${String(action)} ${String(workerId)} --task ${taskId}${payload}`;
18714
+ }, CREATING_ACTIONS, REVISION_RETRY_ATTEMPTS = 8, retryPause, filledRevisions = (request) => {
18595
18715
  const value = typeof request === "object" && request !== null ? request : {};
18596
18716
  return {
18597
18717
  task: value.expectedRevision === undefined,
@@ -18813,6 +18933,7 @@ var init_task_engine = __esm(() => {
18813
18933
  "worker.cancel",
18814
18934
  "state.export"
18815
18935
  ]);
18936
+ WORKER_ADDRESSED_ACTIONS = new Set(["worker.cancel", "worker.report"]);
18816
18937
  CREATING_ACTIONS = new Set([
18817
18938
  "task.revise",
18818
18939
  "task.progress",
@@ -19533,9 +19654,10 @@ async function payloadValue(raw, deps) {
19533
19654
  }
19534
19655
  }
19535
19656
  function inject(request, key, value) {
19657
+ const given = key === "workerId" ? "positional worker id" : "explicit flag";
19536
19658
  if (key in request && !same(request[key], value))
19537
- return failure2("invalid_input", `payload ${key} conflicts with the explicit flag`, {
19538
- fields: [{ path: key, reason: "explicit flag conflicts with payload" }]
19659
+ return failure2("invalid_input", `payload ${key} conflicts with the ${given}`, {
19660
+ fields: [{ path: key, reason: `${given} conflicts with payload` }]
19539
19661
  });
19540
19662
  request[key] = value;
19541
19663
  return success(null, null, null);
@@ -19558,12 +19680,18 @@ async function parseTaskArgs(argv, deps) {
19558
19680
  let workspaceRevision;
19559
19681
  let view;
19560
19682
  let actor;
19683
+ let workerId;
19684
+ const takesWorkerId = family === "worker" && (action === "cancel" || action === "report");
19561
19685
  let json = jsonRequested;
19562
19686
  const judge = [];
19563
19687
  const seen = new Set;
19564
19688
  for (let i = 2;i < argv.length; i += 1) {
19565
19689
  if (argv[i] === "--") {
19566
19690
  const extra = argv.slice(i + 1);
19691
+ if (takesWorkerId && workerId === undefined && extra.length === 1) {
19692
+ workerId = extra[0];
19693
+ break;
19694
+ }
19567
19695
  if (extra.length)
19568
19696
  return parseUsage(`${family} ${actionName} takes no positional arguments (got: ${extra.join(" ")})`, json);
19569
19697
  break;
@@ -19593,6 +19721,10 @@ async function parseTaskArgs(argv, deps) {
19593
19721
  json = true;
19594
19722
  continue;
19595
19723
  }
19724
+ if (takesWorkerId && workerId === undefined && !argv[i].startsWith("-")) {
19725
+ workerId = argv[i];
19726
+ continue;
19727
+ }
19596
19728
  if (!["--payload", "--task", "--revision", "--workspace-revision", "--view", "--actor"].includes(token))
19597
19729
  return parseUsage(`unknown argument: ${argv[i]}`, json);
19598
19730
  const value = inline ?? argv[++i];
@@ -19628,6 +19760,7 @@ async function parseTaskArgs(argv, deps) {
19628
19760
  for (const [key, value] of [
19629
19761
  ["action", action],
19630
19762
  ...taskId === undefined ? [] : [["taskId", taskId]],
19763
+ ...workerId === undefined ? [] : [["workerId", workerId]],
19631
19764
  ...revision === undefined ? [] : [["expectedRevision", revision]],
19632
19765
  ...workspaceRevision === undefined ? [] : [["expectedWorkspaceRevision", workspaceRevision]],
19633
19766
  ...view === undefined ? [] : [["view", view]]
@@ -63965,12 +64098,12 @@ function inspectSessionHook(cwd, env = process.env) {
63965
64098
  return { state: "not_git", ...none };
63966
64099
  const hookPath = path30.join(hooksDir, SESSION_HOOK_NAME);
63967
64100
  const helperPath = path30.join(commonDir, ...HELPER);
63968
- const helperCurrent = readText(helperPath) === SESSION_TRAILER_SCRIPT;
64101
+ const helperCurrent = readText2(helperPath) === SESSION_TRAILER_SCRIPT;
63969
64102
  const leftover = leftoverOf(hooksDir);
63970
64103
  const base = { hooksDir, hookPath, helperPath, helperCurrent, ...leftover ? { leftover } : {} };
63971
64104
  const blocked = (reason, owner, text = "") => {
63972
64105
  const old = `${hookPath}.old`;
63973
- const displaced = readText(old)?.includes(SESSION_HOOK_MARKER) ? old : null;
64106
+ const displaced = readText2(old)?.includes(SESSION_HOOK_MARKER) ? old : null;
63974
64107
  const input = { owner, text, hooksDir, hookPath, top: top.out, displaced };
63975
64108
  const manualTarget = manualTargetOf(input);
63976
64109
  const owned = text ? { owner } : {};
@@ -63993,7 +64126,7 @@ function inspectSessionHook(cwd, env = process.env) {
63993
64126
  };
63994
64127
  if (!inside2(hooksDir, commonDir) && !inside2(hooksDir, top.out))
63995
64128
  return blocked(`core.hooksPath ${hooksDir} is outside the repository; a hook there runs in every repository that uses it`, "other");
63996
- const text = exists(hookPath) ? readText(hookPath) ?? "" : null;
64129
+ const text = exists(hookPath) ? readText2(hookPath) ?? "" : null;
63997
64130
  if (text !== null) {
63998
64131
  if (text === SESSION_HOOK_SCRIPT)
63999
64132
  return { state: helperCurrent ? "installed" : "outdated", ...base };
@@ -64044,7 +64177,7 @@ function installSessionHook(cwd, env = process.env) {
64044
64177
  detail: `${status.reason}${helper}`
64045
64178
  };
64046
64179
  const fresh = status.state === "missing";
64047
- const slotCurrent = readText(status.hookPath) === SESSION_HOOK_SCRIPT;
64180
+ const slotCurrent = readText2(status.hookPath) === SESSION_HOOK_SCRIPT;
64048
64181
  if (!slotCurrent)
64049
64182
  writeExecutable(status.hookPath, SESSION_HOOK_SCRIPT);
64050
64183
  const verb = fresh ? "installed" : "updated";
@@ -64113,7 +64246,7 @@ exit 0
64113
64246
  }, inside2 = (child, parent) => {
64114
64247
  const rel = path30.relative(path30.resolve(parent), path30.resolve(child));
64115
64248
  return rel === "" || !rel.startsWith("..") && !path30.isAbsolute(rel);
64116
- }, readText = (file) => {
64249
+ }, readText2 = (file) => {
64117
64250
  try {
64118
64251
  return readFileSync13(file, "utf8");
64119
64252
  } catch {
@@ -64171,10 +64304,10 @@ exit 0
64171
64304
  }, manualInPlace = (input, target) => {
64172
64305
  if (input.owner === "lefthook")
64173
64306
  return LEFTHOOK_YAML.some((name) => {
64174
- const text = readText(path30.join(input.top, name));
64307
+ const text = readText2(path30.join(input.top, name));
64175
64308
  return text !== null && lefthookRunsHelper(text);
64176
64309
  });
64177
- const text = readText(target);
64310
+ const text = readText2(target);
64178
64311
  if (text === null || !runsHelperText(text))
64179
64312
  return false;
64180
64313
  return input.owner === "husky" && target !== input.hookPath || isExecutable(target);
@@ -64209,7 +64342,7 @@ exit 0
64209
64342
  }, leftoverOf = (hooksDir) => {
64210
64343
  const chained = path30.join(hooksDir, LEGACY_CHAINED);
64211
64344
  const commitMsg = path30.join(hooksDir, "commit-msg");
64212
- const oldOurs = readText(commitMsg)?.includes(SESSION_HOOK_MARKER) ?? false;
64345
+ const oldOurs = readText2(commitMsg)?.includes(SESSION_HOOK_MARKER) ?? false;
64213
64346
  if (exists(chained))
64214
64347
  return oldOurs ? `${chained} was left by an earlier Workit build: move it back to ${commitMsg} (replacing Workit's old hook there)` : `${chained} was left by an earlier Workit build and nothing runs it: if it is your original commit-msg hook, move it back to ${commitMsg}; otherwise delete it`;
64215
64348
  if (oldOurs)
@@ -98111,7 +98244,7 @@ var familySubcommands = (name) => {
98111
98244
  const implicit = name === "task" ? TASK_IMPLICIT : [];
98112
98245
  const grammar = Object.entries(FAMILY_ACTIONS[name]).filter(([action]) => !implicit.some((entry) => entry.name === action)).map(([action, summary]) => ({
98113
98246
  name: action,
98114
- usage: name === "policy" && action !== "explain" ? `workit policy ${action} ${POLICY_JUDGE} ${FAMILY_OPTIONS}` : `workit ${name} ${action} ${FAMILY_OPTIONS}`,
98247
+ usage: name === "policy" && action !== "explain" ? `workit policy ${action} ${POLICY_JUDGE} ${FAMILY_OPTIONS}` : name === "worker" && action !== "assign" ? `workit worker ${action} [<workerId>] ${FAMILY_OPTIONS}` : `workit ${name} ${action} ${FAMILY_OPTIONS}`,
98115
98248
  summary
98116
98249
  }));
98117
98250
  return [...implicit, ...grammar];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "8.9.0",
3
+ "version": "8.9.1",
4
4
  "private": false,
5
5
  "description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
6
6
  "keywords": [
@@ -38,9 +38,9 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/parser": "7.29.9",
41
- "@brainervirus/workit-core": "^8.9.0",
42
- "@brainervirus/workit-cursor": "^8.9.0",
43
- "@brainervirus/workit-opencode": "^8.9.0",
41
+ "@brainervirus/workit-core": "^8.9.1",
42
+ "@brainervirus/workit-cursor": "^8.9.1",
43
+ "@brainervirus/workit-opencode": "^8.9.1",
44
44
  "@inkjs/ui": "2.0.0",
45
45
  "ink": "7.1.1",
46
46
  "react": "19.2.8"