bullswarm 0.28.2 → 0.28.4
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/CHANGELOG.md +34 -0
- package/connectors/command-code.json +13 -0
- package/package.json +1 -1
- package/skill/SKILL.md +87 -134
- package/skill/references/operations.md +14 -0
- package/skill/references/program.md +134 -0
- package/src/setup.js +28 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# bullswarm changelog
|
|
2
2
|
|
|
3
|
+
## 0.28.4 — the skill says how, the schema file says what
|
|
4
|
+
|
|
5
|
+
- skill: the method and the schema are now separate files. `skill/SKILL.md`
|
|
6
|
+
(1,345 → 914 words) keeps only what the kernel cannot check: choosing the
|
|
7
|
+
shape, decomposing into territories, dependencies as inputs rather than
|
|
8
|
+
phases, the integrator, evidence, the effort rule (writers are `implement`;
|
|
9
|
+
high belongs to `integration`, `architecture`, `adversarial-acceptance`;
|
|
10
|
+
never `defaults.effort: high`), and an explicit validate → read `advisories`
|
|
11
|
+
→ adjust → launch sequence. The new `skill/references/program.md` holds the
|
|
12
|
+
program format: fields, kinds, requirement-ID derivation, enforced rules and
|
|
13
|
+
one example that validates with no advisories. `plan contract` is no longer a
|
|
14
|
+
step in the default flow; operations.md documents it as the live fallback
|
|
15
|
+
and the dispatched planner's brief. Reasoning depth, digest details and the
|
|
16
|
+
watch flags live in operations.md only.
|
|
17
|
+
|
|
18
|
+
## 0.28.3 — connector upgrades learn new packaged profiles
|
|
19
|
+
|
|
20
|
+
- command-code: a profile entry for `deepseek/deepseek-v4.1-flash` that
|
|
21
|
+
carries the model's own pricing from
|
|
22
|
+
https://commandcode.ai/docs/resources/pricing-limits (2026-09-11): input
|
|
23
|
+
$0.15, cache read $0.003, output $0.60 per million tokens off peak (the
|
|
24
|
+
peak window is documented in the entry). Tier and rank stay exactly what the
|
|
25
|
+
generic flash catch-all gives; this is not a recommendation, and none will
|
|
26
|
+
be packaged without benchmark evidence. Note for operators: model discovery
|
|
27
|
+
is only re-run by `bullswarm strategy refresh`, so a model a CLI added since
|
|
28
|
+
the last refresh is rejected by `strategy set-rung` until you refresh.
|
|
29
|
+
- Connector upgrades now insert packaged `modelProfiles` entries that the
|
|
30
|
+
installed connector lacks (keyed by `match` or `id`) at the position the
|
|
31
|
+
packaged order implies: before the installed generic catch-all a specific
|
|
32
|
+
entry was written to precede, never ahead of a profile the operator
|
|
33
|
+
authored. Profiles the installed connector already holds are never touched.
|
|
34
|
+
Before this, `modelProfiles` was copied only when the installed connector
|
|
35
|
+
had none at all, so existing installations never learned new entries.
|
|
36
|
+
|
|
3
37
|
## 0.28.2 — terminal glyph fallback, issue watcher, health on a fresh home
|
|
4
38
|
|
|
5
39
|
- `bullswarm workflow` repainted flashing `?` characters on macOS
|
|
@@ -256,6 +256,19 @@
|
|
|
256
256
|
"tier": "low",
|
|
257
257
|
"qualityRank": 3
|
|
258
258
|
},
|
|
259
|
+
{
|
|
260
|
+
"match": "^deepseek/deepseek-v4\\.1-flash$",
|
|
261
|
+
"tier": "low",
|
|
262
|
+
"qualityRank": 2,
|
|
263
|
+
"$comment-deepseek": "Facts only, no recommendation: tier and rank are exactly what the generic flash catch-all below would give, kept here so the entry carries the model's own pricing. OpenRouter publishes no indices for this model yet; raise nothing here without benchmark evidence. Pricing is the off-peak rate (17 h/day); peak is $0.30 input / $1.20 output during 01–04 and 06–10 UTC Monday–Friday.",
|
|
264
|
+
"pricing": {
|
|
265
|
+
"inputUsdPerMillion": 0.15,
|
|
266
|
+
"cacheReadUsdPerMillion": 0.003,
|
|
267
|
+
"outputUsdPerMillion": 0.6
|
|
268
|
+
},
|
|
269
|
+
"pricingSource": "https://commandcode.ai/docs/resources/pricing-limits",
|
|
270
|
+
"pricingUpdatedAt": "2026-09-11"
|
|
271
|
+
},
|
|
259
272
|
{
|
|
260
273
|
"match": "(?:flash|(?:^|[/.-])mini(?:$|[/.-])|luna|free)",
|
|
261
274
|
"tier": "low",
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -5,167 +5,120 @@ description: Delegate bounded work through Bullswarm to one quota-routed coding
|
|
|
5
5
|
|
|
6
6
|
# Bullswarm
|
|
7
7
|
|
|
8
|
-
You
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
You write the task. Bullswarm picks a worker by quota and capability, runs it,
|
|
9
|
+
and saves the output. For a workflow you are the planner: write the program
|
|
10
|
+
once and the kernel runs it to the end.
|
|
11
11
|
|
|
12
12
|
Keep the user's scope and working directory. Delegate only authorized work;
|
|
13
13
|
permission to delegate does not authorize messages, releases, or other external
|
|
14
|
-
writes. If `BULLSWARM_DEPTH` is set
|
|
15
|
-
|
|
14
|
+
writes. If `BULLSWARM_DEPTH` is set you are already a worker: do the assigned
|
|
15
|
+
work directly unless it explicitly requires nested delegation.
|
|
16
16
|
|
|
17
|
-
## 1. Choose the shape
|
|
17
|
+
## 1. Choose the shape
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
workflow
|
|
21
|
-
independent acceptance.
|
|
22
|
-
|
|
19
|
+
One agent for one bounded outcome: a review, a localized fix, a study with one
|
|
20
|
+
deliverable. A workflow when the work splits into parallel territories, needs
|
|
21
|
+
integration, or needs independent acceptance. Decide from the request itself;
|
|
22
|
+
there is no classifier command.
|
|
23
23
|
|
|
24
24
|
## 2a. One agent
|
|
25
25
|
|
|
26
|
-
Dispatch it directly:
|
|
27
|
-
|
|
28
26
|
```bash
|
|
29
27
|
bullswarm run --lane=analyze --add-dir=<abs-dir> --prompt='<task>' --json
|
|
30
28
|
```
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
`pick` (the chosen `{pool, model, command}`), `outFile`, and `why`:
|
|
39
|
-
|
|
40
|
-
- `keepOnClaude: true`: do the work yourself, even if `ok` is true.
|
|
41
|
-
- Otherwise, when `ok: true`, read `outFile` and check its content before using it.
|
|
42
|
-
- `ok: false`: inspect and report the failure; a successful CLI exit is not
|
|
43
|
-
proof that the work succeeded.
|
|
44
|
-
|
|
45
|
-
Do not run `doctor` unless dispatch reports a readiness problem.
|
|
30
|
+
Lanes: `build` edits, `chore` mechanical edits, `analyze` read-only. Use
|
|
31
|
+
`--task-file` for long text. Read the result: `keepOnClaude: true` means do it
|
|
32
|
+
yourself; `ok: true` means read `outFile` and check its content before using
|
|
33
|
+
it; `ok: false` means inspect and report the failure. A clean exit code is not
|
|
34
|
+
proof of success. Do not run `doctor` unless dispatch reports a readiness
|
|
35
|
+
problem.
|
|
46
36
|
|
|
47
37
|
## 2b. A workflow
|
|
48
38
|
|
|
49
|
-
|
|
39
|
+
The program format lives in [program.md](references/program.md): fields, kinds,
|
|
40
|
+
requirement IDs, enforced rules, and one example. This section is how to
|
|
41
|
+
author the graph.
|
|
42
|
+
|
|
43
|
+
- **Decompose.** One action per bounded outcome a single worker can finish
|
|
44
|
+
alone. Every writer gets an `ownedFiles` territory. All workers share one
|
|
45
|
+
tree, so tell each to preserve others' edits and to report any file it needs
|
|
46
|
+
outside its territory instead of editing it.
|
|
47
|
+
- **Dependencies are inputs, not phases.** `dependsOn` lists the actions whose
|
|
48
|
+
outputs this action reads. Everything with no unmet dependency runs at once.
|
|
49
|
+
A phase is simply the set of actions that become ready together; never add a
|
|
50
|
+
dependency to fake one.
|
|
51
|
+
- **Integrate after parallel writers.** One `integration` action that depends
|
|
52
|
+
on all of them, directly or through a digest, with `ownedFiles: []`, which
|
|
53
|
+
on a build-lane action means no territory limit. It reads their outputs,
|
|
54
|
+
resolves shared-file requests, and runs the repository's acceptance checks.
|
|
55
|
+
It runs alone.
|
|
56
|
+
- **Check independently when acceptance matters.** One `adversarial-acceptance`
|
|
57
|
+
action with empty `affects` and `ownedFiles`, `evidenceFor` set to the
|
|
58
|
+
requirement IDs it judges, depending on every writer that affects them.
|
|
59
|
+
Describe what to inspect; the kernel supplies the evidence format. A
|
|
60
|
+
requirement may be covered by evidence alone: a "verification" deliverable
|
|
61
|
+
is the evidence report in the run result, not a file.
|
|
62
|
+
- **Digest when outputs pile up.** A `digest` action when three or more outputs
|
|
63
|
+
feed one reader, or a reader's inputs exceed about 20 KB. The reader depends
|
|
64
|
+
on the digest instead of the raw writers and gets `digestOf` links to them;
|
|
65
|
+
the digest keeps every shared-file request. Evidence never depends on a
|
|
66
|
+
digest.
|
|
67
|
+
- **Effort.** Writers are `implement`. High belongs to exactly three kinds:
|
|
68
|
+
`integration` (the sole writer after parallel work), `architecture` (a
|
|
69
|
+
read-only judgment whose report a later action consumes), and
|
|
70
|
+
`adversarial-acceptance` (independent evidence). A study that reads code and
|
|
71
|
+
writes markdown is `implement`. When a judgment must land in a file, keep it
|
|
72
|
+
`implement`, or split it into an `architecture` action plus a writer that
|
|
73
|
+
records its report. Never set `defaults.effort` to `high`, and do not
|
|
74
|
+
restate `lane` or `effort` on an action that has a `kind`.
|
|
75
|
+
- **Prompts are self-contained.** Each names the absolute workspace path
|
|
76
|
+
(nothing is substituted), the outcome, the relevant files, the dependency
|
|
77
|
+
outputs to read, and the concrete checks to run.
|
|
78
|
+
|
|
79
|
+
### Validate, read, adjust, then launch
|
|
80
|
+
|
|
81
|
+
Keep the goal in a file and pass it as `"$(cat goal.txt)"` to both commands,
|
|
82
|
+
so validate and launch get identical text, apostrophes and line breaks
|
|
83
|
+
included.
|
|
50
84
|
|
|
51
85
|
```bash
|
|
52
|
-
bullswarm workflow plan
|
|
86
|
+
bullswarm workflow plan validate "$(cat goal.txt)" --cwd=<abs-dir> --program=<abs-dir>/plan.json --json
|
|
53
87
|
```
|
|
54
88
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
Each action needs `id`, `purpose`, `dependsOn`, `affects`, `ownedFiles`,
|
|
63
|
-
`prompt`, and `evidenceFor`, plus either `kind` or an explicit `lane`. Copy
|
|
64
|
-
requirement IDs from the contract. Optional `inputs`/`produces` describe actual
|
|
65
|
-
artifacts; ordinary dependencies do not need them. Never put provider/model
|
|
66
|
-
fields into the program.
|
|
67
|
-
|
|
68
|
-
Set `kind` on every action and it fills `lane` and `effort`: `mechanical`
|
|
69
|
-
(chore/low), `io-read` (analyze/low), `digest` (analyze/low), `check`
|
|
70
|
-
(analyze/medium), `implement` (build/medium), `integration` (build/high),
|
|
71
|
-
`architecture` (analyze/high),
|
|
72
|
-
`adversarial-acceptance` (analyze/high). An explicit `lane` or `effort` still
|
|
73
|
-
wins, then the kind table, then an optional program-level `defaults` object
|
|
74
|
-
(`effort` and `reasoning` only), then the per-lane default. A kind outside that
|
|
75
|
-
list is rejected before anything runs. `plan validate` and `workflow goal` also
|
|
76
|
-
print non-blocking `advisory:` lines — `all-writers-high` and `docs-at-high` —
|
|
77
|
-
which never change acceptance or the exit code.
|
|
78
|
-
|
|
79
|
-
Author the graph around these rules:
|
|
80
|
-
|
|
81
|
-
- **Shared tree:** give each writer an intended `ownedFiles` territory. New
|
|
82
|
-
files survive; territories guide scheduling, not file rejection. Tell workers
|
|
83
|
-
others share the tree, preserve their edits, and report shared-file requests.
|
|
84
|
-
- **Real dependencies:** independent actions run concurrently. After parallel
|
|
85
|
-
writers, add a sole integrator depending on all of them, with `lane: "build"`
|
|
86
|
-
and `ownedFiles: []`. It reads their outputs, handles shared-file requests,
|
|
87
|
-
and runs repository acceptance checks. This unrestricted integrator runs alone.
|
|
88
|
-
- **Optional digest:** `kind: "digest"` condenses its dependencies' outputs into
|
|
89
|
-
one artifact so an expensive consumer reads a digest instead of many raw
|
|
90
|
-
files. It is extractive — the kernel writes the task and it quotes verbatim,
|
|
91
|
-
never judges. Add one when three or more writers feed a single integrator, or
|
|
92
|
-
when any consumer's dependency outputs exceed roughly 20 KB. It needs at least
|
|
93
|
-
one `dependsOn`, empty `evidenceFor` and empty `ownedFiles`; `affects` may be
|
|
94
|
-
empty. Never let an evidence action depend on a digest — evidence reads the
|
|
95
|
-
real artifacts, and the validator exits 2 if it does. Consumers still get a
|
|
96
|
-
`digestOf` list naming each digested source, so they can drill down.
|
|
97
|
-
- **Self-contained work:** each prompt names the exact workspace, outcome,
|
|
98
|
-
relevant files, and concrete checks. Use `medium` effort for ordinary build
|
|
99
|
-
or analysis, `low` for mechanical chores, and `high` for difficult judgment.
|
|
100
|
-
- **Optional evidence:** an independent check uses `lane: "analyze"`, empty
|
|
101
|
-
`affects`/`ownedFiles`, and `evidenceFor` requirement IDs. Depend on every
|
|
102
|
-
writer affecting those requirements. Describe the checks; the kernel adds
|
|
103
|
-
the evidence JSON instructions. Evidence is optional for graph completion.
|
|
104
|
-
- **Optional reasoning depth:** `effort` picks the model tier; the optional
|
|
105
|
-
`reasoning` field picks how hard that model thinks. Values are
|
|
106
|
-
`low|medium|high|xhigh|max`, or `default` to pass nothing and let the worker
|
|
107
|
-
CLI's own setting decide. It applies to that one action and outranks every
|
|
108
|
-
configured level for it — so a `low`-effort integrator can still get `xhigh`
|
|
109
|
-
thinking. Omit it and the configured level applies; it never changes the
|
|
110
|
-
pool, model, or effort tier, and a connector that does not accept the exact
|
|
111
|
-
level gets the nearest level it supports. Set it only when an action needs
|
|
112
|
-
deeper thinking than its tier implies (a tricky shared-file integrator,
|
|
113
|
-
ambiguous acceptance judgment) or cheaper thinking for mechanical work.
|
|
114
|
-
For the whole run instead of one action, pass
|
|
115
|
-
`--worker-reasoning <level>` (and `--planner-reasoning <level>` with
|
|
116
|
-
`--orchestrator`) to `workflow goal`; the contract's `reasoning` block
|
|
117
|
-
echoes what a launch will apply.
|
|
118
|
-
|
|
119
|
-
Validate, then launch:
|
|
89
|
+
Exit 2 means the program is invalid: the JSON lists `issues`; fix them and
|
|
90
|
+
validate again. Exit 0 always carries an `advisories` array. Each entry names
|
|
91
|
+
an action whose effort is above what its work warrants (`all-writers-high`,
|
|
92
|
+
`docs-at-high`): lower that action's kind and validate again, or write the
|
|
93
|
+
reason it needs high into its `purpose`. An empty array means launch now, with
|
|
94
|
+
the same goal, `--cwd` and absolute `--program` (validate's `next.launch` line
|
|
95
|
+
is this command):
|
|
120
96
|
|
|
121
97
|
```bash
|
|
122
|
-
bullswarm workflow
|
|
123
|
-
bullswarm workflow goal '<goal>' --cwd=<abs-dir> --program=plan.json --json
|
|
98
|
+
bullswarm workflow goal "$(cat goal.txt)" --cwd=<abs-dir> --program=<abs-dir>/plan.json --json
|
|
124
99
|
```
|
|
125
100
|
|
|
126
|
-
|
|
127
|
-
validate again. A valid launch detaches and returns `shortId`; report it.
|
|
101
|
+
The launch detaches and returns `shortId`; report it.
|
|
128
102
|
|
|
129
|
-
## 3. Observe and judge
|
|
103
|
+
## 3. Observe and judge
|
|
130
104
|
|
|
131
105
|
```bash
|
|
132
106
|
bullswarm workflow watch <shortId> --next
|
|
133
|
-
bullswarm workflow watch <shortId> --next --after <sequence> --since <iso-timestamp>
|
|
134
107
|
bullswarm workflow runs result <shortId> --json --summary
|
|
135
108
|
```
|
|
136
109
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
`
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
mechanical retry lands — even without `--verbose`. Pass `--classic` for the
|
|
153
|
-
older heartbeat-based watcher instead (V2 only; it cannot combine with
|
|
154
|
-
`--next`). A legacy authored-graph run cannot be watched: the watcher prints
|
|
155
|
-
the legacy line and exits 2.
|
|
156
|
-
`watch` also exits at a durable planning pause; that is not completion.
|
|
157
|
-
|
|
158
|
-
Read action outputs and actual artifacts, and probe important edge cases yourself.
|
|
159
|
-
`completed` means the graph succeeded; `verified` means the evidence agents
|
|
160
|
-
returned passing verdicts, which can still miss bugs. A `partial` result
|
|
161
|
-
exposes failed or skipped branches. Negative evidence remains negative and does
|
|
162
|
-
not trigger automatic gap-planning rounds. Author follow-up work explicitly
|
|
163
|
-
when the requested outcome still needs repairs.
|
|
164
|
-
|
|
165
|
-
Shared files remain after failure or cancellation. Saved older runs keep their
|
|
166
|
-
original execution behavior. Exit 0 can mean launched, paused, or completed;
|
|
167
|
-
always inspect the returned status.
|
|
168
|
-
|
|
169
|
-
Read [operations.md](references/operations.md) only when you need **steering,
|
|
170
|
-
cancellation, resume, scouting, a dispatched planner, explicit isolation,
|
|
171
|
-
routing diagnosis**. Ordinary work needs only the flow above.
|
|
110
|
+
Run `watch --next` in a background terminal. When it exits, act on the printed
|
|
111
|
+
event and relaunch with the exact `next: bullswarm workflow watch <shortId>
|
|
112
|
+
--next --after <sequence> --since <iso>` line it printed, until the outcome
|
|
113
|
+
line reports a pause or a terminal status. A pause is not completion.
|
|
114
|
+
|
|
115
|
+
Then read the real outputs and artifacts and probe the important edge cases
|
|
116
|
+
yourself. `completed` means the graph ran. `verified` means evidence passed,
|
|
117
|
+
which can still miss bugs. `partial` exposes failed or skipped branches; author
|
|
118
|
+
follow-up work explicitly when the outcome still needs repair. Shared files
|
|
119
|
+
remain after failure or cancellation. Exit 0 can mean launched, paused, or
|
|
120
|
+
completed, so always inspect the returned status.
|
|
121
|
+
|
|
122
|
+
[operations.md](references/operations.md) covers steering, cancellation,
|
|
123
|
+
resume, scouting, a dispatched planner, isolation, watch flags, reasoning
|
|
124
|
+
depth, digest details, the live planning contract, and routing diagnosis.
|
|
@@ -91,6 +91,20 @@ commands fail closed with their short ID and retained run directory.
|
|
|
91
91
|
|
|
92
92
|
## Program actions: `kind`, `defaults`, and advisories
|
|
93
93
|
|
|
94
|
+
The program format itself — fields, kinds, requirement IDs, enforced rules
|
|
95
|
+
and an example — is in [program.md](program.md). The same rules are also served
|
|
96
|
+
live by the running kernel:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
bullswarm workflow plan contract '<goal>' --cwd=<abs-dir> --json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
That contract carries the goal's derived requirement IDs, the exact validate
|
|
103
|
+
and launch commands with goal and `--cwd` filled in, and any run-wide
|
|
104
|
+
`reasoning` override. It is the brief a dispatched planner receives, and the
|
|
105
|
+
fallback for a caller whose `plan validate` rejects field names or kinds after
|
|
106
|
+
an upgrade.
|
|
107
|
+
|
|
94
108
|
An action's `kind` names what the work IS and derives its `lane` and `effort`,
|
|
95
109
|
so a program states the nature once instead of re-deciding two routing fields:
|
|
96
110
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Workflow program format
|
|
2
|
+
|
|
3
|
+
`plan.json` is the program that `bullswarm workflow goal` executes. Before
|
|
4
|
+
launch, `bullswarm workflow plan validate` checks it against the running
|
|
5
|
+
kernel. Exit 2 returns `issues` and a `next` block; fix the issues yourself.
|
|
6
|
+
Exit 0 returns the resolved program and an `advisories` array. This file
|
|
7
|
+
ships with the kernel it describes; fetch the live contract only when an issue
|
|
8
|
+
names an unknown field, kind, or `schemaVersion`, which can only happen after
|
|
9
|
+
an upgrade this file has not followed:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bullswarm workflow plan contract '<goal>' --cwd=<abs-dir> --json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Program
|
|
16
|
+
|
|
17
|
+
| field | required | value |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `schemaVersion` | yes | exactly `bullswarm.workflow.program.v2` |
|
|
20
|
+
| `actions` | yes | non-empty array of actions |
|
|
21
|
+
| `defaults` | no | object with only `effort` (`high`, `medium`, `low`) and `reasoning` (`low`, `medium`, `high`, `xhigh`, `max`, `default`); applies where neither the action nor its kind sets the field |
|
|
22
|
+
|
|
23
|
+
No other top-level field is accepted.
|
|
24
|
+
|
|
25
|
+
## Action
|
|
26
|
+
|
|
27
|
+
| field | required | value |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| `id` | yes | kebab-case, unique in the program |
|
|
30
|
+
| `purpose` | yes | one line: what this action delivers |
|
|
31
|
+
| `dependsOn` | yes | ids of the actions whose outputs this one reads; `[]` if none |
|
|
32
|
+
| `affects` | yes | requirement IDs this action's work contributes to; an action with `ownedFiles` must list at least one |
|
|
33
|
+
| `ownedFiles` | yes | repo-relative paths this action may edit; `[]` on a build-lane action means no territory limit (the integrator); analyze-lane actions edit nothing |
|
|
34
|
+
| `prompt` | yes | the self-contained task text with the absolute workspace path written in (nothing is substituted; `<cwd>` in the example is a placeholder); for a `digest`, one line of focus appended to the kernel-written task |
|
|
35
|
+
| `evidenceFor` | yes | requirement IDs this action judges; `[]` unless it is evidence |
|
|
36
|
+
| `kind` | kind or lane | one of the kinds below |
|
|
37
|
+
| `lane` | kind or lane | `analyze` (read-only), `build` (edits), `chore` (mechanical edits); only when there is no kind |
|
|
38
|
+
| `effort` | no | `high`, `medium`, `low`; overrides the kind's effort |
|
|
39
|
+
| `reasoning` | no | `low`, `medium`, `high`, `xhigh`, `max`, `default`; how hard the picked model thinks, outranks every configured level |
|
|
40
|
+
| `inputs`, `produces` | no | artifact IDs, kebab-case: the producer lists an ID in `produces`, its consumer in `inputs`; omit for ordinary dependencies |
|
|
41
|
+
|
|
42
|
+
Any other field is rejected. Resolution per field: the action's own `lane` or
|
|
43
|
+
`effort`, then the kind table, then `defaults`, then the lane's default.
|
|
44
|
+
|
|
45
|
+
## Kinds
|
|
46
|
+
|
|
47
|
+
| kind | lane | effort | use for |
|
|
48
|
+
|---|---|---|---|
|
|
49
|
+
| `mechanical` | chore | low | renames, formatting, generated edits |
|
|
50
|
+
| `io-read` | analyze | low | fetch or read something and report it |
|
|
51
|
+
| `digest` | analyze | low | condense dependency outputs verbatim; the kernel writes its task |
|
|
52
|
+
| `check` | analyze | medium | a read-only inspection with a report |
|
|
53
|
+
| `implement` | build | medium | ordinary edits and writing, including docs written from code study |
|
|
54
|
+
| `integration` | build | high | the sole writer after parallel writers; `ownedFiles: []` |
|
|
55
|
+
| `architecture` | analyze | high | a read-only cross-cutting judgment; its report feeds a later action |
|
|
56
|
+
| `adversarial-acceptance` | analyze | high | independent evidence; empty `affects` and `ownedFiles`, `evidenceFor` set |
|
|
57
|
+
|
|
58
|
+
An analyze-lane action edits nothing; its deliverable is the report a
|
|
59
|
+
dependent reads.
|
|
60
|
+
|
|
61
|
+
## Requirement IDs
|
|
62
|
+
|
|
63
|
+
The kernel derives requirements from the goal text. Each numbered item, `1.`
|
|
64
|
+
or `1)` at the start of a line or inline in one line counting from 1, becomes
|
|
65
|
+
`requirement-N` in order. A goal with no numbered items is one
|
|
66
|
+
`requirement-1`. Number distinct deliverables in the goal to get one verdict
|
|
67
|
+
each, and use exactly the same goal text for validate and launch.
|
|
68
|
+
|
|
69
|
+
## Enforced rules
|
|
70
|
+
|
|
71
|
+
- A goal that starts with `read-only`, or says repository files must not be
|
|
72
|
+
modified, forbids mutation: every `ownedFiles` must be `[]`.
|
|
73
|
+
- A `digest` needs at least one `dependsOn`, empty `evidenceFor`, empty
|
|
74
|
+
`ownedFiles`, and no evidence action may list it in `dependsOn`. Only the
|
|
75
|
+
direct dependency is checked; evidence may depend on an action that itself
|
|
76
|
+
read a digest.
|
|
77
|
+
- A requirement needs no writer: coverage by `evidenceFor` alone is accepted,
|
|
78
|
+
and evidence itself is optional.
|
|
79
|
+
- An evidence action's prompt describes what to inspect only. A directive such
|
|
80
|
+
as "return only JSON" is rejected; the kernel owns the evidence format.
|
|
81
|
+
- A kind outside the table, a lane outside `analyze|build|chore`, or an effort
|
|
82
|
+
outside `high|medium|low` exits 2 before anything runs.
|
|
83
|
+
|
|
84
|
+
## Example
|
|
85
|
+
|
|
86
|
+
Goal: `1. Add --since to runs list. 2. Document it in README.`
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"schemaVersion": "bullswarm.workflow.program.v2",
|
|
91
|
+
"actions": [
|
|
92
|
+
{
|
|
93
|
+
"id": "since-flag",
|
|
94
|
+
"kind": "implement",
|
|
95
|
+
"purpose": "Add --since to runs list with a unit test",
|
|
96
|
+
"dependsOn": [],
|
|
97
|
+
"affects": ["requirement-1"],
|
|
98
|
+
"ownedFiles": ["src/workflow/runs-cli.js", "tests/runs-list.test.js"],
|
|
99
|
+
"evidenceFor": [],
|
|
100
|
+
"prompt": "In <cwd>, add a --since <time> flag to `bullswarm workflow runs list` in src/workflow/runs-cli.js with a unit test in tests/runs-list.test.js. Others share this tree: preserve their edits and report any file you need outside your territory. Run `npm test` and quote the summary line."
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"id": "readme",
|
|
104
|
+
"kind": "implement",
|
|
105
|
+
"purpose": "Document --since in README",
|
|
106
|
+
"dependsOn": [],
|
|
107
|
+
"affects": ["requirement-2"],
|
|
108
|
+
"ownedFiles": ["README.md"],
|
|
109
|
+
"evidenceFor": [],
|
|
110
|
+
"prompt": "In <cwd>, document the --since <time> flag of `bullswarm workflow runs list` in the runs section of README.md, matching the style of the neighbouring flags. Edit README.md only."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"id": "integrate",
|
|
114
|
+
"kind": "integration",
|
|
115
|
+
"purpose": "Reconcile both edits and run the full suite",
|
|
116
|
+
"dependsOn": ["since-flag", "readme"],
|
|
117
|
+
"affects": ["requirement-1", "requirement-2"],
|
|
118
|
+
"ownedFiles": [],
|
|
119
|
+
"evidenceFor": [],
|
|
120
|
+
"prompt": "In <cwd>, read both dependency outputs, resolve any shared-file requests they raised, make the README wording match the flag as implemented, run `npm test`, and quote the summary line."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "verify",
|
|
124
|
+
"kind": "adversarial-acceptance",
|
|
125
|
+
"purpose": "Independently confirm the flag works and is documented",
|
|
126
|
+
"dependsOn": ["since-flag", "readme", "integrate"],
|
|
127
|
+
"affects": [],
|
|
128
|
+
"ownedFiles": [],
|
|
129
|
+
"evidenceFor": ["requirement-1", "requirement-2"],
|
|
130
|
+
"prompt": "In <cwd>, exercise `bullswarm workflow runs list --since <time> --json` against a fixture home with runs on both sides of the bound, and check that README.md describes the flag and its accepted time forms. Inspect only; try to break it."
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
```
|
package/src/setup.js
CHANGED
|
@@ -269,6 +269,34 @@ export function upgradeConnectorMetadata(bullswarmDir, {
|
|
|
269
269
|
changed = true;
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
|
+
// A packaged profile the installed connector has never seen (keyed by
|
|
273
|
+
// its `match` pattern or `id`) is inserted where the packaged order puts
|
|
274
|
+
// it: right before the first installed entry that comes later in the
|
|
275
|
+
// packaged list, else at the end. So a new specific entry lands ahead of
|
|
276
|
+
// the packaged generic catch-all it was written to precede, but never
|
|
277
|
+
// ahead of a profile the operator authored themselves. Entries the
|
|
278
|
+
// installed connector already holds, edited or not, are never touched;
|
|
279
|
+
// recommendation guards were handled above.
|
|
280
|
+
if (Array.isArray(installed.modelProfiles) && Array.isArray(packaged.modelProfiles)) {
|
|
281
|
+
const keyOf = (profile) => (profile?.match != null ? `match:${profile.match}`
|
|
282
|
+
: profile?.id != null ? `id:${profile.id}` : null);
|
|
283
|
+
// Guards are prepended by policy above, so they never anchor order.
|
|
284
|
+
const packagedIndex = new Map(packaged.modelProfiles
|
|
285
|
+
.map((profile, index) => [keyOf(profile), index])
|
|
286
|
+
.filter(([key], index) => key != null && typeof packaged.modelProfiles[index].autoRecommend !== 'boolean'));
|
|
287
|
+
packaged.modelProfiles.forEach((profile, index) => {
|
|
288
|
+
const key = keyOf(profile);
|
|
289
|
+
if (key == null || typeof profile.autoRecommend === 'boolean') return;
|
|
290
|
+
if (installed.modelProfiles.some((entry) => keyOf(entry) === key)) return;
|
|
291
|
+
let at = installed.modelProfiles.length;
|
|
292
|
+
for (let j = 0; j < installed.modelProfiles.length; j += 1) {
|
|
293
|
+
const laterInPackage = packagedIndex.get(keyOf(installed.modelProfiles[j]));
|
|
294
|
+
if (laterInPackage != null && laterInPackage > index) { at = j; break; }
|
|
295
|
+
}
|
|
296
|
+
installed.modelProfiles.splice(at, 0, profile);
|
|
297
|
+
changed = true;
|
|
298
|
+
});
|
|
299
|
+
}
|
|
272
300
|
if (changed) {
|
|
273
301
|
writeFileSync(dst, `${JSON.stringify(installed, null, 2)}\n`);
|
|
274
302
|
upgraded.push(f);
|