@brainervirus/workit-claude-code 7.6.0 → 7.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/.claude-plugin/plugin.json +1 -1
- package/dist/workit-hook.js +28 -28
- package/dist/workit.js +758 -363
- package/package.json +3 -3
- package/skills/fanout/SKILL.md +46 -46
- package/skills/fanout/references/brief.md +15 -8
- package/skills/fanout/references/orchestration.md +117 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-claude-code",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Claude Code plugin — session and per-turn task context, branch policy on git shell commands, workit 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-cli": "^7.
|
|
43
|
-
"@brainervirus/workit-core": "^7.
|
|
42
|
+
"@brainervirus/workit-cli": "^7.7.0",
|
|
43
|
+
"@brainervirus/workit-core": "^7.7.0"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": ">=24"
|
package/skills/fanout/SKILL.md
CHANGED
|
@@ -8,60 +8,60 @@ description: Run independent slices in parallel - one worker per isolated worktr
|
|
|
8
8
|
Fan out only independent slices: disjoint files, no shared mutable state, each
|
|
9
9
|
verifiable alone. Code-coupled work stays with one owner, who fans out after
|
|
10
10
|
the blocking part lands. A worker whose whole job is re-running one command is
|
|
11
|
-
ceremony; do it yourself.
|
|
11
|
+
ceremony; do it yourself. Workit never spawns agents; you do.
|
|
12
12
|
|
|
13
13
|
1. **Plan the slices** (call the Skill tool with `workit:shape`) in a plan file (`references/brief.md`):
|
|
14
|
-
per slice an id, branch, TIER,
|
|
15
|
-
`
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
`workit ledger check --branch <b>` per slice, land in `fanout
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
14
|
+
per slice an id, branch, TIER, SCOPE globs, `owns` for shared files,
|
|
15
|
+
`dependsOn` only for a real dependency, and the brief fields. `workit fanout
|
|
16
|
+
plan <plan.json>` refuses an empty or placeholder brief field (exit 2) and
|
|
17
|
+
two slices that may write one file (exit 3) with a fix; apply it and re-run:
|
|
18
|
+
refuse to spawn while a field is empty or the plan is refused. One PR per
|
|
19
|
+
slice is the default; `"fanIn": "integration"` only when the user wants one
|
|
20
|
+
PR (`references/orchestration.md`).
|
|
21
|
+
2. **Record standing orders** (`workit ledger standing add "<order>"`): every
|
|
22
|
+
user directive all workers share. Directives decay across resumes.
|
|
23
|
+
3. **Brief each worker verbatim** with `workit fanout brief <slice>`: plan
|
|
24
|
+
fields, standing orders, SCRATCH, session id, fan-in rule. Never hand-edit
|
|
25
|
+
it; change the plan or the standing orders and render again.
|
|
26
|
+
4. **Spawn in a rolling window**, in the background, each in its own worktree:
|
|
27
|
+
keep 4-6 in flight and refill from `spawnable` in `workit fanout status` as
|
|
28
|
+
each one finishes. Pick the model from TIER (`references/orchestration.md`).
|
|
29
|
+
Claude Code: the `implementer` agent; elsewhere first `workit fanout
|
|
30
|
+
worktree create <slice>`.
|
|
31
|
+
5. **Judge liveness by side effects only:** `workit fanout status` (head age,
|
|
32
|
+
PR, CI, verdict, landed; STUCK past the TIMEBOX). Stop a stuck worker and
|
|
33
|
+
observe that it exited (a timeout is not proof). Removing a worktree drops
|
|
34
|
+
its uncommitted changes: `workit fanout worktree release <slice>` records
|
|
35
|
+
`git status` in the ledger first and refuses them without `--force`. Never
|
|
36
|
+
two live workers on one branch.
|
|
37
|
+
6. **Retry once, then escalate.** A stuck or failed slice gets one retry with
|
|
38
|
+
a fresh brief (`workit fanout brief <slice> --mode resume`, same branch);
|
|
39
|
+
if that fails too, re-slice it, take it over, or report the gap. Never
|
|
40
|
+
chain resumes. A hard slice may race instead: N attempts, keep the best
|
|
41
|
+
verdict (`references/orchestration.md`).
|
|
42
|
+
7. **Verify by the workspace `verification` setting** (`workit grant show`).
|
|
43
|
+
A report is a pointer, never evidence. `self`: a verifier that wrote none
|
|
44
|
+
of the slices, or you if you wrote none. `independent` or high risk: a
|
|
45
|
+
separate verifier session, never yours (doctrine: the ledger only refuses
|
|
46
|
+
authors). One verifier may take a batch of slices, one verdict per branch
|
|
47
|
+
(`workit ledger verdict <result> --branch <b> --how "<evidence>"`), in a
|
|
48
|
+
session never chosen by the author. A review panel on separate models only at high risk.
|
|
49
|
+
8. **Fan in** with `workit fanout check`: out-of-scope files (any file outside
|
|
50
|
+
it stops the fan-in) and `git merge-tree` conflicts with trunk and between
|
|
51
|
+
siblings. Fix what it names until it exits 0; a merged slice reads as
|
|
52
|
+
landed. Then `workit ledger check --branch <b>` per slice, land in `fanout
|
|
53
|
+
status` order, release the worktrees you made, and `workit ledger standing
|
|
54
|
+
clear`. Only you touch topology: workers never rebase, retarget or merge,
|
|
55
|
+
except the integration-tip merge in integration mode. Then ship
|
|
56
|
+
(call the Skill tool with `workit:ship`).
|
|
56
57
|
|
|
57
58
|
## Example
|
|
58
59
|
|
|
59
60
|
Bad brief: "Do the API part and add tests." (no scope, no acceptance, no
|
|
60
61
|
verify command, so nobody can tell when it is done)
|
|
61
62
|
|
|
62
|
-
Good brief:
|
|
63
|
-
|
|
64
|
-
`workit check test`; ...).
|
|
63
|
+
Good brief: the output of `workit fanout brief usage-endpoint`
|
|
64
|
+
(`references/brief.md` shows one).
|
|
65
65
|
|
|
66
66
|
## Check
|
|
67
67
|
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# Worker brief template
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
`workit fanout brief <slice>` renders this brief from the plan, the standing
|
|
4
|
+
orders in force (`workit ledger standing list`) and the slice's scratch dir;
|
|
5
|
+
pass its output verbatim. The template below is what it fills in. Every field
|
|
6
|
+
is required. A brief with an empty field is not spawned. Point to files and
|
|
7
|
+
ledger rows instead of pasting their content. Size the slice so the worker
|
|
8
|
+
finishes it in about 150k tokens of context; split a larger one first.
|
|
6
9
|
|
|
7
10
|
```md
|
|
8
11
|
MODE: <new | resume (a replacement continuing an existing branch)>
|
|
@@ -16,11 +19,12 @@ VERIFY: <exact commands, e.g. `workit check test`, the verify-<app> feature to d
|
|
|
16
19
|
TIER: <mundane | standard | hard: how much model the slice needs>
|
|
17
20
|
TIMEBOX: <wall clock or turn budget; past it without a new commit you will be replaced>
|
|
18
21
|
SCRATCH: <your own temp dir: the one `fanout worktree create` printed, else `mktemp -d`; never a shared path>
|
|
19
|
-
FORBIDDEN: <no edits outside SCOPE; no
|
|
22
|
+
FORBIDDEN: <no edits outside SCOPE; no new dependencies; ...>
|
|
23
|
+
FAN-IN: <one PR per slice: no rebase, retarget, merge or force-push | integration: merge the integration tip before reporting, nothing else>
|
|
20
24
|
REPORT: branch, head SHA, files changed, each VERIFY command with its exit code,
|
|
21
25
|
each ACCEPTANCE line met / not met, rulings you made (`workit ledger ruling`),
|
|
22
26
|
anything out of scope as a follow-up, not a diff.
|
|
23
|
-
STANDING: <the standing orders, verbatim:
|
|
27
|
+
STANDING: <the standing orders, verbatim: `workit ledger standing add` records each one>
|
|
24
28
|
export WORKIT_SESSION_ID=<lead>-w<n> (set by the lead; a verifier brief gets <lead>-v<n>)
|
|
25
29
|
```
|
|
26
30
|
|
|
@@ -40,7 +44,8 @@ VERIFY: `workit check test`; verify-api feature "usage"
|
|
|
40
44
|
TIER: standard
|
|
41
45
|
TIMEBOX: 45 minutes
|
|
42
46
|
SCRATCH: ../app-wt/usage-endpoint/.workit-scratch
|
|
43
|
-
FORBIDDEN: no edits outside SCOPE; no schema migration; no
|
|
47
|
+
FORBIDDEN: no edits outside SCOPE; no schema migration; no new packages
|
|
48
|
+
FAN-IN: one PR per slice. Never rebase, retarget, merge or force-push: the lead owns topology.
|
|
44
49
|
REPORT: as in the template
|
|
45
50
|
STANDING: conventional commits; no comments that restate code; ask nothing, record rulings instead
|
|
46
51
|
```
|
|
@@ -55,7 +60,9 @@ stack); `worktree` defaults to `../<repo>-wt/<id>`. `owns` claims a shared
|
|
|
55
60
|
file another slice's glob also matches. Globs that match no file yet are compared
|
|
56
61
|
through a sample path. Use `/` as the separator; a backslash only escapes
|
|
57
62
|
literal brackets: `"app/\\[id\\]/page.tsx"`. A `timebox` such as `45 minutes`
|
|
58
|
-
is the slice's STUCK threshold in `workit fanout status`.
|
|
63
|
+
is the slice's STUCK threshold in `workit fanout status`. `"fanIn":
|
|
64
|
+
"integration"` (with an integration branch as `trunk`) is the one-PR mode in
|
|
65
|
+
`orchestration.md`; the default `"prs"` lands one PR per slice.
|
|
59
66
|
|
|
60
67
|
```json
|
|
61
68
|
{
|
|
@@ -90,7 +97,7 @@ is the slice's STUCK threshold in `workit fanout status`.
|
|
|
90
97
|
}
|
|
91
98
|
```
|
|
92
99
|
|
|
93
|
-
## Worker rules (
|
|
100
|
+
## Worker rules (`workit fanout brief` appends them as RULES)
|
|
94
101
|
|
|
95
102
|
1. First command. `MODE: new`: `workit git branch <branch> --base <base>` (the
|
|
96
103
|
worktree may start on a name that breaks branch policy). `MODE: resume`:
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Running a fanout
|
|
2
|
+
|
|
3
|
+
How the lead picks models, keeps workers flowing, retries, races, verifies
|
|
4
|
+
and fans in. Workit records and checks; the host's own subagents run the work.
|
|
5
|
+
|
|
6
|
+
## TIER to model
|
|
7
|
+
|
|
8
|
+
TIER is a field of each slice and of its brief. Map it where the host lets you
|
|
9
|
+
pick a model per spawn; nothing in the workspace config routes it.
|
|
10
|
+
|
|
11
|
+
| TIER | Claude Code (`model` on the Agent call) | Hosts without a per-spawn model |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| scouting (read-only search, not a slice) | `haiku` | host default |
|
|
14
|
+
| mundane | `sonnet` | host default |
|
|
15
|
+
| standard | omit it (inherits yours) | host default |
|
|
16
|
+
| hard | omit it (inherits yours); consider a race | host default |
|
|
17
|
+
|
|
18
|
+
OpenCode takes a subagent's model from its agent config: pick a configured
|
|
19
|
+
agent whose model fits the TIER, else the default. Codex, Cursor and Pi run
|
|
20
|
+
every worker on the host's model, so TIER only sizes the timebox and decides
|
|
21
|
+
whether to race.
|
|
22
|
+
|
|
23
|
+
## Rolling window
|
|
24
|
+
|
|
25
|
+
Keep 4-6 workers in flight on Claude Code; elsewhere as many as the host runs
|
|
26
|
+
in the background, never more than 6. Do not wait for a whole wave: when one
|
|
27
|
+
worker finishes (its notification, or a new head or PR in `workit fanout
|
|
28
|
+
status`), verify it, then spawn the next slice from `spawnable` in the same
|
|
29
|
+
status output. A slice whose dependencies landed, or a stacked child whose
|
|
30
|
+
parent is verified, appears there by itself.
|
|
31
|
+
|
|
32
|
+
## Retry, then escalate
|
|
33
|
+
|
|
34
|
+
A slice is retried when it is STUCK, its worker exits without meeting
|
|
35
|
+
ACCEPTANCE, or its verdict fails. Stop the worker and observe that it exited.
|
|
36
|
+
Release its worktree: `workit fanout worktree release <slice>` (native
|
|
37
|
+
worktrees: record `git -C <wt> status --short` first). Then spawn one fresh
|
|
38
|
+
worker with `workit fanout brief <slice> --mode resume`: same branch, and the
|
|
39
|
+
brief points at its head and its ledger rows (last report, verdicts,
|
|
40
|
+
rulings). If the retry fails too, escalate instead of a third worker:
|
|
41
|
+
re-slice it smaller (`workit fanout plan` again), take it over yourself, or
|
|
42
|
+
report the gap to the user.
|
|
43
|
+
|
|
44
|
+
## Race a hard slice
|
|
45
|
+
|
|
46
|
+
When a hard slice has an uncertain approach and a cheap VERIFY, run 2-3
|
|
47
|
+
attempts at once instead of retrying in series. `workit fanout brief <slice>
|
|
48
|
+
--attempt <n>` gives each attempt its own branch (`<branch>-try<n>`), session
|
|
49
|
+
and scratch dir. Each attempt needs its own worktree: Claude Code's
|
|
50
|
+
`implementer` isolates natively; on other hosts `fanout worktree create` makes
|
|
51
|
+
only the slice's own worktree, so run the attempts one after another there.
|
|
52
|
+
Verify every attempt, keep the one with the best verdict (accepted first,
|
|
53
|
+
then the fewest changed files, then the earliest), point the slice branch at
|
|
54
|
+
it (`git branch <branch> <winner>`), have the verifier record the verdict on
|
|
55
|
+
`<branch>` (same head), and delete the losing attempt branches.
|
|
56
|
+
|
|
57
|
+
## Verification
|
|
58
|
+
|
|
59
|
+
Follow the workspace `verification` setting (`workit grant show`); the
|
|
60
|
+
worker never records a verdict on its own work.
|
|
61
|
+
|
|
62
|
+
- `self` (the default): a verifier that wrote none of the slices records the
|
|
63
|
+
verdicts. A lead that authored none of the slices may record them in its
|
|
64
|
+
own session.
|
|
65
|
+
- `independent`, and any slice at high risk: a separate verifier session
|
|
66
|
+
records them, never the lead's own; at high risk one verifier per slice,
|
|
67
|
+
plus a review panel (below). This is doctrine, not enforced: the ledger
|
|
68
|
+
only tells a branch's authors from everyone else, and a lead that wrote
|
|
69
|
+
none of it counts as independent.
|
|
70
|
+
|
|
71
|
+
Which session id a verdict carries, per host:
|
|
72
|
+
|
|
73
|
+
- Claude Code: subagents inherit your `WORKIT_SESSION_ID`, so the
|
|
74
|
+
SubagentStart hook names each `verifier` and `reviewer` its own session
|
|
75
|
+
(`<lead>:<agent id>`), passed as `--session`; that one wins over any
|
|
76
|
+
`<lead>-v<n>` in a brief. An `implementer` uses the session its brief
|
|
77
|
+
exports for its workit commands.
|
|
78
|
+
- Other hosts: the session the brief sets wins: `export
|
|
79
|
+
WORKIT_SESSION_ID=<lead>-w-<slice>` from `workit fanout brief` for a
|
|
80
|
+
worker, `<lead>-v<n>` (or `--as verifier`) for a verifier you start.
|
|
81
|
+
|
|
82
|
+
A batch verifier takes several slices on one surface in one session: for
|
|
83
|
+
each branch it checks out the head, runs that slice's VERIFY, and records its
|
|
84
|
+
own `workit ledger verdict <result> --branch <b> --how "<evidence>"`. Every
|
|
85
|
+
verdict is keyed to that branch's head SHA; a slice whose head moves after
|
|
86
|
+
it needs a new one. Batch at most what fits one context, about 4 slices.
|
|
87
|
+
|
|
88
|
+
## Review panel (high risk only)
|
|
89
|
+
|
|
90
|
+
At risk=high only, 2-3 fresh reviewers (call the Skill tool with `workit:review`), each on a model
|
|
91
|
+
other than the author's (Claude Code: a different `model`), each records
|
|
92
|
+
`workit ledger verdict <result> --kind review --branch <b> --how "<findings>"`.
|
|
93
|
+
Land only when every panel verdict passes. Below high risk a panel costs
|
|
94
|
+
more than it finds.
|
|
95
|
+
|
|
96
|
+
## Integration-branch fan-in (one PR)
|
|
97
|
+
|
|
98
|
+
Only when the user wants one PR for the whole fanout:
|
|
99
|
+
|
|
100
|
+
1. Cut the integration branch (`workit git branch <integration> --base
|
|
101
|
+
<trunk>`) and plan with `"fanIn": "integration"` and `--trunk
|
|
102
|
+
<integration>`. Planning refuses integration mode on origin's default
|
|
103
|
+
branch.
|
|
104
|
+
2. Every brief then tells the worker to merge the integration tip into its
|
|
105
|
+
branch before reporting (the fast-forward rule). That merge is the only
|
|
106
|
+
one a worker makes, and only in this mode.
|
|
107
|
+
3. Land each verified slice with `git merge --ff-only <slice-branch>` in the
|
|
108
|
+
integration checkout. Not a fast-forward (the tip moved since the worker
|
|
109
|
+
merged)? Resume the worker to merge again; never a merge commit of your own.
|
|
110
|
+
4. `workit fanout check` gates against the integration branch; a slice whose
|
|
111
|
+
tip is on it reads as landed. When all have landed, ship the integration
|
|
112
|
+
branch as one PR (call the Skill tool with `workit:ship`).
|
|
113
|
+
|
|
114
|
+
## Stacks
|
|
115
|
+
|
|
116
|
+
For stacked slices (`dependsOn` one parent): `workit stack plan <bottom> …
|
|
117
|
+
<top>` once, then `workit stack sync` and `workit stack land`.
|