@brainervirus/workit-codex 8.20.0 → 8.21.0
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/launch-mcp.js
CHANGED
|
@@ -28826,8 +28826,11 @@ var WRITE_TOOLS = new Set([
|
|
|
28826
28826
|
"editfile",
|
|
28827
28827
|
"writefile"
|
|
28828
28828
|
]);
|
|
28829
|
+
// packages/workit-core/src/hooks/standing.ts
|
|
28830
|
+
var sinceStart = new Map;
|
|
28829
28831
|
// packages/workit-core/src/hooks/handle.ts
|
|
28830
28832
|
var offered = new Set;
|
|
28833
|
+
var PRE_TOOL = new Set(["shell.pre", "write.pre", "tool.pre"]);
|
|
28831
28834
|
// packages/workit-core/src/hooks/deadline.ts
|
|
28832
28835
|
var QUIET = new Set([
|
|
28833
28836
|
"stop",
|
|
@@ -290,4 +290,64 @@ function maybeHeavy(command, cwd, env = process.env) {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
|
|
293
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
294
|
+
import { createHash } from "node:crypto";
|
|
295
|
+
import fs3 from "node:fs";
|
|
296
|
+
import path3 from "node:path";
|
|
297
|
+
var gitStoreDir = (cwd) => {
|
|
298
|
+
try {
|
|
299
|
+
for (let dir = path3.resolve(cwd);; dir = path3.dirname(dir)) {
|
|
300
|
+
const dotGit = path3.join(dir, ".git");
|
|
301
|
+
if (fs3.existsSync(dotGit)) {
|
|
302
|
+
let gitDir = dotGit;
|
|
303
|
+
if (fs3.statSync(dotGit).isFile()) {
|
|
304
|
+
const target = /^gitdir:\s*(.+)$/mu.exec(fs3.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
305
|
+
if (!target)
|
|
306
|
+
return null;
|
|
307
|
+
gitDir = path3.resolve(dir, target);
|
|
308
|
+
const common = path3.join(gitDir, "commondir");
|
|
309
|
+
if (fs3.existsSync(common))
|
|
310
|
+
gitDir = path3.resolve(gitDir, fs3.readFileSync(common, "utf8").trim());
|
|
311
|
+
}
|
|
312
|
+
return path3.join(gitDir, "workit");
|
|
313
|
+
}
|
|
314
|
+
if (path3.dirname(dir) === dir)
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
} catch {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
var standingRevFile = (store) => path3.join(store, "standing", "rev");
|
|
322
|
+
var standingSeenFile = (store, session, agentId) => path3.join(store, "standing", "seen", `${createHash("sha256").update(`${session}\x00${agentId ?? ""}`).digest("hex").slice(0, 32)}.json`);
|
|
323
|
+
var readStandingRev = (store) => {
|
|
324
|
+
try {
|
|
325
|
+
return fs3.readFileSync(standingRevFile(store), "utf8").trim() || null;
|
|
326
|
+
} catch {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
var readStandingSeen = (file) => {
|
|
331
|
+
try {
|
|
332
|
+
const value = JSON.parse(fs3.readFileSync(file, "utf8"));
|
|
333
|
+
return {
|
|
334
|
+
rev: typeof value.rev === "string" ? value.rev : null,
|
|
335
|
+
ids: Array.isArray(value.ids) ? value.ids.filter((id) => typeof id === "string") : []
|
|
336
|
+
};
|
|
337
|
+
} catch {
|
|
338
|
+
return { rev: null, ids: [] };
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
var writeStandingSeen = (file, seen) => {
|
|
342
|
+
try {
|
|
343
|
+
fs3.mkdirSync(path3.dirname(file), { recursive: true });
|
|
344
|
+
fs3.writeFileSync(file, JSON.stringify(seen));
|
|
345
|
+
} catch {}
|
|
346
|
+
};
|
|
347
|
+
var standingPending = (cwd, session, agentId) => {
|
|
348
|
+
const store = gitStoreDir(cwd);
|
|
349
|
+
const rev = store ? readStandingRev(store) : null;
|
|
350
|
+
return rev !== null && readStandingSeen(standingSeenFile(store, session, agentId)).rev !== rev;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
export { CHECKS_FILE, repoHeavyCommands, loadCheckConfig, matchesNamedCheck, gateCheckNames, checkCommand, stateDir, maybeHeavy, gitStoreDir, standingSeenFile, readStandingRev, readStandingSeen, writeStandingSeen, standingPending };
|
|
@@ -6,8 +6,13 @@ import {
|
|
|
6
6
|
matchesNamedCheck,
|
|
7
7
|
gateCheckNames,
|
|
8
8
|
checkCommand,
|
|
9
|
-
maybeHeavy
|
|
10
|
-
|
|
9
|
+
maybeHeavy,
|
|
10
|
+
gitStoreDir,
|
|
11
|
+
standingSeenFile,
|
|
12
|
+
readStandingRev,
|
|
13
|
+
readStandingSeen,
|
|
14
|
+
writeStandingSeen
|
|
15
|
+
} from "./workit-hook-thet0x8m.js";
|
|
11
16
|
// packages/workit-core/src/hooks/descriptor.ts
|
|
12
17
|
var support = (descriptor, axis) => {
|
|
13
18
|
if (axis.startsWith("event:"))
|
|
@@ -14536,6 +14541,28 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
14536
14541
|
warnings
|
|
14537
14542
|
};
|
|
14538
14543
|
}
|
|
14544
|
+
var fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session);
|
|
14545
|
+
function activeStanding(rows, fanout, leads = null) {
|
|
14546
|
+
const active = [];
|
|
14547
|
+
for (const row of rows) {
|
|
14548
|
+
if (row.fanout !== fanout || !fromLead(row, leads))
|
|
14549
|
+
continue;
|
|
14550
|
+
if (row.type === "standing" && typeof row.what === "string" && row.what.trim()) {
|
|
14551
|
+
if (!row.superseded)
|
|
14552
|
+
active.push(row);
|
|
14553
|
+
} else if (row.type === "standing.cleared") {
|
|
14554
|
+
const target = str(row.target);
|
|
14555
|
+
if (target === null)
|
|
14556
|
+
active.length = 0;
|
|
14557
|
+
else {
|
|
14558
|
+
const index = active.findIndex((order) => order.id === target);
|
|
14559
|
+
if (index >= 0)
|
|
14560
|
+
active.splice(index, 1);
|
|
14561
|
+
}
|
|
14562
|
+
}
|
|
14563
|
+
}
|
|
14564
|
+
return active;
|
|
14565
|
+
}
|
|
14539
14566
|
var OBSERVED_ONLY = new Set([
|
|
14540
14567
|
"check",
|
|
14541
14568
|
"merge.unverified",
|
|
@@ -22132,6 +22159,109 @@ var writeTargets = (input) => {
|
|
|
22132
22159
|
const paths = writePaths(input);
|
|
22133
22160
|
return paths.length > 0 ? paths : null;
|
|
22134
22161
|
};
|
|
22162
|
+
// packages/workit-core/src/hooks/standing.ts
|
|
22163
|
+
import fs19 from "node:fs";
|
|
22164
|
+
import path26 from "node:path";
|
|
22165
|
+
var readPlans = (store) => {
|
|
22166
|
+
const dir = path26.join(store, "fanouts");
|
|
22167
|
+
let names;
|
|
22168
|
+
try {
|
|
22169
|
+
names = fs19.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
22170
|
+
} catch {
|
|
22171
|
+
return [];
|
|
22172
|
+
}
|
|
22173
|
+
const plans = [];
|
|
22174
|
+
for (const name of names) {
|
|
22175
|
+
try {
|
|
22176
|
+
const raw = JSON.parse(fs19.readFileSync(path26.join(dir, name), "utf8"));
|
|
22177
|
+
if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
|
|
22178
|
+
continue;
|
|
22179
|
+
const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
|
|
22180
|
+
plans.push({
|
|
22181
|
+
name: raw.name,
|
|
22182
|
+
leads: texts([raw.leadSession, ...texts(raw.formerLeads)]),
|
|
22183
|
+
branches: texts(raw.slices.map((slice) => slice && typeof slice === "object" ? slice.branch : null))
|
|
22184
|
+
});
|
|
22185
|
+
} catch {}
|
|
22186
|
+
}
|
|
22187
|
+
return plans;
|
|
22188
|
+
};
|
|
22189
|
+
var leadOf2 = (input) => input.session.parentId ?? (input.session.agentId ? input.session.id : null) ?? (input.session.id.includes(":") ? input.session.id.split(":")[0] : null);
|
|
22190
|
+
var worksFor = (plan, input, branch) => {
|
|
22191
|
+
const session = input.session.id;
|
|
22192
|
+
if (plan.leads.includes(session) && !input.session.agentId)
|
|
22193
|
+
return false;
|
|
22194
|
+
const lead = leadOf2(input);
|
|
22195
|
+
if (lead && plan.leads.includes(lead))
|
|
22196
|
+
return true;
|
|
22197
|
+
if (plan.leads.some((each) => session.startsWith(`${each}-w-`)))
|
|
22198
|
+
return true;
|
|
22199
|
+
const current = branch();
|
|
22200
|
+
return current !== null && plan.branches.includes(current);
|
|
22201
|
+
};
|
|
22202
|
+
var standingFor = (input, store, rev) => {
|
|
22203
|
+
const orders = new Map;
|
|
22204
|
+
const ledger = readLedger(input.cwd);
|
|
22205
|
+
const rows = ledger.ok ? ledger.value.rows : [];
|
|
22206
|
+
let branch;
|
|
22207
|
+
const lazyBranch = () => branch === undefined ? branch = currentBranch(input.cwd) : branch;
|
|
22208
|
+
for (const plan of readPlans(store))
|
|
22209
|
+
if (worksFor(plan, input, lazyBranch))
|
|
22210
|
+
for (const row of activeStanding(rows, plan.name, plan.leads.length ? plan.leads : null))
|
|
22211
|
+
orders.set(row.id, row);
|
|
22212
|
+
return { rev, orders, rows };
|
|
22213
|
+
};
|
|
22214
|
+
var located = (input) => {
|
|
22215
|
+
const store = input.session.id ? gitStoreDir(input.cwd) : null;
|
|
22216
|
+
const rev = store ? readStandingRev(store) : null;
|
|
22217
|
+
if (!store || rev === null)
|
|
22218
|
+
return null;
|
|
22219
|
+
return { store, rev, file: standingSeenFile(store, input.session.id, input.session.agentId) };
|
|
22220
|
+
};
|
|
22221
|
+
var seedStanding = (input) => {
|
|
22222
|
+
try {
|
|
22223
|
+
const where = located(input);
|
|
22224
|
+
if (!where)
|
|
22225
|
+
return;
|
|
22226
|
+
const now = standingFor(input, where.store, where.rev);
|
|
22227
|
+
writeStandingSeen(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
22228
|
+
} catch {}
|
|
22229
|
+
};
|
|
22230
|
+
var fanoutOf = (row) => typeof row.fanout === "string" ? row.fanout : "?";
|
|
22231
|
+
var changedSince = (now, ids) => {
|
|
22232
|
+
const known = new Set(ids);
|
|
22233
|
+
const added = [...now.orders.values()].filter((row) => !known.has(row.id));
|
|
22234
|
+
const byId = new Map(now.rows.map((row) => [row.id, row]));
|
|
22235
|
+
const dropped = ids.filter((id) => !now.orders.has(id)).map((id) => byId.get(id)).filter((row) => row !== undefined);
|
|
22236
|
+
if (!added.length && !dropped.length)
|
|
22237
|
+
return null;
|
|
22238
|
+
const fanouts = [...new Set([...added, ...dropped].map(fanoutOf))].join(", ");
|
|
22239
|
+
const lines = [
|
|
22240
|
+
`Workit: the lead changed the standing orders for fanout ${fanouts} while you run. They apply to you now and override your brief's STANDING list.`,
|
|
22241
|
+
...added.map((row) => ` - new: ${String(row.what)}`),
|
|
22242
|
+
...dropped.map((row) => ` - no longer in force: ${String(row.what)}${row.stop ? " (the stop is lifted: continue your brief)" : ""}`)
|
|
22243
|
+
];
|
|
22244
|
+
if (added.some((row) => row.stop === true))
|
|
22245
|
+
lines.push("Stop now: make no further changes, close what you opened, and report to the lead with your branch, head SHA, what is done and what is not.");
|
|
22246
|
+
return lines.join(`
|
|
22247
|
+
`);
|
|
22248
|
+
};
|
|
22249
|
+
var standingDelta = (input) => {
|
|
22250
|
+
try {
|
|
22251
|
+
const where = located(input);
|
|
22252
|
+
if (!where)
|
|
22253
|
+
return null;
|
|
22254
|
+
const seen = readStandingSeen(where.file);
|
|
22255
|
+
if (seen.rev === where.rev)
|
|
22256
|
+
return null;
|
|
22257
|
+
const now = standingFor(input, where.store, where.rev);
|
|
22258
|
+
writeStandingSeen(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
22259
|
+
return changedSince(now, seen.ids);
|
|
22260
|
+
} catch {
|
|
22261
|
+
return null;
|
|
22262
|
+
}
|
|
22263
|
+
};
|
|
22264
|
+
var sinceStart = new Map;
|
|
22135
22265
|
// packages/workit-core/src/hooks/handle.ts
|
|
22136
22266
|
var usable2 = (value) => value === "native" || value === "partial";
|
|
22137
22267
|
var NONE5 = { kind: "none" };
|
|
@@ -22176,7 +22306,18 @@ ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
|
|
|
22176
22306
|
const pick = judge === "verifier" ? ", --kind live when you drove the real surface" : "";
|
|
22177
22307
|
return `${readOnly} Its own Workit session is ${own}, so the ledger tells its verdicts apart from the author's. Record the verdict with exactly this command (pick the result${pick}, name the candidate branch if it differs, say what you ran): \`${line}\`.${token ? " The token is this subagent's alone: never write it into a report, a file or a commit. --token needs a workit CLI at least as new as this plugin; if the CLI answers that --token is an unknown option, update the workit CLI (workit upgrade --cli) and record again." : ""}`;
|
|
22178
22308
|
};
|
|
22309
|
+
var PRE_TOOL = new Set(["shell.pre", "write.pre", "tool.pre"]);
|
|
22179
22310
|
function handleHook(input, deps) {
|
|
22311
|
+
const decision = decide(input, deps);
|
|
22312
|
+
if (deps.descriptor.transport !== "hook-process" || !PRE_TOOL.has(input.event.kind) || decision.kind === "deny")
|
|
22313
|
+
return decision;
|
|
22314
|
+
const delta = standingDelta(input);
|
|
22315
|
+
if (!delta)
|
|
22316
|
+
return decision;
|
|
22317
|
+
return decision.kind === "rewrite" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
|
|
22318
|
+
`) } : withContextLine(decision, delta);
|
|
22319
|
+
}
|
|
22320
|
+
function decide(input, deps) {
|
|
22180
22321
|
const { descriptor } = deps;
|
|
22181
22322
|
const event = input.event;
|
|
22182
22323
|
switch (event.kind) {
|
|
@@ -22253,6 +22394,7 @@ function handleHook(input, deps) {
|
|
|
22253
22394
|
case "write.pre":
|
|
22254
22395
|
return usable2(descriptor.events["write.pre"].support) ? writeGate(input.cwd, event.paths, liveOwner(input, descriptor.transport)) : NONE5;
|
|
22255
22396
|
case "subagent.start":
|
|
22397
|
+
seedStanding({ ...input, session: { ...input.session, agentId: event.agentId } });
|
|
22256
22398
|
return {
|
|
22257
22399
|
kind: "context",
|
|
22258
22400
|
text: subagentStartText(input, descriptor, event)
|
|
@@ -22304,7 +22446,7 @@ var dispatchHook = (adapter, raw, env = process.env) => {
|
|
|
22304
22446
|
};
|
|
22305
22447
|
// packages/workit-core/src/hooks/deadline.ts
|
|
22306
22448
|
import { appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
22307
|
-
import
|
|
22449
|
+
import path27 from "node:path";
|
|
22308
22450
|
var HOOK_SKIP_TEXT = "workit context skipped: host under load";
|
|
22309
22451
|
var HOOK_DEADLINE_MS = 8000;
|
|
22310
22452
|
var HOST_DEADLINES = {
|
|
@@ -22322,7 +22464,7 @@ var hookDeadlineMs = (env, host = "", native) => {
|
|
|
22322
22464
|
const row = HOST_DEADLINES[host];
|
|
22323
22465
|
return override(env) ?? (row ? native === undefined ? Math.min(...Object.values(row)) : row[native] ?? row[""] : HOOK_DEADLINE_MS);
|
|
22324
22466
|
};
|
|
22325
|
-
var skipsFile = (stateDir) =>
|
|
22467
|
+
var skipsFile = (stateDir) => path27.join(stateDir, HOOK_SKIPS_FILE);
|
|
22326
22468
|
var recordHookSkip = (skip, stateDir = resolveStateDir()) => {
|
|
22327
22469
|
try {
|
|
22328
22470
|
mkdirSync3(stateDir, { recursive: true });
|
|
@@ -22966,8 +23108,8 @@ var codexAdapter = {
|
|
|
22966
23108
|
};
|
|
22967
23109
|
|
|
22968
23110
|
// packages/workit-core/src/hooks/hosts/cursor.ts
|
|
22969
|
-
import
|
|
22970
|
-
import
|
|
23111
|
+
import fs20 from "node:fs";
|
|
23112
|
+
import path28 from "node:path";
|
|
22971
23113
|
var undocumented = { support: "undocumented", native: null };
|
|
22972
23114
|
var none = { support: "none", native: null };
|
|
22973
23115
|
var CURSOR_DESCRIPTOR = {
|
|
@@ -23164,17 +23306,17 @@ var protocolEvent2 = (input) => {
|
|
|
23164
23306
|
};
|
|
23165
23307
|
var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
|
|
23166
23308
|
var lastAssistantText = (file) => {
|
|
23167
|
-
if (!file || !
|
|
23309
|
+
if (!file || !path28.isAbsolute(file))
|
|
23168
23310
|
return null;
|
|
23169
23311
|
try {
|
|
23170
|
-
const size =
|
|
23312
|
+
const size = fs20.statSync(file).size;
|
|
23171
23313
|
const start = Math.max(0, size - TRANSCRIPT_TAIL_BYTES);
|
|
23172
23314
|
const buffer = Buffer.alloc(size - start);
|
|
23173
|
-
const fd =
|
|
23315
|
+
const fd = fs20.openSync(file, "r");
|
|
23174
23316
|
try {
|
|
23175
|
-
|
|
23317
|
+
fs20.readSync(fd, buffer, 0, buffer.length, start);
|
|
23176
23318
|
} finally {
|
|
23177
|
-
|
|
23319
|
+
fs20.closeSync(fd);
|
|
23178
23320
|
}
|
|
23179
23321
|
const lines = buffer.toString("utf8").split(`
|
|
23180
23322
|
`);
|
|
@@ -23201,7 +23343,7 @@ var lastAssistantText = (file) => {
|
|
|
23201
23343
|
return null;
|
|
23202
23344
|
}
|
|
23203
23345
|
};
|
|
23204
|
-
var within2 = (root, dir) => dir === root || dir.startsWith(root.endsWith(
|
|
23346
|
+
var within2 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path28.sep) ? root : `${root}${path28.sep}`);
|
|
23205
23347
|
var hookCwd = (input) => {
|
|
23206
23348
|
const cwd = existingDirectory(input.cwd);
|
|
23207
23349
|
if (cwd && input.hook_event_name === "beforeShellExecution")
|
package/dist/workit-hook.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
stateDir,
|
|
4
|
-
maybeHeavy
|
|
5
|
-
|
|
4
|
+
maybeHeavy,
|
|
5
|
+
standingPending
|
|
6
|
+
} from "./workit-hook-thet0x8m.js";
|
|
6
7
|
|
|
7
8
|
// packages/workit-codex/hooks/launcher.ts
|
|
8
9
|
var payload = "";
|
|
@@ -22,6 +23,8 @@ var quietEvent = () => {
|
|
|
22
23
|
return null;
|
|
23
24
|
if (typeof value.cwd !== "string" || typeof value.tool_name !== "string")
|
|
24
25
|
return null;
|
|
26
|
+
if (event === "PreToolUse" && typeof value.session_id === "string" && standingPending(value.cwd, value.session_id, typeof value.agent_id === "string" && value.agent_id.trim() ? value.agent_id : null))
|
|
27
|
+
return null;
|
|
25
28
|
const tool = value.tool_name.toLowerCase();
|
|
26
29
|
if (event === "PreToolUse" && WRITE_TOOLS.has(tool.replace(/[_-]/g, "")))
|
|
27
30
|
return null;
|
|
@@ -44,6 +47,6 @@ if (quiet)
|
|
|
44
47
|
process.stdout.write(`${JSON.stringify({ hookSpecificOutput: { hookEventName: quiet } })}
|
|
45
48
|
`);
|
|
46
49
|
else {
|
|
47
|
-
const { runCodexHook } = await import("./workit-hook-
|
|
50
|
+
const { runCodexHook } = await import("./workit-hook-xhk0gksg.js");
|
|
48
51
|
await runCodexHook([payload]);
|
|
49
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-codex",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.21.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Codex CLI/desktop plugin — shared MCP transport, hooks, method skills, and verifier/reviewer/implementer agents",
|
|
6
6
|
"keywords": [
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"build": "bun scripts/build.ts"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@brainervirus/workit-core": "^8.
|
|
43
|
-
"@brainervirus/workit-mcp": "^8.
|
|
42
|
+
"@brainervirus/workit-core": "^8.21.0",
|
|
43
|
+
"@brainervirus/workit-mcp": "^8.21.0"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": ">=24"
|