@brainervirus/workit-opencode 8.15.1 → 8.16.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/plugin.js +119 -5
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -16086,6 +16086,54 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
16086
16086
|
requirementIds: evaluations.map((item) => item.requirementId)
|
|
16087
16087
|
});
|
|
16088
16088
|
}
|
|
16089
|
+
var BRIEF_TEXT = 250;
|
|
16090
|
+
var BRIEF_BLOCKERS = 3;
|
|
16091
|
+
var BRIEF_OPEN = 8;
|
|
16092
|
+
var clip = (value) => {
|
|
16093
|
+
const fits = (text) => Buffer.byteLength(JSON.stringify(text)) <= BRIEF_TEXT;
|
|
16094
|
+
if (fits(value))
|
|
16095
|
+
return value;
|
|
16096
|
+
let length = Math.min(value.length, BRIEF_TEXT);
|
|
16097
|
+
while (length > 0 && !fits(`${value.slice(0, length)}…`))
|
|
16098
|
+
length -= 1;
|
|
16099
|
+
return `${value.slice(0, length)}…`;
|
|
16100
|
+
};
|
|
16101
|
+
function boundTaskSummary(summary) {
|
|
16102
|
+
const rules = new Map((summary.policy?.requirements ?? []).map((item) => [item.id, item]));
|
|
16103
|
+
const unmet = summary.requirements.filter((item) => item.status === "unsatisfied" || item.status === "unavailable");
|
|
16104
|
+
const { progress, closure } = summary;
|
|
16105
|
+
const next = progress.nextAction;
|
|
16106
|
+
const open = unmet.slice(0, BRIEF_OPEN).map((item) => ({
|
|
16107
|
+
dimension: rules.get(item.requirementId)?.dimension ?? "verification",
|
|
16108
|
+
before: rules.get(item.requirementId)?.before ?? "close",
|
|
16109
|
+
status: item.status
|
|
16110
|
+
}));
|
|
16111
|
+
const brief = {
|
|
16112
|
+
id: summary.id,
|
|
16113
|
+
revision: summary.revision,
|
|
16114
|
+
workspaceRevision: summary.workspaceRevision,
|
|
16115
|
+
updatedAt: summary.updatedAt,
|
|
16116
|
+
objective: clip(summary.objective),
|
|
16117
|
+
status: summary.status,
|
|
16118
|
+
closure: closure && {
|
|
16119
|
+
outcome: closure.outcome,
|
|
16120
|
+
at: closure.at,
|
|
16121
|
+
summary: clip(closure.summary)
|
|
16122
|
+
},
|
|
16123
|
+
progress: {
|
|
16124
|
+
summary: clip(progress.summary),
|
|
16125
|
+
nextAction: next && clip(next),
|
|
16126
|
+
blockers: progress.blockers.slice(0, BRIEF_BLOCKERS).map((item) => ({
|
|
16127
|
+
reason: clip(item.reason),
|
|
16128
|
+
dependentAction: clip(item.dependentAction)
|
|
16129
|
+
}))
|
|
16130
|
+
},
|
|
16131
|
+
requirements: { total: summary.requirements.length, unmet: unmet.length, open },
|
|
16132
|
+
truncated: false
|
|
16133
|
+
};
|
|
16134
|
+
brief.truncated = JSON.stringify(brief).includes("…") || progress.blockers.length > BRIEF_BLOCKERS || unmet.length > BRIEF_OPEN;
|
|
16135
|
+
return brief;
|
|
16136
|
+
}
|
|
16089
16137
|
|
|
16090
16138
|
// packages/workit-core/src/core/methods.ts
|
|
16091
16139
|
var METHODS = {
|
|
@@ -19514,6 +19562,15 @@ class WorkitCore {
|
|
|
19514
19562
|
if (!parsed.ok)
|
|
19515
19563
|
return parsed;
|
|
19516
19564
|
const input = parsed.data;
|
|
19565
|
+
if (this.context.readOnlyChild) {
|
|
19566
|
+
if (input.action !== "inspect")
|
|
19567
|
+
return failure2("permission_denied", "child sessions can only inspect the task summary");
|
|
19568
|
+
const task = this.store.readTask(input.taskId);
|
|
19569
|
+
if (!task.ok)
|
|
19570
|
+
return task;
|
|
19571
|
+
const summary = this.summary(task.data);
|
|
19572
|
+
return summary.ok ? { ...summary, data: boundTaskSummary(summary.data) } : summary;
|
|
19573
|
+
}
|
|
19517
19574
|
if ((this.context.workerId ?? null) !== null) {
|
|
19518
19575
|
if (input.action !== "inspect" && input.action !== "list")
|
|
19519
19576
|
return failure2("permission_denied", "helpers cannot control task lifecycle or scope");
|
|
@@ -24176,13 +24233,56 @@ var createV2Lifecycle = (deps) => {
|
|
|
24176
24233
|
const unboundLaunch = (coordinator) => {
|
|
24177
24234
|
const store = new TaskStore(root);
|
|
24178
24235
|
const current = currentTaskId(store);
|
|
24179
|
-
const base = current === null ? 'recovery_required: this branch has no Workit task yet; start it (workit_task start, or `workit task start "<objective>"`), then assign a worker on it with workit_worker before launching a native task' : "recovery_required: no assigned Workit worker is attributable to this coordinator on the current branch's task; assign one with workit_worker before launching a native task";
|
|
24236
|
+
const base = current === null ? 'recovery_required: this branch has no Workit task yet; start it (workit_task start, or `workit task start "<objective>"`), then assign a worker on it with workit_worker before launching a native task' : "recovery_required: no assigned Workit worker is attributable to this coordinator on the current branch's task (worker assignments are branch-scoped: they follow the task of the branch checked out when the launch happens); assign one with workit_worker on this branch's task before launching a native task";
|
|
24180
24237
|
const listed = store.listTasks();
|
|
24181
24238
|
if (!listed.ok)
|
|
24182
24239
|
return base;
|
|
24183
24240
|
const stale = listed.data.flatMap((task) => task.status === "active" && task.id !== current ? task.workers.filter((worker) => (worker.data.state === "assigned" || worker.data.state === "running") && worker.provenance.session?.kind === "host" && worker.provenance.session.handle === coordinator).map((worker) => `workit_worker {"action":"cancel","taskId":"${task.id}","workerId":"${worker.id}","reason":"stale worker from another branch"}`) : []);
|
|
24184
24241
|
return stale.length > 0 ? `${base}. Workers of this coordinator are still open on other tasks; cancel any that are stale: ${stale.join("; ")}` : base;
|
|
24185
24242
|
};
|
|
24243
|
+
const rebindStaleWorker = (coordinator, current, stale) => {
|
|
24244
|
+
if (stale.length !== 1)
|
|
24245
|
+
return false;
|
|
24246
|
+
const { task: from, entry } = stale[0];
|
|
24247
|
+
const store = new TaskStore(root);
|
|
24248
|
+
const target = store.readTask(current);
|
|
24249
|
+
if (!target.ok || target.data.status !== "active")
|
|
24250
|
+
return false;
|
|
24251
|
+
const core = new WorkitCore(store, {
|
|
24252
|
+
root,
|
|
24253
|
+
caller: { host: "opencode", actor: coordinator },
|
|
24254
|
+
capabilities: [],
|
|
24255
|
+
constraints: [],
|
|
24256
|
+
now
|
|
24257
|
+
});
|
|
24258
|
+
const assigned = core.worker({
|
|
24259
|
+
schemaVersion: 1,
|
|
24260
|
+
action: "assign",
|
|
24261
|
+
taskId: current,
|
|
24262
|
+
assignment: entry.data.assignment
|
|
24263
|
+
});
|
|
24264
|
+
if (!assigned.ok)
|
|
24265
|
+
return false;
|
|
24266
|
+
const cancelled = core.worker({
|
|
24267
|
+
schemaVersion: 1,
|
|
24268
|
+
action: "cancel",
|
|
24269
|
+
taskId: from.id,
|
|
24270
|
+
workerId: entry.id,
|
|
24271
|
+
reason: `rebound to task ${current} (worker ${assigned.data.id}) after a branch switch`
|
|
24272
|
+
});
|
|
24273
|
+
const latest = store.readTask(current);
|
|
24274
|
+
if (cancelled.ok && latest.ok)
|
|
24275
|
+
core.task({
|
|
24276
|
+
schemaVersion: 1,
|
|
24277
|
+
action: "progress",
|
|
24278
|
+
taskId: current,
|
|
24279
|
+
progress: {
|
|
24280
|
+
...latest.data.progress,
|
|
24281
|
+
summary: `${latest.data.progress.summary} (worker ${assigned.data.id} rebound from task ${from.id} after a branch switch)`
|
|
24282
|
+
}
|
|
24283
|
+
});
|
|
24284
|
+
return cancelled.ok;
|
|
24285
|
+
};
|
|
24186
24286
|
const prepareDispatch = (coordinator, callID) => {
|
|
24187
24287
|
if (dispatches.has(coordinator))
|
|
24188
24288
|
return "unsettled";
|
|
@@ -24196,7 +24296,16 @@ var createV2Lifecycle = (deps) => {
|
|
|
24196
24296
|
return "unmanaged";
|
|
24197
24297
|
const eligible = managed.flatMap((task) => task.workers.filter((entry) => entry.data.state === "assigned" && entry.data.session === null && entry.provenance.session?.kind === "host" && entry.provenance.session.host === "opencode" && entry.provenance.session.handle === coordinator).map((entry) => ({ task, entry })));
|
|
24198
24298
|
const current = currentTaskId(store);
|
|
24199
|
-
|
|
24299
|
+
let next = oldest(eligible.filter((item) => item.task.id === current));
|
|
24300
|
+
if (!next && current !== null) {
|
|
24301
|
+
const stale = eligible.filter((item) => item.task.id !== current);
|
|
24302
|
+
if (rebindStaleWorker(coordinator, current, stale)) {
|
|
24303
|
+
const refreshed = store.readTask(current);
|
|
24304
|
+
const rebound = refreshed.ok ? refreshed.data.workers.filter((entry) => entry.data.state === "assigned" && entry.data.session === null && entry.provenance.session?.kind === "host" && entry.provenance.session.handle === coordinator) : [];
|
|
24305
|
+
if (refreshed.ok && rebound.length > 0)
|
|
24306
|
+
next = oldest(rebound.map((entry) => ({ task: refreshed.data, entry })));
|
|
24307
|
+
}
|
|
24308
|
+
}
|
|
24200
24309
|
if (!next)
|
|
24201
24310
|
return "unbound";
|
|
24202
24311
|
dispatches.set(coordinator, {
|
|
@@ -24659,13 +24768,14 @@ var childMayRecord = (family, input) => {
|
|
|
24659
24768
|
const action = fields(input).action;
|
|
24660
24769
|
return family !== null && typeof action === "string" && CHILD_RECORDS[family]?.has(action) === true;
|
|
24661
24770
|
};
|
|
24771
|
+
var childMayInspect = (family, input) => family === "task" && fields(input).action === "inspect";
|
|
24662
24772
|
var childTaskMissing = (store, input) => {
|
|
24663
24773
|
if (fields(input).taskId !== undefined)
|
|
24664
24774
|
return false;
|
|
24665
24775
|
const report = store.keyReport();
|
|
24666
24776
|
return !report.ok || report.data.bound.length === 0;
|
|
24667
24777
|
};
|
|
24668
|
-
var childDenial = (identity) => `OpenCode child session has no validated Workit worker: as ${identity} it may only record evidence or findings (workit_evidence/workit_finding action "record") on an existing task; for anything else the lead assigns it a worker with workit_worker before launching it`;
|
|
24778
|
+
var childDenial = (identity) => `OpenCode child session has no validated Workit worker: as ${identity} it may only inspect the task summary (workit_task action "inspect") or record evidence or findings (workit_evidence/workit_finding action "record") on an existing task; for anything else the lead assigns it a worker with workit_worker before launching it`;
|
|
24669
24779
|
|
|
24670
24780
|
// packages/workit-opencode/src/v2/shell.ts
|
|
24671
24781
|
import path38 from "node:path";
|
|
@@ -25041,7 +25151,7 @@ var setup = async (ctx) => {
|
|
|
25041
25151
|
}
|
|
25042
25152
|
});
|
|
25043
25153
|
const contextTool = createContextTool();
|
|
25044
|
-
const runFamily = (family, input, session, store, workerId) => {
|
|
25154
|
+
const runFamily = (family, input, session, store, workerId, readOnlyChild = false) => {
|
|
25045
25155
|
const parsed = parseAdvertisedOperation(family, input, "opencode");
|
|
25046
25156
|
if (!parsed.ok)
|
|
25047
25157
|
return parsed;
|
|
@@ -25052,6 +25162,7 @@ var setup = async (ctx) => {
|
|
|
25052
25162
|
constraints: [],
|
|
25053
25163
|
now: () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z"),
|
|
25054
25164
|
workerId,
|
|
25165
|
+
...readOnlyChild ? { readOnlyChild } : {},
|
|
25055
25166
|
nativeWorker: nativeWorkerFor(lifecycle.directChildren, session.id)
|
|
25056
25167
|
});
|
|
25057
25168
|
const run = core[family];
|
|
@@ -25079,8 +25190,11 @@ var setup = async (ctx) => {
|
|
|
25079
25190
|
const identity = childSessionId(session.parentID, session.id);
|
|
25080
25191
|
const lead = await sessionFacts(ctx, session.parentID);
|
|
25081
25192
|
const directChild = lead !== null && lead.parentID === undefined && sameWorkspace(root, lead.directory);
|
|
25082
|
-
|
|
25193
|
+
const inspecting = childMayInspect(family, input);
|
|
25194
|
+
if (!directChild || family === null || !(inspecting || childMayRecord(family, input)))
|
|
25083
25195
|
return resultContent(failure2("permission_denied", childDenial(identity)));
|
|
25196
|
+
if (inspecting)
|
|
25197
|
+
return resultContent(runFamily(family, input, { ...session, id: identity }, store, null, true));
|
|
25084
25198
|
if (childTaskMissing(store, input))
|
|
25085
25199
|
return resultContent(failure2("not_found", "no task for this branch yet: the lead starts one (workit_task start) before a child records on it, or pass taskId"));
|
|
25086
25200
|
return resultContent(runFamily(family, input, { ...session, id: identity }, store, null));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-opencode",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.16.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit OpenCode plugin — native tools, adaptive policy, and sixteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"typecheck": "tsc --noEmit"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@brainervirus/workit-core": "^8.
|
|
42
|
+
"@brainervirus/workit-core": "^8.16.1",
|
|
43
43
|
"@opencode/plugin": "2.0.18"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|