@brainervirus/workit-codex 8.11.0 → 8.12.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workit",
3
- "version": "8.11.0",
3
+ "version": "8.12.0",
4
4
  "description": "Adaptive engineering workflow rails for Codex",
5
5
  "author": {
6
6
  "name": "BrainerVirus"
@@ -18849,7 +18849,7 @@ function loadCheckConfig(cwd) {
18849
18849
  gates[gate] = names;
18850
18850
  }
18851
18851
  }
18852
- return { source: CHECKS_FILE, root, checks, gates, error: null };
18852
+ return { source: CHECKS_FILE, root, checks, gates, error: null, resources: parsed.resources };
18853
18853
  }
18854
18854
  var sameArgv = (left, right) => left.length === right.length && left.every((item, index) => item === right[index]);
18855
18855
  function matchesNamedCheck(config, name, argv, cwd) {
@@ -19437,6 +19437,7 @@ var workspaceConfigSchema = object({
19437
19437
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
19438
19438
  defaultEndpoint: unknown().optional(),
19439
19439
  verification: _enum(["self", "independent"]).optional(),
19440
+ trailers: boolean2().optional(),
19440
19441
  autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
19441
19442
  kind,
19442
19443
  union([boolean2(), literal("verified")]).optional()
@@ -19718,8 +19719,8 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
19718
19719
  var runtimeWorkspaceIndexSchema = object({
19719
19720
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
19720
19721
  }).passthrough();
19721
- var matchRuntimeWorkspace = (cwd) => {
19722
- const file = path10.join(configDir(), "workspaces.json");
19722
+ var matchRuntimeWorkspace = (cwd, dir = configDir()) => {
19723
+ const file = path10.join(dir, "workspaces.json");
19723
19724
  let raw;
19724
19725
  try {
19725
19726
  raw = readFileSync3(file, "utf8");
@@ -19748,7 +19749,7 @@ var matchRuntimeWorkspace = (cwd) => {
19748
19749
  const matches = matchingEntries(cwd, entries ?? []);
19749
19750
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
19750
19751
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
19751
- return selected ? { file, selected } : null;
19752
+ return selected ? { file, selected, matches } : null;
19752
19753
  };
19753
19754
  var resolveRuntimeReleaseTracks = (cwd) => {
19754
19755
  const matched = matchRuntimeWorkspace(cwd);
@@ -91,9 +91,9 @@ Autonomy contract:
91
91
  ship), go to the effective endpoint in \`workit grant show\`: \`pr\` opens
92
92
  the PR; \`green\` babysits it without asking (workit-ship) to merge-ready,
93
93
  never merging; \`merged\` also lands it with \`workit pr merge\`.
94
- Merge and release need a workspace grant, which only the user raises from
95
- their own terminal (a blocked verb names how); never edit workspaces.json or
96
- route around a grant_required.
94
+ Merge and release need a workspace grant only the user raises from their
95
+ own terminal (a blocked verb names how); never edit workspaces.json or route
96
+ around a grant_required.
97
97
  - Ask only for a product or preference choice, or for authority you lack, with
98
98
  your recommended answer. Facts are yours: read, run or prototype.
99
99
  - Label claims measured (run and seen this session), inferred, or guess.
@@ -102,17 +102,19 @@ Autonomy contract:
102
102
  - Author is not verifier: your own verdict is \`--self\`, shown as
103
103
  self-reviewed, never verified. High risk, \`verification: independent\` and
104
104
  merge need a verifier with its own host-derived session (a subagent's
105
- \`<lead>:<child>\`, set by the host); never hand-mint one such as \`<lead>-v1\`.
105
+ \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
106
106
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
107
107
  is not evidence of a requested remote push. Before reporting delivery,
108
108
  reconcile every requested item and observe it (\`workit verify-delivery\`).
109
109
 
110
110
  CLI first: if a step has one right answer, use the \`workit\` verb instead of
111
111
  hand-running git, gh or glab (\`workit git|pr|ci|check\`; \`workit help\` lists
112
- the rest; without \`workit\` on PATH, \`npx -y @brainervirus/workit-cli\`).
112
+ the rest; lacking \`workit\`, \`npx -y @brainervirus/workit-cli\`).
113
+ Add Co-Authored-By via \`workit git commit --trailer "K: v" -- <paths>\`, never
114
+ an amend.
113
115
  The task families (task, policy, evidence, finding, decision, worker, state)
114
116
  are optional continuity for tracked work; each branch has one implicit task,
115
- created by the first recording, and a solo edit needs no task. A decision
117
+ and a solo edit needs no task. A decision
116
118
  records a user choice; it never authorizes an effect. Judge work once with
117
119
  \`workit policy assess --judge risk= behavior= product-choice= plan=\`.
118
120
  Across repositories, bind each item to its checkout, branch and endpoint,
@@ -8960,7 +8962,7 @@ function loadCheckConfig(cwd) {
8960
8962
  gates[gate] = names;
8961
8963
  }
8962
8964
  }
8963
- return { source: CHECKS_FILE, root, checks, gates, error: null };
8965
+ return { source: CHECKS_FILE, root, checks, gates, error: null, resources: parsed.resources };
8964
8966
  }
8965
8967
  var sameArgv = (left, right) => left.length === right.length && left.every((item, index) => item === right[index]);
8966
8968
  function matchesNamedCheck(config, name, argv, cwd) {
@@ -12506,6 +12508,7 @@ var workspaceConfigSchema = object({
12506
12508
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
12507
12509
  defaultEndpoint: unknown().optional(),
12508
12510
  verification: _enum(["self", "independent"]).optional(),
12511
+ trailers: boolean2().optional(),
12509
12512
  autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
12510
12513
  kind,
12511
12514
  union([boolean2(), literal("verified")]).optional()
@@ -12787,8 +12790,8 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
12787
12790
  var runtimeWorkspaceIndexSchema = object({
12788
12791
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
12789
12792
  }).passthrough();
12790
- var matchRuntimeWorkspace = (cwd) => {
12791
- const file = path11.join(configDir(), "workspaces.json");
12793
+ var matchRuntimeWorkspace = (cwd, dir = configDir()) => {
12794
+ const file = path11.join(dir, "workspaces.json");
12792
12795
  let raw;
12793
12796
  try {
12794
12797
  raw = readFileSync3(file, "utf8");
@@ -12817,12 +12820,30 @@ var matchRuntimeWorkspace = (cwd) => {
12817
12820
  const matches = matchingEntries(cwd, entries ?? []);
12818
12821
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
12819
12822
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
12820
- return selected ? { file, selected } : null;
12823
+ return selected ? { file, selected, matches } : null;
12821
12824
  };
12822
12825
  var resolveRuntimeReleaseTracks = (cwd) => {
12823
12826
  const matched = matchRuntimeWorkspace(cwd);
12824
12827
  return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
12825
12828
  };
12829
+ var workspaceTrailers = (cwd, dir) => {
12830
+ let matched;
12831
+ try {
12832
+ matched = matchRuntimeWorkspace(cwd, dir);
12833
+ } catch {
12834
+ return { enabled: true, workspace: null, from: null };
12835
+ }
12836
+ if (!matched)
12837
+ return { enabled: true, workspace: null, from: null };
12838
+ const { selected, matches } = matched;
12839
+ const enclosing = matches.filter((entry) => entry !== selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
12840
+ const source = [selected, ...enclosing].find((entry) => typeof entry.trailers === "boolean");
12841
+ return {
12842
+ enabled: source?.trailers !== false,
12843
+ workspace: selected.name,
12844
+ from: source?.name ?? null
12845
+ };
12846
+ };
12826
12847
  var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
12827
12848
  const matched = matchRuntimeWorkspace(cwd);
12828
12849
  if (!matched)
@@ -19400,7 +19421,7 @@ var workitRole = (descriptor, agentType) => {
19400
19421
  };
19401
19422
  var subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128);
19402
19423
  var CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
19403
- var ISOLATED_GIT = 'Run git as plain, separate commands inside your worktree (`git switch -c <branch> <base>`, `git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a commit-msg hook that adds the trailer), never `workit git …`: Claude Code\'s worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (`workit check`, `workit ledger`, `workit pr`).';
19424
+ var isolatedGit = (cwd) => `Run git as plain, separate commands inside your worktree (\`git switch -c <branch> <base>\`, ${workspaceTrailers(cwd).enabled ? '`git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a prepare-commit-msg hook that adds the trailer' : "`git commit` (this workspace sets trailers: false: add no Workit-Session trailer), `git push`"}; add Co-Authored-By with \`git commit --trailer\` in the same commit, never by amending), never \`workit git …\`: Claude Code's worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (\`workit check\`, \`workit ledger\`, \`workit pr\`).`;
19404
19425
  var subagentStartText = (input, descriptor, event) => {
19405
19426
  const session = input.session.id ?? null;
19406
19427
  const role = workitRole(descriptor, event.agentType);
@@ -19408,9 +19429,9 @@ var subagentStartText = (input, descriptor, event) => {
19408
19429
  const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" || CLAUDE_WORKTREE.test(input.cwd));
19409
19430
  const guide = role === "implementer" ? branchGuidance(input.cwd) : null;
19410
19431
  if (role === "implementer" && isolated)
19411
- return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${ISOLATED_GIT} Plain git is expected here, and the branch name is still policy-checked: a raw \`git switch -c\`, \`git checkout -b\`, \`git branch\` or \`git worktree add -b\` onto a protected or non-compliant name is denied, so use a policy-compliant branch.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
19432
+ return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${isolatedGit(input.cwd)} Plain git is expected here, and the branch name is still policy-checked: a raw \`git switch -c\`, \`git checkout -b\`, \`git branch\` or \`git worktree add -b\` onto a protected or non-compliant name is denied, so use a policy-compliant branch.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
19412
19433
  if (isolated)
19413
- return `${ISOLATED_GIT}
19434
+ return `${isolatedGit(input.cwd)}
19414
19435
  ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
19415
19436
  if (role === "implementer")
19416
19437
  return `Workit observed ${who} as an implementer: it edits and commits only in its own git worktree (the lead makes one with \`workit fanout worktree create <slice>\`), never in the lead's checkout, within its brief's scope. Before the first commit, switch to a policy-compliant branch with \`workit git branch <branch> --base <base>\` (or \`--kind <kind> --slug <slug>\`, which picks the base); branch policy hooks still deny protected or non-compliant branches, raw git included.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
@@ -37,6 +37,6 @@ if (quiet)
37
37
  process.stdout.write(`${JSON.stringify({ hookSpecificOutput: { hookEventName: quiet } })}
38
38
  `);
39
39
  else {
40
- const { runCodexHook } = await import("./workit-hook-gtdf2ra8.js");
40
+ const { runCodexHook } = await import("./workit-hook-yfq6yhse.js");
41
41
  await runCodexHook([payload]);
42
42
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-codex",
3
- "version": "8.11.0",
3
+ "version": "8.12.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
  "dependencies": {
42
- "@brainervirus/workit-core": "^8.11.0",
43
- "@brainervirus/workit-mcp": "^8.11.0"
42
+ "@brainervirus/workit-core": "^8.12.0",
43
+ "@brainervirus/workit-mcp": "^8.12.0"
44
44
  },
45
45
  "engines": {
46
46
  "node": ">=24"
@@ -25,7 +25,7 @@ REPORT: branch, head SHA, files changed, each VERIFY command with its exit code,
25
25
  each ACCEPTANCE line met / not met, rulings you made (`workit ledger ruling`),
26
26
  anything out of scope as a follow-up, not a diff.
27
27
  STANDING: <the standing orders, verbatim: `workit ledger standing add` records each one>
28
- export WORKIT_SESSION_ID=<lead>-w<n> (set by the lead for a worker's commits; a verifier brief sets none: the host derives it)
28
+ <identity line, per the lead's host: see "Identity and git rules per host" below>
29
29
  ```
30
30
 
31
31
  ## Worked example
@@ -97,17 +97,32 @@ is the slice's STUCK threshold in `workit fanout status`. `"fanIn":
97
97
  }
98
98
  ```
99
99
 
100
+ ## Identity and git rules per host
101
+
102
+ `workit fanout brief` renders the identity line and RULES 1 and 3 for the
103
+ lead's host (`WORKIT_HOST`, or the host's own session variable):
104
+
105
+ | Lead's host | Identity line | RULES 1 and 3 |
106
+ | --- | --- | --- |
107
+ | Claude Code | `Session: your env already has WORKIT_SESSION_ID (the lead's id)`; no `export`, no hand-minted id (SubagentStart issues `<lead>:<agent id>` only to verifiers and reviewers, never to an implementer, so the worker's commits carry the lead's id) | plain git: `git fetch origin && git switch -c <branch> origin/<base>` and `git commit -m <msg> --trailer "Workit-Session: <the env WORKIT_SESSION_ID>" --trailer "<host attribution>" -- <paths in SCOPE>`, because worktree isolation refuses every `workit git` form |
108
+ | OpenCode, Pi, Codex | `Session: your host already sets WORKIT_SESSION_ID in your shell`; export nothing (the host derives the id and an export cannot replace it) | `workit git branch <branch> --base <base>`, `workit git commit -m <msg> -- <paths in SCOPE>` |
109
+ | Cursor, CI, a plain terminal | `export WORKIT_SESSION_ID=<lead>-w-<slice>` (`+try<n>` for a race attempt): declared, not checked | the same `workit git` forms |
110
+
111
+ `MODE: resume` is `git switch <branch>` on every host (the branch exists; the
112
+ lead removed the dead worker's worktree after its exit, so the switch
113
+ succeeds), then continue from its head. A race attempt (`--attempt <n>`)
114
+ follows its host's row with the branch `<branch>-try<n>`.
115
+
100
116
  ## Worker rules (`workit fanout brief` appends them as RULES)
101
117
 
102
- 1. First command. `MODE: new`: `workit git branch <branch> --base <base>` (the
103
- worktree may start on a name that breaks branch policy). `MODE: resume`:
104
- `git switch <branch>` (the branch exists; the lead removed the dead
105
- worker's worktree after its exit, so the switch succeeds), then continue
106
- from its head.
118
+ 1. First command: create the branch (`MODE: new`; the worktree may start on a
119
+ name that breaks branch policy) or `git switch` to it (`MODE: resume`),
120
+ as the table above says for your host.
107
121
  2. Decide ambiguities yourself and record them:
108
122
  `workit ledger ruling "<what>" --why "<why>" --cost-if-wrong "<cost>"`.
109
123
  Stop only for an irreversible action, a security-sensitive one, or a side
110
124
  effect outside the worktree.
111
- 3. Commit with `workit git commit -m "<msg>" -- <paths in SCOPE>`; push only if
112
- the brief says so.
125
+ 3. Commit as the table says (`workit git commit -m "<msg>" -- <paths in SCOPE>`,
126
+ or plain git with the trailers on Claude Code); push only if the brief says
127
+ so.
113
128
  4. Never record a verdict on your own work.
@@ -73,8 +73,8 @@ Which session id a verdict carries, per host:
73
73
  - Claude Code: subagents inherit your `WORKIT_SESSION_ID`, so the
74
74
  SubagentStart hook names each `verifier` and `reviewer` its own session
75
75
  (`<lead>:<agent id>`), passed exactly as `--session`: the hook records the
76
- ids it issues, and only those are accepted. An `implementer` uses the
77
- session its brief exports for its workit commands.
76
+ ids it issues, and only those are accepted. An `implementer` is issued
77
+ none: it keeps your id in its env for its workit commands and commits.
78
78
  - Codex: the `workit-verifier` and `workit-reviewer` agents get the same
79
79
  issued `--session` from SubagentStart; any other verifier passes
80
80
  `--as verifier`.
@@ -84,8 +84,13 @@ Which session id a verdict carries, per host:
84
84
  - Cursor (no session id in the shell): the brief sets the verifier's
85
85
  `WORKIT_SESSION_ID=<lead>:verifier-<random hex>`, a fresh suffix per
86
86
  verifier. Cursor cannot check it: it is declared, not derived.
87
- - A worker's commits use `export WORKIT_SESSION_ID=<lead>-w-<slice>` from
88
- `workit fanout brief`. A verdict under an id you made up (`<lead>-v1`,
87
+ - A worker's commits: on Claude Code the lead's `WORKIT_SESSION_ID` already in
88
+ its env (SubagentStart issues no implementer id; plain git, no export, so the
89
+ lead authored those commits: a verifier or reviewer records the verdict, not
90
+ the lead); on OpenCode, Pi and Codex the id the host already
91
+ puts in its shell; on Cursor, CI and a plain terminal the brief's
92
+ `export WORKIT_SESSION_ID=<lead>-w-<slice>` (see `brief.md`, "Identity and
93
+ git rules per host"). A verdict under an id you made up (`<lead>-v1`,
89
94
  `<lead>:v1`) is refused as `forged_session` on Claude Code, Codex,
90
95
  OpenCode and Pi.
91
96