@brainervirus/workit-cli 1.0.10 → 1.0.11
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 +101 -12
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -50928,10 +50928,11 @@ var decisionSchema = object({
|
|
|
50928
50928
|
presented: text,
|
|
50929
50929
|
approvedContent: text,
|
|
50930
50930
|
displayed: text.optional(),
|
|
50931
|
-
contentRefs: array(refSchema)
|
|
50931
|
+
contentRefs: array(refSchema),
|
|
50932
|
+
statedChoice: object({ ref: text, text }).strict().optional()
|
|
50932
50933
|
}).strict(),
|
|
50933
50934
|
digest,
|
|
50934
|
-
response: _enum(["approved", "rejected"]),
|
|
50935
|
+
response: _enum(["approved", "rejected", "stated"]),
|
|
50935
50936
|
requirementIds: array(digest),
|
|
50936
50937
|
revoked: object({ at: utc, reason: text }).strict().nullable(),
|
|
50937
50938
|
consumption: object({
|
|
@@ -58940,7 +58941,7 @@ function evaluateEvidence(task, candidate) {
|
|
|
58940
58941
|
}
|
|
58941
58942
|
var scopeCovers2 = scopeCovers;
|
|
58942
58943
|
var applicableDecision2 = (task, workspace, requirement, checkoutRoot) => task.decisions.filter((entry) => entry.provenance.kind !== "imported").map((entry) => entry.data).filter((decision) => decision.purpose === "limitation" && decision.response === "approved" && decision.revoked === null && decision.binding.taskId === task.id && decision.binding.workspaceId === workspace.id && decision.requirementIds.includes(requirement.id) && decision.binding.scope && scopeCovers2(decision.binding.scope, requirement.scope) && decision.digest === decisionDigest(decision) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, decision.binding).ok : decision.binding.contentRefs.every((reference) => reference.kind !== "file")));
|
|
58943
|
-
var applicableRequirementDecision = (task, workspace, requirement, checkoutRoot) => task.decisions.filter(({ data, provenance }) => provenance.kind !== "imported" && data.purpose !== "limitation" && data.response === "approved" && data.revoked === null && data.binding.taskId === task.id && data.binding.workspaceId === workspace.id && data.requirementIds.includes(requirement.id) && scopeCovers2(data.binding.scope, requirement.scope) && data.digest === decisionDigest(data) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, data.binding).ok : data.binding.contentRefs.every((reference) => reference.kind !== "file"))).map(({ id }) => ({ id }));
|
|
58944
|
+
var applicableRequirementDecision = (task, workspace, requirement, checkoutRoot) => task.decisions.filter(({ data, provenance }) => provenance.kind !== "imported" && data.purpose !== "limitation" && (data.response === "approved" || data.response === "stated") && data.revoked === null && data.binding.taskId === task.id && data.binding.workspaceId === workspace.id && data.requirementIds.includes(requirement.id) && scopeCovers2(data.binding.scope, requirement.scope) && data.digest === decisionDigest(data) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, data.binding).ok : data.binding.contentRefs.every((reference) => reference.kind !== "file"))).map(({ id }) => ({ id }));
|
|
58944
58945
|
var evidenceMatchesRequirement = (kind, evidenceKind, dimension) => {
|
|
58945
58946
|
if (kind !== "passed")
|
|
58946
58947
|
return false;
|
|
@@ -59016,7 +59017,7 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
59016
59017
|
status: "satisfied",
|
|
59017
59018
|
evidenceIds: [],
|
|
59018
59019
|
decisionIds: decisions.map((decision) => decision.id),
|
|
59019
|
-
reason: "an applicable approved decision satisfies the requirement"
|
|
59020
|
+
reason: "an applicable approved or stated decision satisfies the requirement"
|
|
59020
59021
|
};
|
|
59021
59022
|
const limitations = requirement.acceptanceAllowed ? applicableDecision2(task, workspace, requirement, checkoutRoot) : [];
|
|
59022
59023
|
if (limitations.length)
|
|
@@ -59500,12 +59501,62 @@ var planCommitBinding = (store, host, actor, operation) => {
|
|
|
59500
59501
|
};
|
|
59501
59502
|
var approvedExternalAction = (store, host, actor, operation) => {
|
|
59502
59503
|
const selected = externalActionState(store, host, actor, operation);
|
|
59503
|
-
if (
|
|
59504
|
+
if (selected.ok) {
|
|
59505
|
+
if (selected.data.entry.data.consumption !== null)
|
|
59506
|
+
return failure(selected.data.entry.data.consumption.state === "uncertain" ? "external_outcome_unknown" : "permission_denied", selected.data.entry.data.consumption.state === "uncertain" ? "previous external action outcome is unknown" : "external action was already settled");
|
|
59504
59507
|
return selected;
|
|
59505
|
-
|
|
59506
|
-
|
|
59508
|
+
}
|
|
59509
|
+
const intent = approvedBranchSetupIntent(store, host, actor, operation);
|
|
59510
|
+
if (intent.ok) {
|
|
59511
|
+
if (intent.data.entry.data.consumption !== null)
|
|
59512
|
+
return failure(intent.data.entry.data.consumption.state === "uncertain" ? "external_outcome_unknown" : "permission_denied", intent.data.entry.data.consumption.state === "uncertain" ? "previous external action outcome is unknown" : "external action was already settled");
|
|
59513
|
+
return intent;
|
|
59514
|
+
}
|
|
59507
59515
|
return selected;
|
|
59508
59516
|
};
|
|
59517
|
+
var branchSetupIntent = (descriptor) => {
|
|
59518
|
+
try {
|
|
59519
|
+
const value = JSON.parse(descriptor);
|
|
59520
|
+
if (value.operation !== "git.branch_setup" || !value.payload)
|
|
59521
|
+
return null;
|
|
59522
|
+
const { target_branch, resolved } = value.payload;
|
|
59523
|
+
if (typeof target_branch !== "string" || !target_branch || !resolved)
|
|
59524
|
+
return null;
|
|
59525
|
+
if (typeof resolved.base_branch !== "string" || typeof resolved.target_exists !== "boolean")
|
|
59526
|
+
return null;
|
|
59527
|
+
return {
|
|
59528
|
+
target: target_branch,
|
|
59529
|
+
base: resolved.base_branch,
|
|
59530
|
+
remoteBase: typeof resolved.remote_base === "string" ? resolved.remote_base : null,
|
|
59531
|
+
targetExists: resolved.target_exists
|
|
59532
|
+
};
|
|
59533
|
+
} catch {
|
|
59534
|
+
return null;
|
|
59535
|
+
}
|
|
59536
|
+
};
|
|
59537
|
+
var approvedBranchSetupIntent = (store, host, actor, operation) => {
|
|
59538
|
+
const current = branchSetupIntent(operation);
|
|
59539
|
+
if (!current)
|
|
59540
|
+
return failure("permission_denied", "no approved action is bound to this session");
|
|
59541
|
+
const listed = store.listTasks();
|
|
59542
|
+
const workspace = store.readWorkspace();
|
|
59543
|
+
if (!listed.ok || !workspace.ok)
|
|
59544
|
+
return failure("storage_error", "external action state is unavailable");
|
|
59545
|
+
if (!workspace.data)
|
|
59546
|
+
return failure("not_found", "workspace not found");
|
|
59547
|
+
const candidates = listed.data.flatMap((task) => {
|
|
59548
|
+
if (task.status !== "active" || task.workspaceId !== workspace.data.id || task.intent.provenance.session?.kind !== "host" || task.intent.provenance.session.host !== host || task.intent.provenance.session.handle !== actor)
|
|
59549
|
+
return [];
|
|
59550
|
+
return task.decisions.filter((entry) => entry.data.purpose === "action" && entry.data.response === "approved" && entry.data.revoked === null).map((entry) => ({ task, entry }));
|
|
59551
|
+
});
|
|
59552
|
+
const matches = candidates.filter(({ entry }) => {
|
|
59553
|
+
const intent = branchSetupIntent(entry.data.binding.approvedContent);
|
|
59554
|
+
return intent !== null && intent.target === current.target && intent.base === current.base && intent.remoteBase === current.remoteBase && intent.targetExists === current.targetExists;
|
|
59555
|
+
});
|
|
59556
|
+
if (matches.length !== 1)
|
|
59557
|
+
return failure("permission_denied", matches.length === 0 ? "no approved action is bound to this session" : "multiple approved actions match this session");
|
|
59558
|
+
return success(workspace.data.revision, null, { ...matches[0], workspace: workspace.data });
|
|
59559
|
+
};
|
|
59509
59560
|
var priorResolvedDrift = (store, host, actor, operation, payload, currentResolved) => {
|
|
59510
59561
|
const prior = priorExternalAction(store, host, actor, operation, payload);
|
|
59511
59562
|
if (!prior.ok)
|
|
@@ -59519,6 +59570,24 @@ var priorResolvedDrift = (store, host, actor, operation, payload, currentResolve
|
|
|
59519
59570
|
}
|
|
59520
59571
|
if (baseline === undefined || baseline === null)
|
|
59521
59572
|
return success(null, null, null);
|
|
59573
|
+
if (operation === "git.branch_setup") {
|
|
59574
|
+
const before = branchSetupIntent(prior.data.entry.data.binding.approvedContent);
|
|
59575
|
+
let after = null;
|
|
59576
|
+
try {
|
|
59577
|
+
after = branchSetupIntent(JSON.stringify({
|
|
59578
|
+
operation,
|
|
59579
|
+
payload: { ...payload, resolved: currentResolved }
|
|
59580
|
+
}));
|
|
59581
|
+
} catch {
|
|
59582
|
+
after = null;
|
|
59583
|
+
}
|
|
59584
|
+
if (before && after) {
|
|
59585
|
+
const moved = before.target !== after.target ? "target_branch" : before.base !== after.base ? "base_branch" : before.remoteBase !== after.remoteBase ? "remote_base" : before.targetExists !== after.targetExists ? "target_exists" : null;
|
|
59586
|
+
if (moved === null)
|
|
59587
|
+
return success(null, null, null);
|
|
59588
|
+
return failure("invalid_input", `repository state changed since approval (${moved} moved); show the current state and approve the action again`, { outcome: "not_started", operation });
|
|
59589
|
+
}
|
|
59590
|
+
}
|
|
59522
59591
|
if (canonicalJson(baseline) === canonicalJson(currentResolved))
|
|
59523
59592
|
return success(null, null, null);
|
|
59524
59593
|
return failure("invalid_input", "repository state changed since approval; show the current state and approve the action again", { outcome: "not_started", operation });
|
|
@@ -60774,7 +60843,12 @@ class WorkitCore {
|
|
|
60774
60843
|
const input = parsed.data;
|
|
60775
60844
|
if (nativeRequired && input.action !== "record")
|
|
60776
60845
|
return failure("permission_denied", "native observation is only valid for recording decisions");
|
|
60777
|
-
|
|
60846
|
+
const stated = input.action === "record" && input.response === "stated";
|
|
60847
|
+
if (stated && input.purpose === "action")
|
|
60848
|
+
return failure("permission_denied", "stated choices cannot authorize mutating actions");
|
|
60849
|
+
if (stated && !input.binding?.statedChoice)
|
|
60850
|
+
return failure("invalid_input", "stated choices require binding.statedChoice");
|
|
60851
|
+
if (nativeRequired && nativeObservation === undefined && !stated)
|
|
60778
60852
|
return failure("permission_denied", "native decision observation is required");
|
|
60779
60853
|
const task = this.store.readTask(input.taskId);
|
|
60780
60854
|
if (!task.ok)
|
|
@@ -60807,7 +60881,7 @@ class WorkitCore {
|
|
|
60807
60881
|
consumption: null
|
|
60808
60882
|
};
|
|
60809
60883
|
const data = { ...base, digest: decisionDigest(base) };
|
|
60810
|
-
const native = nativeRequired ? verifyNativeDecision(this.context.nativeAuthority, {
|
|
60884
|
+
const native = nativeRequired && !stated ? verifyNativeDecision(this.context.nativeAuthority, {
|
|
60811
60885
|
observation: nativeObservation,
|
|
60812
60886
|
expected: {
|
|
60813
60887
|
taskId: task.data.id,
|
|
@@ -64288,13 +64362,20 @@ var actionProposalQuestion = (request, descriptorPayload) => {
|
|
|
64288
64362
|
approvedText: "Reapply the recorded stash."
|
|
64289
64363
|
};
|
|
64290
64364
|
const target = String(payload.target_branch ?? "");
|
|
64365
|
+
const stashes = payload.stash === "yes" && resolved.dirty === true;
|
|
64291
64366
|
if (resolved.target_exists === true)
|
|
64292
|
-
return {
|
|
64367
|
+
return stashes ? {
|
|
64368
|
+
presented: `Workit decision: action — Stash the dirty working tree and switch to branch \`${target}\`?`,
|
|
64369
|
+
approvedText: `Stash and switch to \`${target}\`.`
|
|
64370
|
+
} : {
|
|
64293
64371
|
presented: `Workit decision: action — Switch to branch \`${target}\`?`,
|
|
64294
64372
|
approvedText: `Switch to \`${target}\`.`
|
|
64295
64373
|
};
|
|
64296
64374
|
const base = String(resolved.base_branch ?? "the base branch");
|
|
64297
|
-
return {
|
|
64375
|
+
return stashes ? {
|
|
64376
|
+
presented: `Workit decision: action — Stash the dirty working tree and create branch \`${target}\` from \`${base}\` (currently ${shortSha(resolved.remote_base)})?`,
|
|
64377
|
+
approvedText: `Stash and create \`${target}\` from \`${base}\` at ${shortSha(resolved.remote_base)}.`
|
|
64378
|
+
} : {
|
|
64298
64379
|
presented: `Workit decision: action — Create branch \`${target}\` from \`${base}\` (currently ${shortSha(resolved.remote_base)})?`,
|
|
64299
64380
|
approvedText: `Create \`${target}\` from \`${base}\` at ${shortSha(resolved.remote_base)}.`
|
|
64300
64381
|
};
|
|
@@ -65486,7 +65567,7 @@ async function runActionCommand(argv, deps = {}) {
|
|
|
65486
65567
|
return 2;
|
|
65487
65568
|
}
|
|
65488
65569
|
const root = deps.root ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? deps.cwd ?? process.cwd();
|
|
65489
|
-
|
|
65570
|
+
let resolved = resolveExternalActionRequest(root, parsed.data);
|
|
65490
65571
|
if (!resolved.ok) {
|
|
65491
65572
|
if (json)
|
|
65492
65573
|
jsonResult(outOf(deps), resolved);
|
|
@@ -65494,6 +65575,14 @@ async function runActionCommand(argv, deps = {}) {
|
|
|
65494
65575
|
printHuman(resolved, deps);
|
|
65495
65576
|
return 2;
|
|
65496
65577
|
}
|
|
65578
|
+
if (resolved.data.request.operation === "git.branch_setup" && resolved.data.descriptorPayload.resolved?.dirty === true && resolved.data.descriptorPayload.stash !== "yes") {
|
|
65579
|
+
const upgraded = resolveExternalActionRequest(root, {
|
|
65580
|
+
...parsed.data,
|
|
65581
|
+
payload: { ...parsed.data.payload, stash: "yes" }
|
|
65582
|
+
});
|
|
65583
|
+
if (upgraded.ok)
|
|
65584
|
+
resolved = upgraded;
|
|
65585
|
+
}
|
|
65497
65586
|
const normalized = resolved.data.request;
|
|
65498
65587
|
const descriptor = externalActionDescriptor(normalized.operation, resolved.data.descriptorPayload);
|
|
65499
65588
|
if (preview) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
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": "^1.0.
|
|
41
|
-
"@brainervirus/workit-cursor": "^1.0.
|
|
42
|
-
"@brainervirus/workit-opencode": "^1.0.
|
|
40
|
+
"@brainervirus/workit-core": "^1.0.11",
|
|
41
|
+
"@brainervirus/workit-cursor": "^1.0.11",
|
|
42
|
+
"@brainervirus/workit-opencode": "^1.0.11",
|
|
43
43
|
"@inkjs/ui": "2.0.0",
|
|
44
44
|
"ink": "7.1.1",
|
|
45
45
|
"react": "19.2.8"
|