@brainervirus/workit-opencode 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/plugin.js +156 -40
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -7591,10 +7591,11 @@ var decisionSchema = object({
|
|
|
7591
7591
|
presented: text,
|
|
7592
7592
|
approvedContent: text,
|
|
7593
7593
|
displayed: text.optional(),
|
|
7594
|
-
contentRefs: array(refSchema)
|
|
7594
|
+
contentRefs: array(refSchema),
|
|
7595
|
+
statedChoice: object({ ref: text, text }).strict().optional()
|
|
7595
7596
|
}).strict(),
|
|
7596
7597
|
digest,
|
|
7597
|
-
response: _enum(["approved", "rejected"]),
|
|
7598
|
+
response: _enum(["approved", "rejected", "stated"]),
|
|
7598
7599
|
requirementIds: array(digest),
|
|
7599
7600
|
revoked: object({ at: utc, reason: text }).strict().nullable(),
|
|
7600
7601
|
consumption: object({
|
|
@@ -10413,7 +10414,7 @@ function evaluateEvidence(task, candidate) {
|
|
|
10413
10414
|
}
|
|
10414
10415
|
var scopeCovers2 = scopeCovers;
|
|
10415
10416
|
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")));
|
|
10416
|
-
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 }));
|
|
10417
|
+
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 }));
|
|
10417
10418
|
var evidenceMatchesRequirement = (kind, evidenceKind, dimension) => {
|
|
10418
10419
|
if (kind !== "passed")
|
|
10419
10420
|
return false;
|
|
@@ -10489,7 +10490,7 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
10489
10490
|
status: "satisfied",
|
|
10490
10491
|
evidenceIds: [],
|
|
10491
10492
|
decisionIds: decisions.map((decision) => decision.id),
|
|
10492
|
-
reason: "an applicable approved decision satisfies the requirement"
|
|
10493
|
+
reason: "an applicable approved or stated decision satisfies the requirement"
|
|
10493
10494
|
};
|
|
10494
10495
|
const limitations = requirement.acceptanceAllowed ? applicableDecision2(task, workspace, requirement, checkoutRoot) : [];
|
|
10495
10496
|
if (limitations.length)
|
|
@@ -10822,6 +10823,23 @@ function shellRouteIntent(command) {
|
|
|
10822
10823
|
}
|
|
10823
10824
|
return null;
|
|
10824
10825
|
}
|
|
10826
|
+
function hasLiveWorkitTask(dir) {
|
|
10827
|
+
try {
|
|
10828
|
+
if (typeof dir !== "string" || dir === "")
|
|
10829
|
+
return false;
|
|
10830
|
+
const listed = new TaskStore(dir).listTasks();
|
|
10831
|
+
if (!listed.ok)
|
|
10832
|
+
return false;
|
|
10833
|
+
return listed.data.some((task) => task.status === "active" || task.status === "paused");
|
|
10834
|
+
} catch {
|
|
10835
|
+
return false;
|
|
10836
|
+
}
|
|
10837
|
+
}
|
|
10838
|
+
function shouldDenyShellRoute(dir, command) {
|
|
10839
|
+
if (!hasLiveWorkitTask(dir))
|
|
10840
|
+
return null;
|
|
10841
|
+
return shellRouteIntent(command);
|
|
10842
|
+
}
|
|
10825
10843
|
// packages/workit-core/src/core/external-action.ts
|
|
10826
10844
|
import { execFileSync } from "node:child_process";
|
|
10827
10845
|
var externalActionSchema = discriminatedUnion("operation", [
|
|
@@ -11068,12 +11086,62 @@ var planCommitBinding = (store, host, actor, operation) => {
|
|
|
11068
11086
|
};
|
|
11069
11087
|
var approvedExternalAction = (store, host, actor, operation) => {
|
|
11070
11088
|
const selected = externalActionState(store, host, actor, operation);
|
|
11071
|
-
if (
|
|
11089
|
+
if (selected.ok) {
|
|
11090
|
+
if (selected.data.entry.data.consumption !== null)
|
|
11091
|
+
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");
|
|
11072
11092
|
return selected;
|
|
11073
|
-
|
|
11074
|
-
|
|
11093
|
+
}
|
|
11094
|
+
const intent = approvedBranchSetupIntent(store, host, actor, operation);
|
|
11095
|
+
if (intent.ok) {
|
|
11096
|
+
if (intent.data.entry.data.consumption !== null)
|
|
11097
|
+
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");
|
|
11098
|
+
return intent;
|
|
11099
|
+
}
|
|
11075
11100
|
return selected;
|
|
11076
11101
|
};
|
|
11102
|
+
var branchSetupIntent = (descriptor) => {
|
|
11103
|
+
try {
|
|
11104
|
+
const value = JSON.parse(descriptor);
|
|
11105
|
+
if (value.operation !== "git.branch_setup" || !value.payload)
|
|
11106
|
+
return null;
|
|
11107
|
+
const { target_branch, resolved } = value.payload;
|
|
11108
|
+
if (typeof target_branch !== "string" || !target_branch || !resolved)
|
|
11109
|
+
return null;
|
|
11110
|
+
if (typeof resolved.base_branch !== "string" || typeof resolved.target_exists !== "boolean")
|
|
11111
|
+
return null;
|
|
11112
|
+
return {
|
|
11113
|
+
target: target_branch,
|
|
11114
|
+
base: resolved.base_branch,
|
|
11115
|
+
remoteBase: typeof resolved.remote_base === "string" ? resolved.remote_base : null,
|
|
11116
|
+
targetExists: resolved.target_exists
|
|
11117
|
+
};
|
|
11118
|
+
} catch {
|
|
11119
|
+
return null;
|
|
11120
|
+
}
|
|
11121
|
+
};
|
|
11122
|
+
var approvedBranchSetupIntent = (store, host, actor, operation) => {
|
|
11123
|
+
const current = branchSetupIntent(operation);
|
|
11124
|
+
if (!current)
|
|
11125
|
+
return failure("permission_denied", "no approved action is bound to this session");
|
|
11126
|
+
const listed = store.listTasks();
|
|
11127
|
+
const workspace = store.readWorkspace();
|
|
11128
|
+
if (!listed.ok || !workspace.ok)
|
|
11129
|
+
return failure("storage_error", "external action state is unavailable");
|
|
11130
|
+
if (!workspace.data)
|
|
11131
|
+
return failure("not_found", "workspace not found");
|
|
11132
|
+
const candidates = listed.data.flatMap((task) => {
|
|
11133
|
+
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)
|
|
11134
|
+
return [];
|
|
11135
|
+
return task.decisions.filter((entry) => entry.data.purpose === "action" && entry.data.response === "approved" && entry.data.revoked === null).map((entry) => ({ task, entry }));
|
|
11136
|
+
});
|
|
11137
|
+
const matches = candidates.filter(({ entry }) => {
|
|
11138
|
+
const intent = branchSetupIntent(entry.data.binding.approvedContent);
|
|
11139
|
+
return intent !== null && intent.target === current.target && intent.base === current.base && intent.remoteBase === current.remoteBase && intent.targetExists === current.targetExists;
|
|
11140
|
+
});
|
|
11141
|
+
if (matches.length !== 1)
|
|
11142
|
+
return failure("permission_denied", matches.length === 0 ? "no approved action is bound to this session" : "multiple approved actions match this session");
|
|
11143
|
+
return success(workspace.data.revision, null, { ...matches[0], workspace: workspace.data });
|
|
11144
|
+
};
|
|
11077
11145
|
var priorResolvedDrift = (store, host, actor, operation, payload, currentResolved) => {
|
|
11078
11146
|
const prior = priorExternalAction(store, host, actor, operation, payload);
|
|
11079
11147
|
if (!prior.ok)
|
|
@@ -11087,6 +11155,24 @@ var priorResolvedDrift = (store, host, actor, operation, payload, currentResolve
|
|
|
11087
11155
|
}
|
|
11088
11156
|
if (baseline === undefined || baseline === null)
|
|
11089
11157
|
return success(null, null, null);
|
|
11158
|
+
if (operation === "git.branch_setup") {
|
|
11159
|
+
const before = branchSetupIntent(prior.data.entry.data.binding.approvedContent);
|
|
11160
|
+
let after = null;
|
|
11161
|
+
try {
|
|
11162
|
+
after = branchSetupIntent(JSON.stringify({
|
|
11163
|
+
operation,
|
|
11164
|
+
payload: { ...payload, resolved: currentResolved }
|
|
11165
|
+
}));
|
|
11166
|
+
} catch {
|
|
11167
|
+
after = null;
|
|
11168
|
+
}
|
|
11169
|
+
if (before && after) {
|
|
11170
|
+
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;
|
|
11171
|
+
if (moved === null)
|
|
11172
|
+
return success(null, null, null);
|
|
11173
|
+
return failure("invalid_input", `repository state changed since approval (${moved} moved); show the current state and approve the action again`, { outcome: "not_started", operation });
|
|
11174
|
+
}
|
|
11175
|
+
}
|
|
11090
11176
|
if (canonicalJson(baseline) === canonicalJson(currentResolved))
|
|
11091
11177
|
return success(null, null, null);
|
|
11092
11178
|
return failure("invalid_input", "repository state changed since approval; show the current state and approve the action again", { outcome: "not_started", operation });
|
|
@@ -12361,7 +12447,12 @@ class WorkitCore {
|
|
|
12361
12447
|
const input = parsed.data;
|
|
12362
12448
|
if (nativeRequired && input.action !== "record")
|
|
12363
12449
|
return failure("permission_denied", "native observation is only valid for recording decisions");
|
|
12364
|
-
|
|
12450
|
+
const stated = input.action === "record" && input.response === "stated";
|
|
12451
|
+
if (stated && input.purpose === "action")
|
|
12452
|
+
return failure("permission_denied", "stated choices cannot authorize mutating actions");
|
|
12453
|
+
if (stated && !input.binding?.statedChoice)
|
|
12454
|
+
return failure("invalid_input", "stated choices require binding.statedChoice");
|
|
12455
|
+
if (nativeRequired && nativeObservation === undefined && !stated)
|
|
12365
12456
|
return failure("permission_denied", "native decision observation is required");
|
|
12366
12457
|
const task = this.store.readTask(input.taskId);
|
|
12367
12458
|
if (!task.ok)
|
|
@@ -12394,7 +12485,7 @@ class WorkitCore {
|
|
|
12394
12485
|
consumption: null
|
|
12395
12486
|
};
|
|
12396
12487
|
const data = { ...base, digest: decisionDigest(base) };
|
|
12397
|
-
const native = nativeRequired ? verifyNativeDecision(this.context.nativeAuthority, {
|
|
12488
|
+
const native = nativeRequired && !stated ? verifyNativeDecision(this.context.nativeAuthority, {
|
|
12398
12489
|
observation: nativeObservation,
|
|
12399
12490
|
expected: {
|
|
12400
12491
|
taskId: task.data.id,
|
|
@@ -30820,13 +30911,20 @@ var actionProposalQuestion = (request, descriptorPayload) => {
|
|
|
30820
30911
|
approvedText: "Reapply the recorded stash."
|
|
30821
30912
|
};
|
|
30822
30913
|
const target = String(payload.target_branch ?? "");
|
|
30914
|
+
const stashes = payload.stash === "yes" && resolved.dirty === true;
|
|
30823
30915
|
if (resolved.target_exists === true)
|
|
30824
|
-
return {
|
|
30916
|
+
return stashes ? {
|
|
30917
|
+
presented: `Workit decision: action — Stash the dirty working tree and switch to branch \`${target}\`?`,
|
|
30918
|
+
approvedText: `Stash and switch to \`${target}\`.`
|
|
30919
|
+
} : {
|
|
30825
30920
|
presented: `Workit decision: action — Switch to branch \`${target}\`?`,
|
|
30826
30921
|
approvedText: `Switch to \`${target}\`.`
|
|
30827
30922
|
};
|
|
30828
30923
|
const base = String(resolved.base_branch ?? "the base branch");
|
|
30829
|
-
return {
|
|
30924
|
+
return stashes ? {
|
|
30925
|
+
presented: `Workit decision: action — Stash the dirty working tree and create branch \`${target}\` from \`${base}\` (currently ${shortSha(resolved.remote_base)})?`,
|
|
30926
|
+
approvedText: `Stash and create \`${target}\` from \`${base}\` at ${shortSha(resolved.remote_base)}.`
|
|
30927
|
+
} : {
|
|
30830
30928
|
presented: `Workit decision: action — Create branch \`${target}\` from \`${base}\` (currently ${shortSha(resolved.remote_base)})?`,
|
|
30831
30929
|
approvedText: `Create \`${target}\` from \`${base}\` at ${shortSha(resolved.remote_base)}.`
|
|
30832
30930
|
};
|
|
@@ -31545,7 +31643,6 @@ var sessionParent = (session) => {
|
|
|
31545
31643
|
const parentID = session.parentID;
|
|
31546
31644
|
return typeof parentID === "string" && parentID.length > 0 ? parentID : null;
|
|
31547
31645
|
};
|
|
31548
|
-
var freshMs = 5 * 60 * 1000;
|
|
31549
31646
|
var rejectedDescription = "Reject this decision";
|
|
31550
31647
|
var isSelfAuthorizingActionContent = (content) => {
|
|
31551
31648
|
try {
|
|
@@ -31660,8 +31757,6 @@ class NativeReceiptStore {
|
|
|
31660
31757
|
queue.splice(i, 1);
|
|
31661
31758
|
if (!queue.length)
|
|
31662
31759
|
this.#receipts.delete(sessionID);
|
|
31663
|
-
if (this.#now() - receipt.recordedAt > freshMs)
|
|
31664
|
-
return { ok: false, error: "permission_denied: native question receipt is stale" };
|
|
31665
31760
|
const observation = { receipt };
|
|
31666
31761
|
this.#observations.add(observation);
|
|
31667
31762
|
return { ok: true, receipt, observation };
|
|
@@ -31682,8 +31777,6 @@ class NativeReceiptStore {
|
|
|
31682
31777
|
reasons.push(`purpose was "${closest.decisionPurpose}"`);
|
|
31683
31778
|
if (expected.contentDigest !== undefined && closest.contentDigest !== expected.contentDigest)
|
|
31684
31779
|
reasons.push("question or approved content differed from the asked receipt");
|
|
31685
|
-
if (this.#now() - closest.recordedAt > freshMs)
|
|
31686
|
-
reasons.push("receipt is stale (older than 5 minutes)");
|
|
31687
31780
|
if (reasons.length)
|
|
31688
31781
|
return `${base} (closest ${purpose} receipt: ${reasons.join("; ")})`;
|
|
31689
31782
|
}
|
|
@@ -31962,8 +32055,7 @@ var workerIdFor = (store, actor, current, directChildren) => {
|
|
|
31962
32055
|
var createWorkitTools = ({
|
|
31963
32056
|
client,
|
|
31964
32057
|
receipts = new NativeReceiptStore,
|
|
31965
|
-
directChildren = new Map
|
|
31966
|
-
now = Date.now
|
|
32058
|
+
directChildren = new Map
|
|
31967
32059
|
} = {}) => {
|
|
31968
32060
|
const actionProposals = new Map;
|
|
31969
32061
|
const make = (family) => tool({
|
|
@@ -31999,6 +32091,10 @@ var createWorkitTools = ({
|
|
|
31999
32091
|
let result;
|
|
32000
32092
|
if (family === "decision" && args.action === "record") {
|
|
32001
32093
|
const decision = parsed.data;
|
|
32094
|
+
if (decision.response === "stated") {
|
|
32095
|
+
result = core.observeDecision(parsed.data, undefined);
|
|
32096
|
+
return output2(result);
|
|
32097
|
+
}
|
|
32002
32098
|
const budgetIssue = workitBindingQuestionIssue([
|
|
32003
32099
|
decisionContent(decision.purpose, decision.binding.presented, decision.binding.approvedContent)
|
|
32004
32100
|
]);
|
|
@@ -32019,22 +32115,30 @@ var createWorkitTools = ({
|
|
|
32019
32115
|
if (decision.purpose === "action" && decision.response === "approved") {
|
|
32020
32116
|
const queue = actionProposals.get(context.sessionID) ?? [];
|
|
32021
32117
|
const textMatches = queue.filter((pending) => pending.presented === decision.binding.presented && pending.approvedText === decision.binding.approvedContent);
|
|
32022
|
-
|
|
32023
|
-
if (matches.length > 1)
|
|
32118
|
+
if (textMatches.length > 1 && new Set(textMatches.map((pending) => pending.descriptor)).size > 1)
|
|
32024
32119
|
return output2(failure("invalid_input", "multiple action proposals match this approval; resolve the action again"));
|
|
32025
|
-
|
|
32120
|
+
let bound = false;
|
|
32121
|
+
const pending = textMatches[0];
|
|
32026
32122
|
if (pending) {
|
|
32027
|
-
|
|
32028
|
-
|
|
32029
|
-
|
|
32030
|
-
|
|
32031
|
-
|
|
32032
|
-
|
|
32033
|
-
|
|
32034
|
-
|
|
32035
|
-
|
|
32036
|
-
|
|
32037
|
-
|
|
32123
|
+
const fresh = resolveExternalActionRequest(context.directory, pending.request);
|
|
32124
|
+
const freshDescriptor = fresh.ok ? externalActionDescriptor(pending.request.operation, fresh.data.descriptorPayload) : null;
|
|
32125
|
+
if (freshDescriptor === pending.descriptor) {
|
|
32126
|
+
actionProposals.set(context.sessionID, queue.filter((candidate) => candidate !== pending));
|
|
32127
|
+
recordInput = {
|
|
32128
|
+
...recordInput,
|
|
32129
|
+
binding: {
|
|
32130
|
+
...recordInput.binding,
|
|
32131
|
+
approvedContent: pending.descriptor,
|
|
32132
|
+
displayed: pending.approvedText
|
|
32133
|
+
}
|
|
32134
|
+
};
|
|
32135
|
+
bound = true;
|
|
32136
|
+
} else if (fresh.ok) {
|
|
32137
|
+
actionProposals.set(context.sessionID, queue.filter((candidate) => candidate !== pending));
|
|
32138
|
+
}
|
|
32139
|
+
}
|
|
32140
|
+
if (!bound && !isSelfAuthorizingActionContent(decision.binding.approvedContent)) {
|
|
32141
|
+
return output2(failure("invalid_input", textMatches.length > 0 ? "repository state changed since the proposal; resolve the action again for a fresh proposal" : "no matching action proposal; resolve the action through the action tool first"));
|
|
32038
32142
|
}
|
|
32039
32143
|
}
|
|
32040
32144
|
result = core.observeDecision(recordInput, observed.observation);
|
|
@@ -32073,9 +32177,17 @@ var createWorkitTools = ({
|
|
|
32073
32177
|
if (earlySession !== null && sessionParent(earlySession) !== undefined)
|
|
32074
32178
|
return output2(failure("permission_denied", "child sessions cannot run external actions"));
|
|
32075
32179
|
}
|
|
32076
|
-
|
|
32180
|
+
let resolved = resolveExternalActionRequest(context.directory, parsed.data);
|
|
32077
32181
|
if (!resolved.ok)
|
|
32078
32182
|
return output2(resolved);
|
|
32183
|
+
if (resolved.ok && resolved.data.request.operation === "git.branch_setup" && resolved.data.descriptorPayload.resolved?.dirty === true && resolved.data.descriptorPayload.stash !== "yes") {
|
|
32184
|
+
const upgraded = resolveExternalActionRequest(context.directory, {
|
|
32185
|
+
...parsed.data,
|
|
32186
|
+
payload: { ...parsed.data.payload, stash: "yes" }
|
|
32187
|
+
});
|
|
32188
|
+
if (upgraded.ok)
|
|
32189
|
+
resolved = upgraded;
|
|
32190
|
+
}
|
|
32079
32191
|
if (resolved.data.request.operation === "context.read")
|
|
32080
32192
|
return output2(await executeResolvedExternalAction(resolved.data, context.directory));
|
|
32081
32193
|
if (!client)
|
|
@@ -32174,15 +32286,19 @@ var createWorkitTools = ({
|
|
|
32174
32286
|
if (selected.error.startsWith("no approved action")) {
|
|
32175
32287
|
const proposal = actionProposalQuestion(resolved.data.request, resolved.data.descriptorPayload);
|
|
32176
32288
|
const pending = actionProposals.get(context.sessionID) ?? [];
|
|
32177
|
-
pending.
|
|
32289
|
+
const existing = pending.find((candidate) => candidate.descriptor === descriptor);
|
|
32290
|
+
const open = existing ?? {
|
|
32178
32291
|
descriptor,
|
|
32179
32292
|
presented: proposal.presented,
|
|
32180
32293
|
approvedText: proposal.approvedText,
|
|
32181
|
-
|
|
32182
|
-
}
|
|
32183
|
-
if (
|
|
32184
|
-
pending.
|
|
32185
|
-
|
|
32294
|
+
request: resolved.data.request
|
|
32295
|
+
};
|
|
32296
|
+
if (!existing) {
|
|
32297
|
+
pending.push(open);
|
|
32298
|
+
if (pending.length > 8)
|
|
32299
|
+
pending.shift();
|
|
32300
|
+
actionProposals.set(context.sessionID, pending);
|
|
32301
|
+
}
|
|
32186
32302
|
return output2(failure("needs_input", proposal.presented, {
|
|
32187
32303
|
outcome: "not_started",
|
|
32188
32304
|
operation: resolved.data.request.operation,
|
|
@@ -32616,7 +32732,7 @@ var plugin = async ({ client, directory }) => {
|
|
|
32616
32732
|
warnStaleSources();
|
|
32617
32733
|
if (input.tool === "bash") {
|
|
32618
32734
|
const command = output?.args?.command;
|
|
32619
|
-
const route = typeof command === "string" ?
|
|
32735
|
+
const route = typeof command === "string" ? shouldDenyShellRoute(directory, command) : null;
|
|
32620
32736
|
if (route)
|
|
32621
32737
|
throw new Error(`recovery_required: direct branch or PR creation bypasses the Workit route; ${route.guidance}`);
|
|
32622
32738
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-opencode",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit OpenCode plugin — native tools, adaptive policy, and fourteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typecheck": "tsc --noEmit"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@brainervirus/workit-core": "^1.0.
|
|
41
|
+
"@brainervirus/workit-core": "^1.0.11"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@opencode-ai/plugin": "1.18.30"
|