@brainervirus/workit-cli 8.14.0 → 8.14.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 +52 -14
  2. package/package.json +3 -3
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.14.0",
68
+ version: "8.14.1",
69
69
  private: false,
70
70
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
71
71
  keywords: [
@@ -103,13 +103,13 @@ var init_package = __esm(() => {
103
103
  },
104
104
  dependencies: {
105
105
  "@babel/parser": "7.29.9",
106
- "@brainervirus/workit-cursor": "^8.14.0",
106
+ "@brainervirus/workit-cursor": "^8.14.1",
107
107
  "@inkjs/ui": "2.0.0",
108
108
  ink: "7.1.1",
109
109
  react: "19.2.8"
110
110
  },
111
111
  devDependencies: {
112
- "@brainervirus/workit-core": "^8.14.0"
112
+ "@brainervirus/workit-core": "^8.14.1"
113
113
  },
114
114
  engines: {
115
115
  node: ">=24"
@@ -7977,6 +7977,16 @@ var init_zod = __esm(() => {
7977
7977
 
7978
7978
  // packages/workit-core/src/core/task-contract.ts
7979
7979
  import { createHash, randomUUID } from "node:crypto";
7980
+ function resolveIdRef(kind, ref, ids) {
7981
+ if (ids.includes(ref))
7982
+ return success(null, null, ref);
7983
+ const matches = ids.filter((candidate) => candidate.startsWith(ref));
7984
+ if (matches.length === 1)
7985
+ return success(null, null, matches[0]);
7986
+ if (matches.length === 0)
7987
+ return failure2("not_found", `${kind} not found`);
7988
+ return failure2("invalid_input", `${kind} prefix ${ref} is ambiguous; candidates: ${matches.join(", ")}`);
7989
+ }
7980
7990
  function parseOperation(family, input) {
7981
7991
  if (typeof input === "object" && input !== null && "schemaVersion" in input && input.schemaVersion !== SCHEMA_VERSION)
7982
7992
  return failure2("unsupported_version", "unsupported schema version", { operation: family });
@@ -8079,7 +8089,7 @@ var SCHEMA_VERSION = 1, POLICY_VERSION = "1.0.0", OPERATION_FAMILIES, uuidPatter
8079
8089
  return true;
8080
8090
  }
8081
8091
  return false;
8082
- }, text, id, digest, revision, validUtc = (value) => {
8092
+ }, text, id, idRefPattern, idRef, digest, revision, validUtc = (value) => {
8083
8093
  const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?Z$/.exec(value);
8084
8094
  if (!match)
8085
8095
  return false;
@@ -8262,6 +8272,8 @@ var init_task_contract = __esm(() => {
8262
8272
  ctx.issues.push({ code: "custom", input: ctx.value, message: "invalid Unicode", path: [] });
8263
8273
  });
8264
8274
  id = text.regex(uuidPattern, "expected lowercase UUID");
8275
+ idRefPattern = /^[0-9a-f][0-9a-f-]{7,35}$/;
8276
+ idRef = text.regex(idRefPattern, "expected a UUID or an id prefix of 8+ characters");
8265
8277
  digest = text.regex(digestPattern, "expected lowercase SHA-256 digest");
8266
8278
  revision = text.regex(uuidPattern, "expected UUID revision");
8267
8279
  utcSchema = text.check((ctx) => {
@@ -8530,7 +8542,7 @@ var init_task_contract = __esm(() => {
8530
8542
  outcome: _enum(["completed", "failed", "cancelled"]),
8531
8543
  summary: text,
8532
8544
  evidenceIds: array(id),
8533
- findingIds: array(id)
8545
+ findingIds: array(idRef)
8534
8546
  }).strict();
8535
8547
  workerSchema = object({
8536
8548
  assignment: assignmentSchema,
@@ -8722,7 +8734,7 @@ var init_task_contract = __esm(() => {
8722
8734
  action: literal("resolve"),
8723
8735
  ...taskId,
8724
8736
  expectedRevision: revision.optional(),
8725
- findingId: id,
8737
+ findingId: idRef,
8726
8738
  disposition: _enum(["open", "fixed", "dismissed", "deferred"]),
8727
8739
  reason: text,
8728
8740
  evidenceIds: array(id),
@@ -8763,7 +8775,7 @@ var init_task_contract = __esm(() => {
8763
8775
  ...taskId,
8764
8776
  expectedRevision: revision.optional(),
8765
8777
  expectedWorkspaceRevision: revision.optional(),
8766
- workerId: id,
8778
+ workerId: idRef,
8767
8779
  report: workerReportSchema
8768
8780
  }),
8769
8781
  cancel: operation({
@@ -8771,7 +8783,7 @@ var init_task_contract = __esm(() => {
8771
8783
  ...taskId,
8772
8784
  ...revisions,
8773
8785
  expectedWorkspaceRevision: revision.optional(),
8774
- workerId: id,
8786
+ workerId: idRef,
8775
8787
  reason: text
8776
8788
  })
8777
8789
  };
@@ -11453,20 +11465,26 @@ class TaskStore {
11453
11465
  return success(null, null, { key: key.data, bound: bound.data });
11454
11466
  }
11455
11467
  taskForWorker(workerId) {
11456
- if (typeof workerId !== "string" || !validId(workerId))
11468
+ if (typeof workerId !== "string" || !idRefPattern.test(workerId))
11457
11469
  return failure2("invalid_input", "needs a worker id: `workit worker cancel|report <workerId>`");
11458
11470
  const listed = this.listTaskIndex();
11459
11471
  if (!listed.ok)
11460
11472
  return listed;
11473
+ const owners = new Map;
11461
11474
  for (const entry of listed.data) {
11462
11475
  if (entry.status === "closed")
11463
11476
  continue;
11464
11477
  const loaded = this.load(entry.id);
11465
11478
  if (!loaded.ok)
11466
11479
  return loaded;
11467
- if (loaded.data?.record.workers.some((worker) => worker.id === workerId))
11468
- return success(null, null, entry.id);
11480
+ for (const worker of loaded.data?.record.workers ?? [])
11481
+ owners.set(worker.id, entry.id);
11469
11482
  }
11483
+ const resolved = resolveIdRef("worker", workerId, [...owners.keys()]);
11484
+ if (resolved.ok)
11485
+ return success(null, null, owners.get(resolved.data) ?? null);
11486
+ if (resolved.code !== "not_found")
11487
+ return resolved;
11470
11488
  return success(null, null, null);
11471
11489
  }
11472
11490
  originTaskEntry() {
@@ -18818,6 +18836,10 @@ class WorkitCore {
18818
18836
  }
18819
18837
  if (helper?.ok)
18820
18838
  return failure2("permission_denied", "helpers cannot resolve findings");
18839
+ const findingRef = resolveIdRef("finding", input.findingId, task.data.findings.map((entry) => entry.id));
18840
+ if (!findingRef.ok)
18841
+ return findingRef;
18842
+ input.findingId = findingRef.data;
18821
18843
  const finding = task.data.findings.find((entry) => entry.id === input.findingId);
18822
18844
  if (!finding)
18823
18845
  return failure2("not_found", "finding not found");
@@ -18969,15 +18991,31 @@ class WorkitCore {
18969
18991
  return changed;
18970
18992
  return success(changed.data.task.revision, changed.data.workspace.revision, changed.data.task.workers.at(-1));
18971
18993
  }
18994
+ const workerRef = resolveIdRef("worker", input.workerId, helperId === null ? task.data.workers.map((candidate) => candidate.id) : [helperId]);
18995
+ if (!workerRef.ok)
18996
+ return helperId === null ? workerRef : failure2("permission_denied", input.action === "report" ? ONLY_OWN_REPORT : NO_HELPER_CONTROL);
18997
+ input.workerId = workerRef.data;
18972
18998
  const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
18973
18999
  if (!entry)
18974
19000
  return failure2("not_found", "worker not found");
18975
19001
  if (input.action === "report") {
18976
19002
  if (helperId === null || helperId !== input.workerId)
18977
- return failure2("permission_denied", "workers can submit only their own report");
19003
+ return failure2("permission_denied", ONLY_OWN_REPORT);
18978
19004
  const helper = this.helperEntry(task.data, true, true);
18979
19005
  if (!helper.ok)
18980
19006
  return helper;
19007
+ const ownFindings = task.data.findings.filter((candidate) => candidate.provenance.workerId === helperId).map((candidate) => candidate.id);
19008
+ const reported = [];
19009
+ for (const findingRef of input.report.findingIds) {
19010
+ const found = resolveIdRef("finding", findingRef, ownFindings);
19011
+ if (found.ok)
19012
+ reported.push(found.data);
19013
+ else if (found.code === "not_found")
19014
+ reported.push(findingRef);
19015
+ else
19016
+ return found;
19017
+ }
19018
+ input.report.findingIds = reported;
18981
19019
  const evidence = task.data.evidence.filter((candidate) => input.report.evidenceIds.includes(candidate.id));
18982
19020
  const findings = task.data.findings.filter((candidate) => input.report.findingIds.includes(candidate.id));
18983
19021
  if (evidence.length !== input.report.evidenceIds.length || findings.length !== input.report.findingIds.length)
@@ -19005,7 +19043,7 @@ class WorkitCore {
19005
19043
  return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during report");
19006
19044
  }
19007
19045
  if (helperId !== null)
19008
- return failure2("permission_denied", "helpers cannot cancel or control workers");
19046
+ return failure2("permission_denied", NO_HELPER_CONTROL);
19009
19047
  if (task.data.status === "closed")
19010
19048
  return failure2("invalid_transition", "closed task cannot cancel workers");
19011
19049
  if (entry.data.state === "stopped") {
@@ -19534,7 +19572,7 @@ var MAX_JUDGED_REFS = 5, workspaceVerification = (root) => {
19534
19572
  return changed;
19535
19573
  const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
19536
19574
  return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
19537
- }, 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) => {
19575
+ }, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || scopeCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), TASK_SCOPED_ACTIONS, ONLY_OWN_REPORT = "workers can submit only their own report", NO_HELPER_CONTROL = "helpers cannot cancel or control workers", WORKER_ADDRESSED_ACTIONS, workerCommand = (taskId, request) => {
19538
19576
  const { action, workerId, reason, report } = request;
19539
19577
  const rest = JSON.stringify({ reason, report });
19540
19578
  const payload = rest === "{}" ? "" : ` --payload '${rest.replace(/'/gu, "'\\''")}'`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "8.14.0",
3
+ "version": "8.14.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.14.0",
41
+ "@brainervirus/workit-cursor": "^8.14.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.14.0"
47
+ "@brainervirus/workit-core": "^8.14.1"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=24"