@brainervirus/workit-cursor 2.2.0 → 2.2.2

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.
@@ -2,7 +2,7 @@
2
2
  "name": "workit",
3
3
  "displayName": "Workit",
4
4
  "description": "Adaptive Workit workflow with shared MCP tools and native Cursor hooks",
5
- "version": "2.2.0",
5
+ "version": "2.2.2",
6
6
  "author": {
7
7
  "name": "Cristhofer Pincetti"
8
8
  },
@@ -10442,7 +10442,7 @@ class TaskStore {
10442
10442
  if (!current.data)
10443
10443
  return failure2("not_found", "workspace not found");
10444
10444
  if (current.data.revision !== expected)
10445
- return this.conflict(expected, current.data.revision);
10445
+ return this.workspaceConflict(expected, current.data.revision);
10446
10446
  const previousBytes = this.snapshotBytes(this.workspacePath);
10447
10447
  if (!previousBytes)
10448
10448
  return failure2("storage_error", "workspace snapshot disappeared during mutation");
@@ -10485,7 +10485,7 @@ class TaskStore {
10485
10485
  if (task.data.revision !== expected)
10486
10486
  return this.conflict(expected, task.data.revision);
10487
10487
  if (workspace.data.revision !== input.expectedWorkspaceRevision)
10488
- return this.conflict(input.expectedWorkspaceRevision, workspace.data.revision);
10488
+ return this.workspaceConflict(input.expectedWorkspaceRevision, workspace.data.revision);
10489
10489
  const previousWorkspaceBytes = this.snapshotBytes(this.workspacePath);
10490
10490
  const previousTaskBytes = this.snapshotBytes(this.taskPath(input.taskId));
10491
10491
  if (!previousWorkspaceBytes || !previousTaskBytes)
@@ -11295,6 +11295,9 @@ class TaskStore {
11295
11295
  actualRevision: actual
11296
11296
  });
11297
11297
  }
11298
+ workspaceConflict(expected, actual) {
11299
+ return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
11300
+ }
11298
11301
  taskPath(taskId) {
11299
11302
  return path7.join(this.tasksDir, `${taskId}.json`);
11300
11303
  }
@@ -13036,8 +13039,10 @@ values are still concurrency-checked, so never copy revisions between calls.
13036
13039
  A busy result means another live Workit call holds the checkout lock: retry the
13037
13040
  same call; it is not a recovery condition. A lock left by a dead process is
