@brainervirus/workit-cli 2.2.0 → 2.2.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.
- package/dist/index.js +87 -9
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -9822,7 +9822,7 @@ class TaskStore {
|
|
|
9822
9822
|
if (!current.data)
|
|
9823
9823
|
return failure2("not_found", "workspace not found");
|
|
9824
9824
|
if (current.data.revision !== expected)
|
|
9825
|
-
return this.
|
|
9825
|
+
return this.workspaceConflict(expected, current.data.revision);
|
|
9826
9826
|
const previousBytes = this.snapshotBytes(this.workspacePath);
|
|
9827
9827
|
if (!previousBytes)
|
|
9828
9828
|
return failure2("storage_error", "workspace snapshot disappeared during mutation");
|
|
@@ -9865,7 +9865,7 @@ class TaskStore {
|
|
|
9865
9865
|
if (task.data.revision !== expected)
|
|
9866
9866
|
return this.conflict(expected, task.data.revision);
|
|
9867
9867
|
if (workspace.data.revision !== input.expectedWorkspaceRevision)
|
|
9868
|
-
return this.
|
|
9868
|
+
return this.workspaceConflict(input.expectedWorkspaceRevision, workspace.data.revision);
|
|
9869
9869
|
const previousWorkspaceBytes = this.snapshotBytes(this.workspacePath);
|
|
9870
9870
|
const previousTaskBytes = this.snapshotBytes(this.taskPath(input.taskId));
|
|
9871
9871
|
if (!previousWorkspaceBytes || !previousTaskBytes)
|
|
@@ -10675,6 +10675,9 @@ class TaskStore {
|
|
|
10675
10675
|
actualRevision: actual
|
|
10676
10676
|
});
|
|
10677
10677
|
}
|
|
10678
|
+
workspaceConflict(expected, actual) {
|
|
10679
|
+
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
|
|
10680
|
+
}
|
|
10678
10681
|
taskPath(taskId) {
|
|
10679
10682
|
return path5.join(this.tasksDir, `${taskId}.json`);
|
|
10680
10683
|
}
|
|
@@ -14756,6 +14759,9 @@ class WorkitCore {
|
|
|
14756
14759
|
if (input.expectedWorkspaceRevision === undefined)
|
|
14757
14760
|
input.expectedWorkspaceRevision = workspace ? workspace.revision : null;
|
|
14758
14761
|
}
|
|
14762
|
+
retryOmittedRevisions(request, run) {
|
|
14763
|
+
return retryFilledRevisions(filledRevisions(request), run);
|
|
14764
|
+
}
|
|
14759
14765
|
helperEntry(task, requireSession = false, requireActive = false) {
|
|
14760
14766
|
const workerId = this.context.workerId ?? null;
|
|
14761
14767
|
if (workerId === null)
|
|
@@ -14787,6 +14793,9 @@ class WorkitCore {
|
|
|
14787
14793
|
return null;
|
|
14788
14794
|
}
|
|
14789
14795
|
state(request) {
|
|
14796
|
+
return request?.action === "import" ? this.retryOmittedRevisions(request, () => this.stateOnce(request)) : this.stateOnce(request);
|
|
14797
|
+
}
|
|
14798
|
+
stateOnce(request) {
|
|
14790
14799
|
const root = this.contextRootError();
|
|
14791
14800
|
if (!root.ok)
|
|
14792
14801
|
return root;
|
|
@@ -14888,6 +14897,9 @@ class WorkitCore {
|
|
|
14888
14897
|
});
|
|
14889
14898
|
}
|
|
14890
14899
|
task(request) {
|
|
14900
|
+
return this.retryOmittedRevisions(request, () => this.taskOnce(request));
|
|
14901
|
+
}
|
|
14902
|
+
taskOnce(request) {
|
|
14891
14903
|
const root = this.contextRootError();
|
|
14892
14904
|
if (!root.ok)
|
|
14893
14905
|
return root;
|
|
@@ -14987,6 +14999,9 @@ class WorkitCore {
|
|
|
14987
14999
|
}
|
|
14988
15000
|
}
|
|
14989
15001
|
policy(request) {
|
|
15002
|
+
return this.retryOmittedRevisions(request, () => this.policyOnce(request));
|
|
15003
|
+
}
|
|
15004
|
+
policyOnce(request) {
|
|
14990
15005
|
const root = this.contextRootError();
|
|
14991
15006
|
if (!root.ok)
|
|
14992
15007
|
return root;
|
|
@@ -15033,6 +15048,9 @@ class WorkitCore {
|
|
|
15033
15048
|
return success(changed.data.revision, null, changed.data.policy);
|
|
15034
15049
|
}
|
|
15035
15050
|
evidence(request) {
|
|
15051
|
+
return this.retryOmittedRevisions(request, () => this.evidenceOnce(request));
|
|
15052
|
+
}
|
|
15053
|
+
evidenceOnce(request) {
|
|
15036
15054
|
const root = this.contextRootError();
|
|
15037
15055
|
if (!root.ok)
|
|
15038
15056
|
return root;
|
|
@@ -15117,6 +15135,23 @@ class WorkitCore {
|
|
|
15117
15135
|
observeStandingDecision(request) {
|
|
15118
15136
|
return this.recordDecision(request, undefined, true, true);
|
|
15119
15137
|
}
|
|
15138
|
+
commitTask(taskId, expected, filled, recheck, update) {
|
|
15139
|
+
let revision = expected;
|
|
15140
|
+
let first = true;
|
|
15141
|
+
return retryFilledRevisions({ task: filled, workspace: false }, () => {
|
|
15142
|
+
if (!first) {
|
|
15143
|
+
const fresh = this.store.readTask(taskId);
|
|
15144
|
+
if (!fresh.ok)
|
|
15145
|
+
return fresh;
|
|
15146
|
+
const checked = recheck(fresh.data);
|
|
15147
|
+
if (!checked.ok)
|
|
15148
|
+
return checked;
|
|
15149
|
+
revision = fresh.data.revision;
|
|
15150
|
+
}
|
|
15151
|
+
first = false;
|
|
15152
|
+
return this.store.mutateTask(taskId, revision, update, trustedNow(this.context));
|
|
15153
|
+
});
|
|
15154
|
+
}
|
|
15120
15155
|
recordDecision(request, nativeObservation, nativeRequired = false, standing = false) {
|
|
15121
15156
|
const root = this.contextRootError();
|
|
15122
15157
|
if (!root.ok)
|
|
@@ -15141,6 +15176,7 @@ class WorkitCore {
|
|
|
15141
15176
|
return task;
|
|
15142
15177
|
if ((this.context.workerId ?? null) !== null)
|
|
15143
15178
|
return failure2("permission_denied", "helpers cannot record or revoke decisions");
|
|
15179
|
+
const filled = input.expectedRevision === undefined;
|
|
15144
15180
|
this.fillRevisions(input, task.data);
|
|
15145
15181
|
if (input.action === "record") {
|
|
15146
15182
|
if (task.data.status === "closed")
|
|
@@ -15189,7 +15225,20 @@ class WorkitCore {
|
|
|
15189
15225
|
const nativeProvenance = native?.ok ? retireNativeAuthority(native.data) : null;
|
|
15190
15226
|
if (native?.ok && !nativeProvenance)
|
|
15191
15227
|
return failure2("permission_denied", "native decision authority was retired");
|
|
15192
|
-
|
|
15228
|
+
let standingProvenance = standingApproval?.ok === true ? standingApproval.data : null;
|
|
15229
|
+
const recheck = (fresh) => {
|
|
15230
|
+
if (fresh.status === "closed")
|
|
15231
|
+
return failure2("invalid_transition", "closed task cannot record a decision");
|
|
15232
|
+
if (!standingProvenance)
|
|
15233
|
+
return success(null, null, null);
|
|
15234
|
+
const again = verifyStandingApproval(this.store.root, fresh, this.context.caller, input.binding);
|
|
15235
|
+
if (again.ok)
|
|
15236
|
+
standingProvenance = again.data;
|
|
15237
|
+
return again;
|
|
15238
|
+
};
|
|
15239
|
+
const changed = this.commitTask(task.data.id, input.expectedRevision, filled, recheck, (current, mutation) => {
|
|
15240
|
+
if (current.status === "closed")
|
|
15241
|
+
return failure2("invalid_transition", "closed task cannot record a decision");
|
|
15193
15242
|
const latestContent = verifyDecisionContent(this.store, input.binding);
|
|
15194
15243
|
if (!latestContent.ok)
|
|
15195
15244
|
return latestContent;
|
|
@@ -15201,14 +15250,14 @@ class WorkitCore {
|
|
|
15201
15250
|
const entry = {
|
|
15202
15251
|
id: newId(),
|
|
15203
15252
|
recordedAt: mutation.now,
|
|
15204
|
-
provenance:
|
|
15253
|
+
provenance: standingProvenance ?? nativeProvenance ?? provenance(this.context, "agent_reported"),
|
|
15205
15254
|
data
|
|
15206
15255
|
};
|
|
15207
15256
|
return success(mutation.revision, null, {
|
|
15208
15257
|
...current,
|
|
15209
15258
|
decisions: [...current.decisions, entry]
|
|
15210
15259
|
});
|
|
15211
|
-
}
|
|
15260
|
+
});
|
|
15212
15261
|
if (!changed.ok)
|
|
15213
15262
|
return changed;
|
|
15214
15263
|
return success(changed.data.revision, null, changed.data.decisions.at(-1));
|
|
@@ -15222,7 +15271,7 @@ class WorkitCore {
|
|
|
15222
15271
|
return failure2("invalid_transition", "decision is already revoked");
|
|
15223
15272
|
if (decision.data.consumption)
|
|
15224
15273
|
return failure2("permission_denied", "consumed decision cannot be revoked");
|
|
15225
|
-
const changed = this.
|
|
15274
|
+
const changed = this.commitTask(task.data.id, input.expectedRevision, filled, () => success(null, null, null), (current, mutation) => {
|
|
15226
15275
|
const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
15227
15276
|
if (!entry)
|
|
15228
15277
|
return failure2("not_found", "decision not found");
|
|
@@ -15239,13 +15288,16 @@ class WorkitCore {
|
|
|
15239
15288
|
...current,
|
|
15240
15289
|
decisions: current.decisions.map((candidate) => candidate.id === input.decisionId ? updated : candidate)
|
|
15241
15290
|
});
|
|
15242
|
-
}
|
|
15291
|
+
});
|
|
15243
15292
|
if (!changed.ok)
|
|
15244
15293
|
return changed;
|
|
15245
15294
|
const entry = changed.data.decisions.find((candidate) => candidate.id === input.decisionId);
|
|
15246
15295
|
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "decision disappeared");
|
|
15247
15296
|
}
|
|
15248
15297
|
finding(request) {
|
|
15298
|
+
return this.retryOmittedRevisions(request, () => this.findingOnce(request));
|
|
15299
|
+
}
|
|
15300
|
+
findingOnce(request) {
|
|
15249
15301
|
const root = this.contextRootError();
|
|
15250
15302
|
if (!root.ok)
|
|
15251
15303
|
return root;
|
|
@@ -15369,6 +15421,9 @@ class WorkitCore {
|
|
|
15369
15421
|
return entry ? success(changed.data.revision, null, entry) : failure2("recovery_required", "finding disappeared");
|
|
15370
15422
|
}
|
|
15371
15423
|
worker(request) {
|
|
15424
|
+
return this.retryOmittedRevisions(request, () => this.workerOnce(request));
|
|
15425
|
+
}
|
|
15426
|
+
workerOnce(request) {
|
|
15372
15427
|
const root = this.contextRootError();
|
|
15373
15428
|
if (!root.ok)
|
|
15374
15429
|
return root;
|
|
@@ -15716,6 +15771,9 @@ class WorkitCore {
|
|
|
15716
15771
|
return applied;
|
|
15717
15772
|
}
|
|
15718
15773
|
writer(request) {
|
|
15774
|
+
return this.retryOmittedRevisions(request, () => this.writerOnce(request));
|
|
15775
|
+
}
|
|
15776
|
+
writerOnce(request) {
|
|
15719
15777
|
const root = this.contextRootError();
|
|
15720
15778
|
if (!root.ok)
|
|
15721
15779
|
return root;
|
|
@@ -16474,7 +16532,25 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
16474
16532
|
return changed;
|
|
16475
16533
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
16476
16534
|
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
|
|
16477
|
-
}, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] })),
|
|
16535
|
+
}, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || bindingCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), REVISION_RETRY_ATTEMPTS = 8, retryPause, filledRevisions = (request) => {
|
|
16536
|
+
const value = typeof request === "object" && request !== null ? request : {};
|
|
16537
|
+
return {
|
|
16538
|
+
task: value.expectedRevision === undefined,
|
|
16539
|
+
workspace: value.expectedWorkspaceRevision === undefined
|
|
16540
|
+
};
|
|
16541
|
+
}, filledConflict = (result, filled) => !result.ok && result.code === "revision_conflict" && (("actualRevision" in result.details) && filled.task || ("actualWorkspaceRevision" in result.details) && filled.workspace), retryFilledRevisions = (filled, run) => {
|
|
16542
|
+
if (!filled.task && !filled.workspace)
|
|
16543
|
+
return run();
|
|
16544
|
+
let result = run();
|
|
16545
|
+
const deadline = Date.now() + defaultLockTimeout();
|
|
16546
|
+
for (let attempt = 1;filledConflict(result, filled); attempt += 1) {
|
|
16547
|
+
if (attempt >= REVISION_RETRY_ATTEMPTS || Date.now() >= deadline)
|
|
16548
|
+
return failure2("busy", "records kept changing under concurrent writers; retry the call");
|
|
16549
|
+
Atomics.wait(retryPause, 0, 0, Math.floor(Math.random() * 4 * attempt) + 1);
|
|
16550
|
+
result = run();
|
|
16551
|
+
}
|
|
16552
|
+
return result;
|
|
16553
|
+
}, trustedNow = (context) => typeof context.now === "function" ? context.now() : context.now, mapRef = (ref, ids) => {
|
|
16478
16554
|
if (ref.kind !== "record")
|
|
16479
16555
|
return ref;
|
|
16480
16556
|
return { ...ref, id: ids.get(ref.id) ?? ref.id };
|
|
@@ -16685,11 +16761,13 @@ var init_task_engine = __esm(() => {
|
|
|
16685
16761
|
init_authority();
|
|
16686
16762
|
init_policy_resolver();
|
|
16687
16763
|
init_auto_approval();
|
|
16764
|
+
init_store_lock();
|
|
16688
16765
|
init_task_context();
|
|
16689
16766
|
init_workers();
|
|
16690
16767
|
init_task_evaluation();
|
|
16691
16768
|
verifiedWorkers = new WeakMap;
|
|
16692
16769
|
dispatchReservations = new WeakMap;
|
|
16770
|
+
retryPause = new Int32Array(new SharedArrayBuffer(4));
|
|
16693
16771
|
});
|
|
16694
16772
|
|
|
16695
16773
|
// packages/workit-core/src/core.ts
|
|
@@ -73026,7 +73104,7 @@ import path34 from "node:path";
|
|
|
73026
73104
|
// packages/workit-cli/package.json
|
|
73027
73105
|
var package_default = {
|
|
73028
73106
|
name: "@brainervirus/workit-cli",
|
|
73029
|
-
version: "2.
|
|
73107
|
+
version: "2.2.0",
|
|
73030
73108
|
private: false,
|
|
73031
73109
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
73032
73110
|
keywords: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
6
6
|
"keywords": [
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"typecheck": "tsc --noEmit"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@brainervirus/workit-core": "^2.2.
|
|
41
|
-
"@brainervirus/workit-cursor": "^2.2.
|
|
42
|
-
"@brainervirus/workit-opencode": "^2.2.
|
|
40
|
+
"@brainervirus/workit-core": "^2.2.1",
|
|
41
|
+
"@brainervirus/workit-cursor": "^2.2.1",
|
|
42
|
+
"@brainervirus/workit-opencode": "^2.2.1",
|
|
43
43
|
"@inkjs/ui": "2.0.0",
|
|
44
44
|
"ink": "7.1.1",
|
|
45
45
|
"react": "19.2.8"
|