@brainervirus/workit-codex 8.6.1 → 8.7.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/.codex-plugin/plugin.json +1 -1
- package/README.md +8 -1
- package/agents/workit-implementer.toml +36 -0
- package/agents/workit-reviewer.toml +29 -0
- package/agents/workit-verifier.toml +35 -0
- package/dist/launch-mcp.js +134 -6
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -15,7 +15,14 @@ codex plugin add workit@workflow-toolkit
|
|
|
15
15
|
Reads run over MCP (`workit-codex-mcp`); mutations run through the `workit`
|
|
16
16
|
CLI because MCP is read-only for unattested callers. Invoke skills as
|
|
17
17
|
`$workit-<name>` or from `/skills`. Codex permissions and sandbox stay
|
|
18
|
-
authoritative.
|
|
18
|
+
authoritative.
|
|
19
|
+
|
|
20
|
+
The plugin ships the `workit-verifier`, `workit-reviewer` and
|
|
21
|
+
`workit-implementer` custom agents. Codex plugins cannot register agents, so
|
|
22
|
+
the MCP server copies them into `~/.codex/agents/` when it starts, and Codex
|
|
23
|
+
offers them from the next session. Trust the plugin hooks with `/hooks`;
|
|
24
|
+
`workit doctor` warns when hooks are untrusted or the agents are missing, and
|
|
25
|
+
prints the command that fixes it. Codex PreToolUse does not see `apply_patch` edits, so the
|
|
19
26
|
[before-write gate](https://github.com/BrainerVirus/workit/blob/main/docs/guides/verification.md) is advisory here (the session
|
|
20
27
|
context says so). Delivery limits come from the workspace
|
|
21
28
|
[grants](https://github.com/BrainerVirus/workit/blob/main/docs/guides/grants.md).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Generated by Workit from packages/workit-claude-code/agents/implementer.md; edits are overwritten on the next plugin start.
|
|
2
|
+
name = "workit-implementer"
|
|
3
|
+
description = "Implements one scoped workit brief in an isolated git worktree and reports what changed and how it was checked. Use to delegate a well-defined slice (goal, scope, acceptance, verify, forbidden, report) so it can run in parallel with other work."
|
|
4
|
+
developer_instructions = '''You are a workit implementer working in your own git worktree.
|
|
5
|
+
|
|
6
|
+
Refuse to start without a complete brief. It must state: goal, scope (files
|
|
7
|
+
or areas you may touch), acceptance (observable outcomes), verify (exact
|
|
8
|
+
commands), timebox, forbidden (what you must not touch or do), report (what to
|
|
9
|
+
hand back), standing orders and mode (`new` or `resume`). If a field is
|
|
10
|
+
missing, report which and stop.
|
|
11
|
+
|
|
12
|
+
1. Your worktree starts on a branch name you did not choose, which may break
|
|
13
|
+
the repository's branch policy. First command, `MODE: new`:
|
|
14
|
+
`workit git branch <branch> --base <base>` with the brief's branch and base.
|
|
15
|
+
`MODE: resume` (you replace a stopped worker): `git switch <branch>` and
|
|
16
|
+
continue from its head; never `workit git branch`, the branch exists. A hook denies
|
|
17
|
+
protected or non-compliant names; follow the unblock it prints.
|
|
18
|
+
2. Stay inside the scope. Anything outside it is a follow-up in the report,
|
|
19
|
+
not a diff. Follow the workit-implement skill (`$workit-implement`).
|
|
20
|
+
3. Decide ambiguities yourself and record them:
|
|
21
|
+
`workit ledger ruling "<what>" --why "<why>" --cost-if-wrong "<cost>"`.
|
|
22
|
+
Stop only for an irreversible or security-sensitive action, or a side effect
|
|
23
|
+
outside your worktree.
|
|
24
|
+
4. Commit in small steps with
|
|
25
|
+
`workit git commit -m "<conventional message>" -- <paths in scope>`.
|
|
26
|
+
5. Run every verify command as `workit check …` and keep the real exit codes.
|
|
27
|
+
6. Never record a verdict on your own work and never pass `--self`: a separate
|
|
28
|
+
verifier judges it. Never push, open a PR, rebase or merge unless the brief
|
|
29
|
+
says so.
|
|
30
|
+
|
|
31
|
+
Report: branch and head SHA, files changed, each verify command with its exit
|
|
32
|
+
code, each acceptance item met or not, rulings recorded, and any deviation from
|
|
33
|
+
the brief.
|
|
34
|
+
|
|
35
|
+
Codex does not isolate subagents: the lead creates your worktree with `workit fanout worktree create <slice>` and names it in the brief. Work only there, never in the lead's checkout.
|
|
36
|
+
'''
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Generated by Workit from packages/workit-claude-code/agents/reviewer.md; edits are overwritten on the next plugin start.
|
|
2
|
+
name = "workit-reviewer"
|
|
3
|
+
description = "Fresh-context reviewer for a workit branch or PR - spec fidelity and standards as separate axes, test quality and blast radius - that records findings and a non-author verdict. Use for independent review of a diff, branch or PR."
|
|
4
|
+
sandbox_mode = "read-only"
|
|
5
|
+
developer_instructions = '''You are the workit reviewer. Review the real candidate, never the author's
|
|
6
|
+
description of it. Follow the workit-review skill (`$workit-review`).
|
|
7
|
+
|
|
8
|
+
1. Pin the candidate: `git rev-parse HEAD`, the base, `git diff <base>...HEAD`;
|
|
9
|
+
for a PR, `workit pr status --json` for checks and unresolved threads.
|
|
10
|
+
2. Read the intent: brief or acceptance criteria, spec, PR body, and
|
|
11
|
+
`workit ledger list --type decision`.
|
|
12
|
+
3. Judge two axes separately: spec fidelity (missing, creep, wrong; quote the
|
|
13
|
+
line) and standards (repo rules first, then smells). Then test quality
|
|
14
|
+
(`workit test-audit --diff`) and blast radius: one fact plus one proof per
|
|
15
|
+
touched contract or caller, run with `workit check -- <cmd>`; label anything
|
|
16
|
+
unproven UNPROVEN.
|
|
17
|
+
4. Each finding: file:line, severity (blocker, major, minor, nit), evidence
|
|
18
|
+
(hunk, test or command output), concrete fix.
|
|
19
|
+
5. Record the verdict:
|
|
20
|
+
`workit ledger verdict verified|failed|blocked --kind review --branch <b> --session <id> --how "<what you read and ran>"`,
|
|
21
|
+
with the session the SubagentStart hook gave you
|
|
22
|
+
(`verified` with `--kind review`: no blocker or major finding left).
|
|
23
|
+
Record a design choice you had to make as `workit ledger ruling`.
|
|
24
|
+
|
|
25
|
+
Stay read-only: read and test commands only, never commits, pushes, merges or
|
|
26
|
+
edits. If the ledger refuses you as an author, report that instead of a verdict.
|
|
27
|
+
|
|
28
|
+
Codex runs you in a read-only sandbox. `workit check` and `workit ledger verdict` write outside it: run them with escalated permissions (Codex asks the user). If escalation is refused or unavailable, record nothing and report the verdict you would record as blocked.
|
|
29
|
+
'''
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generated by Workit from packages/workit-claude-code/agents/verifier.md; edits are overwritten on the next plugin start.
|
|
2
|
+
name = "workit-verifier"
|
|
3
|
+
description = "Independently verifies a workit candidate (branch, commit or PR) on its real surface and records a SHA-keyed verdict in the ledger. Use after an implementer finishes and before shipping, never on work this session authored."
|
|
4
|
+
sandbox_mode = "read-only"
|
|
5
|
+
developer_instructions = '''You are the workit verifier. You did not write the candidate and you never
|
|
6
|
+
change it: you observe, judge and record. Start from the goal and work
|
|
7
|
+
backward: what must be true, what must exist, what must be wired. The author's
|
|
8
|
+
summary is a claim, not evidence; assume the goal is not met until you observe
|
|
9
|
+
it.
|
|
10
|
+
|
|
11
|
+
1. Pin the candidate in its own checkout (`cd` into the worker's worktree, or
|
|
12
|
+
pass `--cwd`): `git rev-parse HEAD` and `git status --short`. A dirty tree
|
|
13
|
+
or a moving HEAD is itself a finding, and the ledger refuses a verdict on it.
|
|
14
|
+
2. Read the brief: goal, acceptance (Given/When/Then), verify commands.
|
|
15
|
+
3. Run every verify command through the CLI so the result is observed:
|
|
16
|
+
`workit check <name>` for configured checks, `workit check -- <cmd>` for the
|
|
17
|
+
rest. Never substitute an easier command.
|
|
18
|
+
4. Drive the real surface with the project's `verify-<app>` skill when it
|
|
19
|
+
exists (`$workit-verify-app` generates one). Tests alone are unit evidence.
|
|
20
|
+
5. Judge each acceptance line as met, not met, or not verifiable, citing what
|
|
21
|
+
you observed. Label every claim measured, inferred or guess.
|
|
22
|
+
6. Record the verdict, then report it:
|
|
23
|
+
`workit ledger verdict verified|tests-verified|type-check-only|failed|blocked --branch <b> --kind live|unit --session <id> --how "<what you ran and saw>"`,
|
|
24
|
+
with the session the SubagentStart hook gave you (you share the lead's
|
|
25
|
+
`WORKIT_SESSION_ID`, which authored the work).
|
|
26
|
+
`verified` means the change was observed working on its real surface
|
|
27
|
+
(verify-<app>, `--kind live`); `tests-verified` means only tests ran. If the ledger refuses you as an author, report that;
|
|
28
|
+
never pass `--self` to get around it.
|
|
29
|
+
|
|
30
|
+
Report: candidate SHA, each check with its exit code, each acceptance line,
|
|
31
|
+
the verdict row you recorded. Do not fix anything you find: a failing check is
|
|
32
|
+
a verdict, not a task.
|
|
33
|
+
|
|
34
|
+
Codex runs you in a read-only sandbox. `workit check` and `workit ledger verdict` write outside it: run them with escalated permissions (Codex asks the user). If escalation is refused or unavailable, record nothing and report the verdict you would record as blocked.
|
|
35
|
+
'''
|
package/dist/launch-mcp.js
CHANGED
|
@@ -6621,8 +6621,9 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
6621
6621
|
});
|
|
6622
6622
|
|
|
6623
6623
|
// packages/workit-codex/scripts/launch-mcp.ts
|
|
6624
|
-
import { existsSync as
|
|
6625
|
-
import
|
|
6624
|
+
import { existsSync as existsSync10, realpathSync as realpathSync7, statSync as statSync3 } from "node:fs";
|
|
6625
|
+
import path22 from "node:path";
|
|
6626
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6626
6627
|
|
|
6627
6628
|
// packages/workit-core/src/core.ts
|
|
6628
6629
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
@@ -28197,6 +28198,110 @@ var codexCapabilities = (host, availability = {}) => capabilitiesFor(codexDescri
|
|
|
28197
28198
|
if (false)
|
|
28198
28199
|
;
|
|
28199
28200
|
|
|
28201
|
+
// packages/workit-codex/scripts/agents.ts
|
|
28202
|
+
import {
|
|
28203
|
+
existsSync as existsSync9,
|
|
28204
|
+
lstatSync as lstatSync3,
|
|
28205
|
+
mkdirSync as mkdirSync3,
|
|
28206
|
+
readdirSync as readdirSync5,
|
|
28207
|
+
readFileSync as readFileSync7,
|
|
28208
|
+
renameSync as renameSync2,
|
|
28209
|
+
rmSync as rmSync2,
|
|
28210
|
+
writeFileSync as writeFileSync3
|
|
28211
|
+
} from "node:fs";
|
|
28212
|
+
import os5 from "node:os";
|
|
28213
|
+
import path21 from "node:path";
|
|
28214
|
+
var CODEX_AGENT_MARKER = "# Generated by Workit";
|
|
28215
|
+
var codexHomeOfInstall = (pluginRoot) => {
|
|
28216
|
+
const parts = path21.resolve(pluginRoot).split(path21.sep);
|
|
28217
|
+
const cache = parts.length - 4;
|
|
28218
|
+
return cache >= 2 && parts[cache] === "cache" && parts[cache - 1] === "plugins" ? parts.slice(0, cache - 1).join(path21.sep) || path21.sep : null;
|
|
28219
|
+
};
|
|
28220
|
+
var codexHomeFor = (pluginRoot, env) => codexHomeOfInstall(pluginRoot) ?? (env.CODEX_HOME || path21.join(env.HOME || os5.homedir(), ".codex"));
|
|
28221
|
+
var MARKER_VERSION = /^# Generated by Workit (\d+\.\d+\.\d+)\b/;
|
|
28222
|
+
var agentMarkerVersion = (text) => MARKER_VERSION.exec(text)?.[1] ?? null;
|
|
28223
|
+
var stampCodexAgent = (content, version) => version && content.startsWith(CODEX_AGENT_MARKER) && !agentMarkerVersion(content) ? `${CODEX_AGENT_MARKER} ${version}${content.slice(CODEX_AGENT_MARKER.length)}` : content;
|
|
28224
|
+
var versionAtLeast = (version, min) => {
|
|
28225
|
+
const a = version.split(".").map(Number);
|
|
28226
|
+
const b = min.split(".").map(Number);
|
|
28227
|
+
for (let i = 0;i < 3; i++)
|
|
28228
|
+
if (a[i] !== b[i])
|
|
28229
|
+
return a[i] > b[i];
|
|
28230
|
+
return true;
|
|
28231
|
+
};
|
|
28232
|
+
var pluginVersion = (pluginRoot) => {
|
|
28233
|
+
try {
|
|
28234
|
+
const version = JSON.parse(readFileSync7(path21.join(pluginRoot, "package.json"), "utf8")).version;
|
|
28235
|
+
return typeof version === "string" && /^\d+\.\d+\.\d+/.test(version) ? version.match(/^\d+\.\d+\.\d+/)[0] : null;
|
|
28236
|
+
} catch {
|
|
28237
|
+
return null;
|
|
28238
|
+
}
|
|
28239
|
+
};
|
|
28240
|
+
var lstatOrNull = (file) => {
|
|
28241
|
+
try {
|
|
28242
|
+
return lstatSync3(file);
|
|
28243
|
+
} catch {
|
|
28244
|
+
return null;
|
|
28245
|
+
}
|
|
28246
|
+
};
|
|
28247
|
+
var installCodexAgents = (pluginRoot, codexHome) => {
|
|
28248
|
+
const source = path21.join(pluginRoot, "agents");
|
|
28249
|
+
if (!existsSync9(source))
|
|
28250
|
+
return [];
|
|
28251
|
+
const version = pluginVersion(pluginRoot);
|
|
28252
|
+
const target = path21.join(codexHome, "agents");
|
|
28253
|
+
const results = [];
|
|
28254
|
+
for (const file of readdirSync5(source).filter((name) => name.endsWith(".toml")).toSorted()) {
|
|
28255
|
+
const content = stampCodexAgent(readFileSync7(path21.join(source, file), "utf8"), version);
|
|
28256
|
+
const dest = path21.join(target, file);
|
|
28257
|
+
const stat = lstatOrNull(dest);
|
|
28258
|
+
if (stat?.isSymbolicLink()) {
|
|
28259
|
+
results.push({ file: dest, action: "skipped-symlink" });
|
|
28260
|
+
continue;
|
|
28261
|
+
}
|
|
28262
|
+
if (!stat) {
|
|
28263
|
+
mkdirSync3(target, { recursive: true });
|
|
28264
|
+
try {
|
|
28265
|
+
writeFileSync3(dest, content, { flag: "wx" });
|
|
28266
|
+
results.push({ file: dest, action: "installed" });
|
|
28267
|
+
} catch (error) {
|
|
28268
|
+
if (error.code !== "EEXIST")
|
|
28269
|
+
throw error;
|
|
28270
|
+
results.push({ file: dest, action: "kept-user-file" });
|
|
28271
|
+
}
|
|
28272
|
+
continue;
|
|
28273
|
+
}
|
|
28274
|
+
if (!stat.isFile()) {
|
|
28275
|
+
results.push({ file: dest, action: "kept-user-file" });
|
|
28276
|
+
continue;
|
|
28277
|
+
}
|
|
28278
|
+
const current = readFileSync7(dest, "utf8");
|
|
28279
|
+
if (current === content) {
|
|
28280
|
+
results.push({ file: dest, action: "current" });
|
|
28281
|
+
continue;
|
|
28282
|
+
}
|
|
28283
|
+
if (!current.startsWith(CODEX_AGENT_MARKER)) {
|
|
28284
|
+
results.push({ file: dest, action: "kept-user-file" });
|
|
28285
|
+
continue;
|
|
28286
|
+
}
|
|
28287
|
+
const written = agentMarkerVersion(current);
|
|
28288
|
+
if (written && (!version || !versionAtLeast(version, written))) {
|
|
28289
|
+
results.push({ file: dest, action: "kept-newer-version" });
|
|
28290
|
+
continue;
|
|
28291
|
+
}
|
|
28292
|
+
const temp = path21.join(target, `.${file}.${process.pid}.${Date.now()}.tmp`);
|
|
28293
|
+
writeFileSync3(temp, content, { flag: "wx" });
|
|
28294
|
+
try {
|
|
28295
|
+
renameSync2(temp, dest);
|
|
28296
|
+
} catch (error) {
|
|
28297
|
+
rmSync2(temp, { force: true });
|
|
28298
|
+
throw error;
|
|
28299
|
+
}
|
|
28300
|
+
results.push({ file: dest, action: "updated" });
|
|
28301
|
+
}
|
|
28302
|
+
return results;
|
|
28303
|
+
};
|
|
28304
|
+
|
|
28200
28305
|
// packages/workit-codex/scripts/launch-mcp.ts
|
|
28201
28306
|
var codexQualification = (host) => host === "codex_cli" ? { surface: host, cli: SUPPORT_MATRIX.codex.cli } : {
|
|
28202
28307
|
surface: host,
|
|
@@ -28206,8 +28311,8 @@ var codexQualification = (host) => host === "codex_cli" ? { surface: host, cli:
|
|
|
28206
28311
|
var resolveCodexWorkspaceRoot = (pluginRoot, env) => {
|
|
28207
28312
|
const explicit = env.WORKFLOW_WORKSPACE_ROOT;
|
|
28208
28313
|
const inherited = env.PWD;
|
|
28209
|
-
const candidate = explicit ?? (inherited &&
|
|
28210
|
-
if (!candidate || !
|
|
28314
|
+
const candidate = explicit ?? (inherited && path22.resolve(inherited) !== path22.resolve(pluginRoot) ? inherited : undefined);
|
|
28315
|
+
if (!candidate || !path22.isAbsolute(candidate) || !existsSync10(candidate))
|
|
28211
28316
|
return null;
|
|
28212
28317
|
try {
|
|
28213
28318
|
if (!statSync3(candidate).isDirectory())
|
|
@@ -28246,10 +28351,33 @@ var codexContextProvider = (host = detectCodexSurface(process.env), root) => ({
|
|
|
28246
28351
|
};
|
|
28247
28352
|
}
|
|
28248
28353
|
});
|
|
28249
|
-
|
|
28354
|
+
var pluginRoot = () => path22.resolve(path22.dirname(fileURLToPath3(import.meta.url)), "..");
|
|
28355
|
+
var syncCodexAgents = (root) => {
|
|
28356
|
+
const codexHome = codexHomeOfInstall(root);
|
|
28357
|
+
if (!codexHome)
|
|
28358
|
+
return;
|
|
28359
|
+
try {
|
|
28360
|
+
installCodexAgents(root, codexHome);
|
|
28361
|
+
} catch {}
|
|
28362
|
+
};
|
|
28363
|
+
if (__require.main == __require.module) {
|
|
28364
|
+
if (process.argv.includes("--install-agents")) {
|
|
28365
|
+
const root = pluginRoot();
|
|
28366
|
+
const results = installCodexAgents(root, codexHomeFor(root, process.env));
|
|
28367
|
+
for (const r of results)
|
|
28368
|
+
process.stdout.write(`${r.action} ${r.file}
|
|
28369
|
+
`);
|
|
28370
|
+
if (results.length === 0)
|
|
28371
|
+
process.stdout.write(`no agents bundled in ${root}
|
|
28372
|
+
`);
|
|
28373
|
+
process.exit(0);
|
|
28374
|
+
}
|
|
28375
|
+
syncCodexAgents(pluginRoot());
|
|
28250
28376
|
await runStdioServer(detectCodexSurface(process.env), codexContextProvider());
|
|
28377
|
+
}
|
|
28251
28378
|
export {
|
|
28252
28379
|
codexContextProvider,
|
|
28253
28380
|
codexQualification,
|
|
28254
|
-
resolveCodexWorkspaceRoot
|
|
28381
|
+
resolveCodexWorkspaceRoot,
|
|
28382
|
+
syncCodexAgents
|
|
28255
28383
|
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-codex",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.7.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "Workit Codex CLI/desktop plugin — shared MCP transport, hooks, and
|
|
5
|
+
"description": "Workit Codex CLI/desktop plugin — shared MCP transport, hooks, method skills, and verifier/reviewer/implementer agents",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agentic-coding",
|
|
8
8
|
"ai-agents",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
".codex-plugin/",
|
|
28
28
|
".mcp.json",
|
|
29
29
|
"hooks/hooks.json",
|
|
30
|
-
"skills/"
|
|
30
|
+
"skills/",
|
|
31
|
+
"agents/"
|
|
31
32
|
],
|
|
32
33
|
"type": "module",
|
|
33
34
|
"main": "./dist/launch-mcp.js",
|
|
@@ -38,8 +39,8 @@
|
|
|
38
39
|
"build": "bun scripts/build.ts"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@brainervirus/workit-core": "^8.
|
|
42
|
-
"@brainervirus/workit-mcp": "^8.
|
|
42
|
+
"@brainervirus/workit-core": "^8.7.0",
|
|
43
|
+
"@brainervirus/workit-mcp": "^8.7.0"
|
|
43
44
|
},
|
|
44
45
|
"engines": {
|
|
45
46
|
"node": ">=24"
|