13038
13041
  reclaimed on the next write, and \`workit doctor --fix-lock\` clears it on demand.
13039
- A revision_conflict on a call that omitted expectedRevision is contention too:
13040
- re-read the record and retry the call.
13042
+ An omitted revision absorbs a concurrent write: Workit re-reads, re-checks
13043
+ policy, and reapplies the call, returning busy under persistent contention. A
13044
+ revision_conflict means a revision you passed is stale: re-read the record
13045
+ before deciding whether to retry.
13041
13046
  A solo edit does not need writer acquisition; use it when concurrent checkout
13042
13047
  writers need coordination. Record only observed facts and checks. Evidence can
13043
13048
  become stale when its bound candidate changes; reconcile findings against the
@@ -13254,6 +13259,9 @@ class WorkitCore {
13254
13259
  if (input.expectedWorkspaceRevision === undefined)
13255
13260
  input.expectedWorkspaceRevision = workspace ? workspace.revision : null;
13256
13261
  }
13262
+ retryOmittedRevisions(request, run) {
13263
+ return retryFilledRevisions(filledRevisions(request), run);
13264
+ }
13257
13265
  helperEntry(task, requireSession = false, requireActive = false) {
13258
13266
  const workerId = this.context.workerId ?? null;
13259
13267
  if (workerId === null)
@@ -13285,6 +13293,9 @@ class WorkitCore {
13285
13293
  return null;
13286
13294
  }
13287
13295
  state(request) {
13296
+ return request?.action === "import" ? this.retryOmittedRevisions(request, () => this.stateOnce(request)) : this.stateOnce(request);
13297
+ }
13298
+ stateOnce(request) {
13288
13299
  const root = this.contextRootError();
13289
13300
  if (!root.ok)
13290
13301
  return root;
@@ -13386,6 +13397,9 @@ class WorkitCore {
13386
13397
  });
13387
13398
  }
13388
13399
  task(request) {
13400
+ return this.retryOmittedRevisions(request, () => this.taskOnce(request));
13401
+ }
13402
+ taskOnce(request) {
13389
13403
  const root = this.contextRootError();
13390
13404
  if (!root.ok)
13391
13405
  return root;
@@ -13485,6 +13499,9 @@ class WorkitCore {
13485
13499
  }
13486
13500
  }
13487
13501
  policy(request) {
13502
+ return this.retryOmittedRevisions(request, () => this.policyOnce(request));
13503
+ }
13504
+ policyOnce(request) {
13488
13505
  const root = this.contextRootError();
13489
13506
  if (!root.ok)
13490
13507
  return root;
@@ -13531,6 +13548,9 @@ class WorkitCore {
13531
13548
  return success(changed.data.revision, null, changed.data.policy);
13532
13549
  }
13533
13550
  evidence(request) {
13551
+ return this.retryOmittedRevisions(request, () => this.evidenceOnce(request));
13552
+ }
13553
+ evidenceOnce(request) {
13534
13554
  const root = this.contextRootError();
13535
13555
  if (!root.ok)
13536
13556
  return root;
@@ -13615,6 +13635,23 @@ class WorkitCore {
13615
13635
  observeStandingDecision(request) {
13616
13636
  return this.recordDecision(request, undefined, true, true);
13617
13637
  }
13638
+ commitTask(taskId, expected, filled, recheck, update) {
13639
+ let revision = expected;
13640
+ let first = true;
13641
+ return retryFilledRevisions({ task: filled, workspace: false }, () => {
13642
+ if (!first) {
13643
+ const fresh = this.store.readTask(taskId);
13644
+ if (!fresh.ok)
13645
+ return fresh;
13646
+ const checked = recheck(fresh.data);
13647
+ if (!checked.ok)
13648
+ return checked;
13649
+ revision = fresh.data.revision;
13650
+ }
13651
+ first = false;
13652
+ return this.store.mutateTask(taskId, revision, update, trustedNow(this.context));
13653
+ });
13654
+ }
13618
13655
  recordDecision(request, nativeObservation, nativeRequired = false, standing = false) {
13619
13656
  const root = this.contextRootError();
13620
13657
  if (!root.ok)
@@ -13639,6 +13676,7 @@ class WorkitCore {
13639
13676
  return task;
13640
13677
  if ((this.context.workerId ?? null) !== null)
13641
13678
  return failure2("permission_denied", "helpers cannot record or revoke decisions");
13679
+ const filled = input.expectedRevision === undefined;
13642
13680
  this.fillRevisions(input, task.data);
13643
13681
  if (input.action === "record") {
13644
13682
  if (task.data.status === "closed")
@@ -13687,7 +13725,20 @@ class WorkitCore {
13687
13725
  const nativeProvenance = native?.ok ? retireNativeAuthority(native.data) : null;
13688
13726
  if (native?.ok && !nativeProvenance)
13689
13727
  return failure2("permission_denied", "native decision authority was retired");
13690
- const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
13728
+ let standingProvenance = standingApproval?.ok === true ? standingApproval.data : null;
13729
+ const recheck = (fresh) => {
13730
+ if (fresh.status === "closed")
13731
+ return failure2("invalid_transition", "closed task cannot record a decision");
13732
+ if (!standingProvenance)
13733
+ return success(null, null, null);
13734
+ const again = verifyStandingApproval(this.store.root, fresh, this.context.caller, input.binding);
13735
+ if (again.ok)
13736
+ standingProvenance = again.data;
13737
+ return again;
13738
+ };
13739
+ const changed = this.commitTask(task.data.id, input.expectedRevision, filled, recheck, (current, mutation) => {
13740
+ if (current.status === "closed")
13741
+ return failure2("invalid_transition", "closed task cannot record a decision");
13691
13742
  const latestContent = verifyDecisionContent(this.store, input.binding);
13692
13743
  if (!latestContent.ok)
13693
13744
  return latestContent;
@@ -13699,14 +13750,14 @@ class WorkitCore {
13699
13750
  const entry = {
13700
13751
  id: newId(),
13701
13752
  recordedAt: mutation.now,
13702
- provenance: standingApproval?.ok === true ? standingApproval.data : nativeProvenance ?? provenance(this.context, "agent_reported"),
13753
+ provenance: standingProvenance ?? nativeProvenance ?? provenance(this.context, "agent_reported"),
13703
13754
  data
13704
13755
  };
13705
13756
  return success(mutation.revision, null, {
13706
13757
  ...current,
13707
13758
  decisions: [...current.decisions, entry]
13708
13759
  });
13709
- }, trustedNow(this.context));
13760
+ });
13710
13761
  if (!changed.ok)
13711
13762
  return changed;
13712
13763
  return success(changed.data.revision, null, changed.data.decisions.at(-1));
@@ -13720,7 +13771,7 @@ class WorkitCore {
13720
13771
  return failure2("invalid_transition", "decision is already revoked");
13721
13772
  if (decision.data.consumption)
13722
13773
  return failure2("permission_denied", "consumed decision cannot be revoked");
13723
- const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
13774
+ const changed = this.commitTask(task.data.id, input.expectedRevision, filled, () => success(null, null, null), (current, mutation) => {
13724
13775
  const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
13725
13776
  if (!entry)
13726
13777
  return failure2("not_found", "decision not found");
@@ -13737,13 +13788,16 @@ class WorkitCore {
13737
13788
  ...current,
13738
13789
  decisions: current.decisions.map((candidate) => candidate.id === input.decisionId ? updated : candidate)
13739
13790
  });
13740
- }, trustedNow(this.context));
13791
+ });
13741
13792
  if (!changed.ok)
13742
13793
  return changed;
13743
13794
  const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
13744
13795
  return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "decision disappeared");
13745
13796
  }
13746
13797
  finding(request) {
13798
+ return this.retryOmittedRevisions(request, () => this.findingOnce(request));
13799
+ }
13800
+ findingOnce(request) {
13747
13801
  const root = this.contextRootError();
13748
13802
  if (!root.ok)
13749
13803
  return root;
@@ -13867,6 +13921,9 @@ class WorkitCore {
13867
13921
  return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "finding disappeared");
13868
13922
  }
13869
13923
  worker(request) {
13924
+ return this.retryOmittedRevisions(request, () => this.workerOnce(request));
13925
+ }
13926
+ workerOnce(request) {
13870
13927
  const root = this.contextRootError();
13871
13928
  if (!root.ok)
13872
13929
  return root;
@@ -14214,6 +14271,9 @@ class WorkitCore {
14214
14271
  return applied;
14215
14272
  }
14216
14273
  writer(request) {
14274
+ return this.retryOmittedRevisions(request, () => this.writerOnce(request));
14275
+ }
14276
+ writerOnce(request) {
14217
14277
  const root = this.contextRootError();
14218
14278
  if (!root.ok)
14219
14279
  return root;
@@ -14972,7 +15032,25 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
14972
15032
  return changed;
14973
15033
  const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
14974
15034
  return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
14975
- }, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now, mapRef = (ref, ids) => {
15035
+ }, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), REVISION_RETRY_ATTEMPTS = 8, retryPause, filledRevisions = (request) => {
15036
+ const value = typeof request === "object" && request !== null ? request : {};
15037
+ return {
15038
+ task: value.expectedRevision === undefined,
15039
+ workspace: value.expectedWorkspaceRevision === undefined
15040
+ };
15041
+ }, filledConflict = (result, filled) => !result.ok && result.code === "revision_conflict" && (("actualRevision" in result.details) && filled.task || ("actualWorkspaceRevision" in result.details) && filled.workspace), retryFilledRevisions = (filled, run) => {
15042
+ if (!filled.task && !filled.workspace)
15043
+ return run();
15044
+ let result = run();
15045
+ const deadline = Date.now() + defaultLockTimeout();
15046
+ for (let attempt = 1;filledConflict(result, filled); attempt += 1) {
15047
+ if (attempt >= REVISION_RETRY_ATTEMPTS || Date.now() >= deadline)
15048
+ return failure2("busy", "records kept changing under concurrent writers; retry the call");
15049
+ Atomics.wait(retryPause, 0, 0, Math.floor(Math.random() * 4 * attempt) + 1);
15050
+ result = run();
15051
+ }
15052
+ return result;
15053
+ }, trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now, mapRef = (ref, ids) => {
14976
15054
  if (ref.kind !== "record")
14977
15055
  return ref;
14978
15056
  return { ...ref, id: ids.get(ref.id) ?? ref.id };
@@ -15183,11 +15261,13 @@ var init_task_engine = __esm(() => {
15183
15261
  init_authority();
15184
15262
  init_policy_resolver();
15185
15263
  init_auto_approval();
15264
+ init_store_lock();
15186
15265
  init_task_context();
15187
15266
  init_workers();
15188
15267
  init_task_evaluation();
15189
15268
  verifiedWorkers = new WeakMap;
15190
15269
  dispatchReservations = new WeakMap;
15270
+ retryPause = new Int32Array(new SharedArrayBuffer(4));
15191
15271
  });
15192
15272
 
15193
15273
  // packages/workit-core/src/hooks/protocol.ts
@@ -19061,7 +19061,7 @@ class TaskStore {
19061
19061
  if (!current.data)
19062
19062
  return failure2("not_found", "workspace not found");
19063
19063
  if (current.data.revision !== expected)
19064
- return this.conflict(expected, current.data.revision);
19064
+ return this.workspaceConflict(expected, current.data.revision);
19065
19065
  const previousBytes = this.snapshotBytes(this.workspacePath);
19066
19066
  if (!previousBytes)
19067
19067
  return failure2("storage_error", "workspace snapshot disappeared during mutation");
@@ -19104,7 +19104,7 @@ class TaskStore {
19104
19104
  if (task.data.revision !== expected)
19105
19105
  return this.conflict(expected, task.data.revision);
19106
19106
  if (workspace.data.revision !== input.expectedWorkspaceRevision)
19107
- return this.conflict(input.expectedWorkspaceRevision, workspace.data.revision);
19107
+ return this.workspaceConflict(input.expectedWorkspaceRevision, workspace.data.revision);
19108
19108
  const previousWorkspaceBytes = this.snapshotBytes(this.workspacePath);
19109
19109
  const previousTaskBytes = this.snapshotBytes(this.taskPath(input.taskId));
19110
19110
  if (!previousWorkspaceBytes || !previousTaskBytes)
@@ -19914,6 +19914,9 @@ class TaskStore {
19914
19914
  actualRevision: actual
19915
19915
  });
19916
19916
  }
19917
+ workspaceConflict(expected, actual) {
19918
+ return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
19919
+ }
19917
19920
  taskPath(taskId) {
19918
19921
  return path4.join(this.tasksDir, `${taskId}.json`);
19919
19922
  }
@@ -22966,6 +22969,29 @@ var applyWorkerLifecycle = (input) => {
22966
22969
  return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
22967
22970
  };
22968
22971
  var refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] }));
22972
+ var REVISION_RETRY_ATTEMPTS = 8;
22973
+ var retryPause = new Int32Array(new SharedArrayBuffer(4));
22974
+ var filledRevisions = (request) => {
22975
+ const value = typeof request === "object" && request !== null ? request : {};
22976
+ return {
22977
+ task: value.expectedRevision === undefined,
22978
+ workspace: value.expectedWorkspaceRevision === undefined
22979
+ };
22980
+ };
22981
+ var filledConflict = (result, filled) => !result.ok && result.code === "revision_conflict" && (("actualRevision" in result.details) && filled.task || ("actualWorkspaceRevision" in result.details) && filled.workspace);
22982
+ var retryFilledRevisions = (filled, run) => {
22983
+ if (!filled.task && !filled.workspace)
22984
+ return run();
22985
+ let result = run();
22986
+ const deadline = Date.now() + defaultLockTimeout();
22987
+ for (let attempt = 1;filledConflict(result, filled); attempt += 1) {
22988
+ if (attempt >= REVISION_RETRY_ATTEMPTS || Date.now() >= deadline)
22989
+ return failure2("busy", "records kept changing under concurrent writers; retry the call");
22990
+ Atomics.wait(retryPause, 0, 0, Math.floor(Math.random() * 4 * attempt) + 1);
22991
+ result = run();
22992
+ }
22993
+ return result;
22994
+ };
22969
22995
  var trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now;
22970
22996
  var mapRef = (ref, ids) => {
22971
22997
  if (ref.kind !== "record")
@@ -23213,6 +23239,9 @@ class WorkitCore {
23213
23239
  if (input.expectedWorkspaceRevision === undefined)
23214
23240
  input.expectedWorkspaceRevision = workspace ? workspace.revision : null;
23215
23241
  }
23242
+ retryOmittedRevisions(request, run) {
23243
+ return retryFilledRevisions(filledRevisions(request), run);
23244
+ }
23216
23245
  helperEntry(task, requireSession = false, requireActive = false) {
23217
23246
  const workerId = this.context.workerId ?? null;
23218
23247
  if (workerId === null)
@@ -23244,6 +23273,9 @@ class WorkitCore {
23244
23273
  return null;
23245
23274
  }
23246
23275
  state(request) {
23276
+ return request?.action === "import" ? this.retryOmittedRevisions(request, () => this.stateOnce(request)) : this.stateOnce(request);
23277
+ }
23278
+ stateOnce(request) {
23247
23279
  const root = this.contextRootError();
23248
23280
  if (!root.ok)
23249
23281
  return root;
@@ -23345,6 +23377,9 @@ class WorkitCore {
23345
23377
  });
23346
23378
  }
23347
23379
  task(request) {
23380
+ return this.retryOmittedRevisions(request, () => this.taskOnce(request));
23381
+ }
23382
+ taskOnce(request) {
23348
23383
  const root = this.contextRootError();
23349
23384
  if (!root.ok)
23350
23385
  return root;
@@ -23444,6 +23479,9 @@ class WorkitCore {
23444
23479
  }
23445
23480
  }
23446
23481
  policy(request) {
23482
+ return this.retryOmittedRevisions(request, () => this.policyOnce(request));
23483
+ }
23484
+ policyOnce(request) {
23447
23485
  const root = this.contextRootError();
23448
23486
  if (!root.ok)
23449
23487
  return root;
@@ -23490,6 +23528,9 @@ class WorkitCore {
23490
23528
  return success(changed.data.revision, null, changed.data.policy);
23491
23529
  }
23492
23530
  evidence(request) {
23531
+ return this.retryOmittedRevisions(request, () => this.evidenceOnce(request));
23532
+ }
23533
+ evidenceOnce(request) {
23493
23534
  const root = this.contextRootError();
23494
23535
  if (!root.ok)
23495
23536
  return root;
@@ -23574,6 +23615,23 @@ class WorkitCore {
23574
23615
  observeStandingDecision(request) {
23575
23616
  return this.recordDecision(request, undefined, true, true);
23576
23617
  }
23618
+ commitTask(taskId, expected, filled, recheck, update) {
23619
+ let revision = expected;
23620
+ let first = true;
23621
+ return retryFilledRevisions({ task: filled, workspace: false }, () => {
23622
+ if (!first) {
23623
+ const fresh = this.store.readTask(taskId);
23624
+ if (!fresh.ok)
23625
+ return fresh;
23626
+ const checked = recheck(fresh.data);
23627
+ if (!checked.ok)
23628
+ return checked;
23629
+ revision = fresh.data.revision;
23630
+ }
23631
+ first = false;
23632
+ return this.store.mutateTask(taskId, revision, update, trustedNow(this.context));
23633
+ });
23634
+ }
23577
23635
  recordDecision(request, nativeObservation, nativeRequired = false, standing = false) {
23578
23636
  const root = this.contextRootError();
23579
23637
  if (!root.ok)
@@ -23598,6 +23656,7 @@ class WorkitCore {
23598
23656
  return task;
23599
23657
  if ((this.context.workerId ?? null) !== null)
23600
23658
  return failure2("permission_denied", "helpers cannot record or revoke decisions");
23659
+ const filled = input.expectedRevision === undefined;
23601
23660
  this.fillRevisions(input, task.data);
23602
23661
  if (input.action === "record") {
23603
23662
  if (task.data.status === "closed")
@@ -23646,7 +23705,20 @@ class WorkitCore {
23646
23705
  const nativeProvenance = native?.ok ? retireNativeAuthority(native.data) : null;
23647
23706
  if (native?.ok && !nativeProvenance)
23648
23707
  return failure2("permission_denied", "native decision authority was retired");
23649
- const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
23708
+ let standingProvenance = standingApproval?.ok === true ? standingApproval.data : null;
23709
+ const recheck = (fresh) => {
23710
+ if (fresh.status === "closed")
23711
+ return failure2("invalid_transition", "closed task cannot record a decision");
23712
+ if (!standingProvenance)
23713
+ return success(null, null, null);
23714
+ const again = verifyStandingApproval(this.store.root, fresh, this.context.caller, input.binding);
23715
+ if (again.ok)
23716
+ standingProvenance = again.data;
23717
+ return again;
23718
+ };
23719
+ const changed = this.commitTask(task.data.id, input.expectedRevision, filled, recheck, (current, mutation) => {
23720
+ if (current.status === "closed")
23721
+ return failure2("invalid_transition", "closed task cannot record a decision");
23650
23722
  const latestContent = verifyDecisionContent(this.store, input.binding);
23651
23723
  if (!latestContent.ok)
23652
23724
  return latestContent;
@@ -23658,14 +23730,14 @@ class WorkitCore {
23658
23730
  const entry = {
23659
23731
  id: newId(),
23660
23732
  recordedAt: mutation.now,
23661
- provenance: standingApproval?.ok === true ? standingApproval.data : nativeProvenance ?? provenance(this.context, "agent_reported"),
23733
+ provenance: standingProvenance ?? nativeProvenance ?? provenance(this.context, "agent_reported"),
23662
23734
  data
23663
23735
  };
23664
23736
  return success(mutation.revision, null, {
23665
23737
  ...current,
23666
23738
  decisions: [...current.decisions, entry]
23667
23739
  });
23668
- }, trustedNow(this.context));
23740
+ });
23669
23741
  if (!changed.ok)
23670
23742
  return changed;
23671
23743
  return success(changed.data.revision, null, changed.data.decisions.at(-1));
@@ -23679,7 +23751,7 @@ class WorkitCore {
23679
23751
  return failure2("invalid_transition", "decision is already revoked");
23680
23752
  if (decision.data.consumption)
23681
23753
  return failure2("permission_denied", "consumed decision cannot be revoked");
23682
- const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
23754
+ const changed = this.commitTask(task.data.id, input.expectedRevision, filled, () => success(null, null, null), (current, mutation) => {
23683
23755
  const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
23684
23756
  if (!entry)
23685
23757
  return failure2("not_found", "decision not found");
@@ -23696,13 +23768,16 @@ class WorkitCore {
23696
23768
  ...current,
23697
23769
  decisions: current.decisions.map((candidate) => candidate.id === input.decisionId ? updated : candidate)
23698
23770
  });
23699
- }, trustedNow(this.context));
23771
+ });
23700
23772
  if (!changed.ok)
23701
23773
  return changed;
23702
23774
  const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
23703
23775
  return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "decision disappeared");
23704
23776
  }
23705
23777
  finding(request) {
23778
+ return this.retryOmittedRevisions(request, () => this.findingOnce(request));
23779
+ }
23780
+ findingOnce(request) {
23706
23781
  const root = this.contextRootError();
23707
23782
  if (!root.ok)
23708
23783
  return root;
@@ -23826,6 +23901,9 @@ class WorkitCore {
23826
23901
  return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "finding disappeared");
23827
23902
  }
23828
23903
  worker(request) {
23904
+ return this.retryOmittedRevisions(request, () => this.workerOnce(request));
23905
+ }
23906
+ workerOnce(request) {
23829
23907
  const root = this.contextRootError();
23830
23908
  if (!root.ok)
23831
23909
  return root;
@@ -24173,6 +24251,9 @@ class WorkitCore {
24173
24251
  return applied;
24174
24252
  }
24175
24253
  writer(request) {
24254
+ return this.retryOmittedRevisions(request, () => this.writerOnce(request));
24255
+ }
24256
+ writerOnce(request) {
24176
24257
  const root = this.contextRootError();
24177
24258
  if (!root.ok)
24178
24259
  return root;
@@ -10502,7 +10502,7 @@ class TaskStore {
10502
10502
  if (!current.data)
10503
10503
  return failure2("not_found", "workspace not found");
10504
10504
  if (current.data.revision !== expected)
10505
- return this.conflict(expected, current.data.revision);
10505
+ return this.workspaceConflict(expected, current.data.revision);
10506
10506
  const previousBytes = this.snapshotBytes(this.workspacePath);
10507
10507
  if (!previousBytes)
10508
10508
  return failure2("storage_error", "workspace snapshot disappeared during mutation");
@@ -10545,7 +10545,7 @@ class TaskStore {
10545
10545
  if (task.data.revision !== expected)
10546
10546
  return this.conflict(expected, task.data.revision);
10547
10547
  if (workspace.data.revision !== input.expectedWorkspaceRevision)
10548
- return this.conflict(input.expectedWorkspaceRevision, workspace.data.revision);
10548
+ return this.workspaceConflict(input.expectedWorkspaceRevision, workspace.data.revision);
10549
10549
  const previousWorkspaceBytes = this.snapshotBytes(this.workspacePath);
10550
10550
  const previousTaskBytes = this.snapshotBytes(this.taskPath(input.taskId));
10551
10551
  if (!previousWorkspaceBytes || !previousTaskBytes)
@@ -11355,6 +11355,9 @@ class TaskStore {
11355
11355
  actualRevision: actual
11356
11356
  });
11357
11357
  }
11358
+ workspaceConflict(expected, actual) {
11359
+ return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
11360
+ }
11358
11361
  taskPath(taskId) {
11359
11362
  return path7.join(this.tasksDir, `${taskId}.json`);
11360
11363
  }
@@ -13028,8 +13031,10 @@ values are still concurrency-checked, so never copy revisions between calls.
13028
13031
  A busy result means another live Workit call holds the checkout lock: retry the
13029
13032
  same call; it is not a recovery condition. A lock left by a dead process is
13030
13033
  reclaimed on the next write, and \`workit doctor --fix-lock\` clears it on demand.
13031
- A revision_conflict on a call that omitted expectedRevision is contention too:
13032
- re-read the record and retry the call.
13034
+ An omitted revision absorbs a concurrent write: Workit re-reads, re-checks
13035
+ policy, and reapplies the call, returning busy under persistent contention. A
13036
+ revision_conflict means a revision you passed is stale: re-read the record
13037
+ before deciding whether to retry.
13033
13038
  A solo edit does not need writer acquisition; use it when concurrent checkout
13034
13039
  writers need coordination. Record only observed facts and checks. Evidence can
13035
13040
  become stale when its bound candidate changes; reconcile findings against the
@@ -13372,6 +13377,29 @@ var applyWorkerLifecycle = (input) => {
13372
13377
  return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
13373
13378
  };
13374
13379
  var refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] }));
13380
+ var REVISION_RETRY_ATTEMPTS = 8;
13381
+ var retryPause = new Int32Array(new SharedArrayBuffer(4));
13382
+ var filledRevisions = (request) => {
13383
+ const value = typeof request === "object" && request !== null ? request : {};
13384
+ return {
13385
+ task: value.expectedRevision === undefined,
13386
+ workspace: value.expectedWorkspaceRevision === undefined
13387
+ };
13388
+ };
13389
+ var filledConflict = (result, filled) => !result.ok && result.code === "revision_conflict" && (("actualRevision" in result.details) && filled.task || ("actualWorkspaceRevision" in result.details) && filled.workspace);
13390
+ var retryFilledRevisions = (filled, run) => {
13391
+ if (!filled.task && !filled.workspace)
13392
+ return run();
13393
+ let result = run();
13394
+ const deadline = Date.now() + defaultLockTimeout();
13395
+ for (let attempt = 1;filledConflict(result, filled); attempt += 1) {
13396
+ if (attempt >= REVISION_RETRY_ATTEMPTS || Date.now() >= deadline)
13397
+ return failure2("busy", "records kept changing under concurrent writers; retry the call");
13398
+ Atomics.wait(retryPause, 0, 0, Math.floor(Math.random() * 4 * attempt) + 1);
13399
+ result = run();
13400
+ }
13401
+ return result;
13402
+ };
13375
13403
  var trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now;
13376
13404
  var mapRef = (ref, ids) => {
13377
13405
  if (ref.kind !== "record")
@@ -13619,6 +13647,9 @@ class WorkitCore {
13619
13647
  if (input.expectedWorkspaceRevision === undefined)
13620
13648
  input.expectedWorkspaceRevision = workspace ? workspace.revision : null;
13621
13649
  }
13650
+ retryOmittedRevisions(request, run) {
13651
+ return retryFilledRevisions(filledRevisions(request), run);
13652
+ }
13622
13653
  helperEntry(task, requireSession = false, requireActive = false) {
13623
13654
  const workerId = this.context.workerId ?? null;
13624
13655
  if (workerId === null)
@@ -13650,6 +13681,9 @@ class WorkitCore {
13650
13681
  return null;
13651
13682
  }
13652
13683
  state(request) {
13684
+ return request?.action === "import" ? this.retryOmittedRevisions(request, () => this.stateOnce(request)) : this.stateOnce(request);
13685
+ }
13686
+ stateOnce(request) {
13653
13687
  const root = this.contextRootError();
13654
13688
  if (!root.ok)
13655
13689
  return root;
@@ -13751,6 +13785,9 @@ class WorkitCore {
13751
13785
  });
13752
13786
  }
13753
13787
  task(request) {
13788
+ return this.retryOmittedRevisions(request, () => this.taskOnce(request));
13789
+ }
13790
+ taskOnce(request) {
13754
13791
  const root = this.contextRootError();
13755
13792
  if (!root.ok)
13756
13793
  return root;
@@ -13850,6 +13887,9 @@ class WorkitCore {
13850
13887
  }
13851
13888
  }
13852
13889
  policy(request) {
13890
+ return this.retryOmittedRevisions(request, () => this.policyOnce(request));
13891
+ }
13892
+ policyOnce(request) {
13853
13893
  const root = this.contextRootError();
13854
13894
  if (!root.ok)
13855
13895
  return root;
@@ -13896,6 +13936,9 @@ class WorkitCore {
13896
13936
  return success(changed.data.revision, null, changed.data.policy);
13897
13937
  }
13898
13938
  evidence(request) {
13939
+ return this.retryOmittedRevisions(request, () => this.evidenceOnce(request));
13940
+ }
13941
+ evidenceOnce(request) {
13899
13942
  const root = this.contextRootError();
13900
13943
  if (!root.ok)
13901
13944
  return root;
@@ -13980,6 +14023,23 @@ class WorkitCore {
13980
14023
  observeStandingDecision(request) {
13981
14024
  return this.recordDecision(request, undefined, true, true);
13982
14025
  }
14026
+ commitTask(taskId, expected, filled, recheck, update) {
14027
+ let revision = expected;
14028
+ let first = true;
14029
+ return retryFilledRevisions({ task: filled, workspace: false }, () => {
14030
+ if (!first) {
14031
+ const fresh = this.store.readTask(taskId);
14032
+ if (!fresh.ok)
14033
+ return fresh;
14034
+ const checked = recheck(fresh.data);
14035
+ if (!checked.ok)
14036
+ return checked;
14037
+ revision = fresh.data.revision;
14038
+ }
14039
+ first = false;
14040
+ return this.store.mutateTask(taskId, revision, update, trustedNow(this.context));
14041
+ });
14042
+ }
13983
14043
  recordDecision(request, nativeObservation, nativeRequired = false, standing = false) {
13984
14044
  const root = this.contextRootError();
13985
14045
  if (!root.ok)
@@ -14004,6 +14064,7 @@ class WorkitCore {
14004
14064
  return task;
14005
14065
  if ((this.context.workerId ?? null) !== null)
14006
14066
  return failure2("permission_denied", "helpers cannot record or revoke decisions");
14067
+ const filled = input.expectedRevision === undefined;
14007
14068
  this.fillRevisions(input, task.data);
14008
14069
  if (input.action === "record") {
14009
14070
  if (task.data.status === "closed")
@@ -14052,7 +14113,20 @@ class WorkitCore {
14052
14113
  const nativeProvenance = native?.ok ? retireNativeAuthority(native.data) : null;
14053
14114
  if (native?.ok && !nativeProvenance)
14054
14115
  return failure2("permission_denied", "native decision authority was retired");
14055
- const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
14116
+ let standingProvenance = standingApproval?.ok === true ? standingApproval.data : null;
14117
+ const recheck = (fresh) => {
14118
+ if (fresh.status === "closed")
14119
+ return failure2("invalid_transition", "closed task cannot record a decision");
14120
+ if (!standingProvenance)
14121
+ return success(null, null, null);
14122
+ const again = verifyStandingApproval(this.store.root, fresh, this.context.caller, input.binding);
14123
+ if (again.ok)
14124
+ standingProvenance = again.data;
14125
+ return again;
14126
+ };
14127
+ const changed = this.commitTask(task.data.id, input.expectedRevision, filled, recheck, (current, mutation) => {
14128
+ if (current.status === "closed")
14129
+ return failure2("invalid_transition", "closed task cannot record a decision");
14056
14130
  const latestContent = verifyDecisionContent(this.store, input.binding);
14057
14131
  if (!latestContent.ok)
14058
14132
  return latestContent;
@@ -14064,14 +14138,14 @@ class WorkitCore {
14064
14138
  const entry = {
14065
14139
  id: newId(),
14066
14140
  recordedAt: mutation.now,
14067
- provenance: standingApproval?.ok === true ? standingApproval.data : nativeProvenance ?? provenance(this.context, "agent_reported"),
14141
+ provenance: standingProvenance ?? nativeProvenance ?? provenance(this.context, "agent_reported"),
14068
14142
  data
14069
14143
  };
14070
14144
  return success(mutation.revision, null, {
14071
14145
  ...current,
14072
14146
  decisions: [...current.decisions, entry]
14073
14147
  });
14074
- }, trustedNow(this.context));
14148
+ });
14075
14149
  if (!changed.ok)
14076
14150
  return changed;
14077
14151
  return success(changed.data.revision, null, changed.data.decisions.at(-1));
@@ -14085,7 +14159,7 @@ class WorkitCore {
14085
14159
  return failure2("invalid_transition", "decision is already revoked");
14086
14160
  if (decision.data.consumption)
14087
14161
  return failure2("permission_denied", "consumed decision cannot be revoked");
14088
- const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
14162
+ const changed = this.commitTask(task.data.id, input.expectedRevision, filled, () => success(null, null, null), (current, mutation) => {
14089
14163
  const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
14090
14164
  if (!entry)
14091
14165
  return failure2("not_found", "decision not found");
@@ -14102,13 +14176,16 @@ class WorkitCore {
14102
14176
  ...current,
14103
14177
  decisions: current.decisions.map((candidate) => candidate.id === input.decisionId ? updated : candidate)
14104
14178
  });
14105
- }, trustedNow(this.context));
14179
+ });
14106
14180
  if (!changed.ok)
14107
14181
  return changed;
14108
14182
  const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
14109
14183
  return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "decision disappeared");
14110
14184
  }
14111
14185
  finding(request) {
14186
+ return this.retryOmittedRevisions(request, () => this.findingOnce(request));
14187
+ }
14188
+ findingOnce(request) {
14112
14189
  const root = this.contextRootError();
14113
14190
  if (!root.ok)
14114
14191
  return root;
@@ -14232,6 +14309,9 @@ class WorkitCore {
14232
14309
  return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "finding disappeared");
14233
14310
  }
14234
14311
  worker(request) {
14312
+ return this.retryOmittedRevisions(request, () => this.workerOnce(request));
14313
+ }
14314
+ workerOnce(request) {
14235
14315
  const root = this.contextRootError();
14236
14316
  if (!root.ok)
14237
14317
  return root;
@@ -14579,6 +14659,9 @@ class WorkitCore {
14579
14659
  return applied;
14580
14660
  }
14581
14661
  writer(request) {
14662
+ return this.retryOmittedRevisions(request, () => this.writerOnce(request));
14663
+ }
14664
+ writerOnce(request) {
14582
14665
  const root = this.contextRootError();
14583
14666
  if (!root.ok)
14584
14667
  return root;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cursor",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "private": false,
5
5
  "description": "Workit Cursor plugin — shared MCP transport, native hooks, and fourteen method skills",
6
6
  "keywords": [
@@ -44,8 +44,8 @@
44
44
  "build": "bun scripts/build.ts"
45
45
  },
46
46
  "dependencies": {
47
- "@brainervirus/workit-core": "^2.2.0",
48
- "@brainervirus/workit-mcp": "^2.2.0"
47
+ "@brainervirus/workit-core": "^2.2.2",
48
+ "@brainervirus/workit-mcp": "^2.2.2"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=24"